Btrfs: fix race in check-integrity caused by usage of bitfield
[firefly-linux-kernel-4.4.55.git] / fs / btrfs / backref.c
index 208d8aa5b07e488f1f39cb0877ff46bb5d08d5a6..04edf69be87561318375716abeb1d854370c63c3 100644 (file)
@@ -461,6 +461,7 @@ static int __merge_refs(struct list_head *head, int mode)
                     pos2 = n2, n2 = pos2->next) {
                        struct __prelim_ref *ref2;
                        struct __prelim_ref *xchg;
+                       struct extent_inode_elem *eie;
 
                        ref2 = list_entry(pos2, struct __prelim_ref, list);
 
@@ -472,12 +473,20 @@ static int __merge_refs(struct list_head *head, int mode)
                                        ref1 = ref2;
                                        ref2 = xchg;
                                }
-                               ref1->count += ref2->count;
                        } else {
                                if (ref1->parent != ref2->parent)
                                        continue;
-                               ref1->count += ref2->count;
                        }
+
+                       eie = ref1->inode_list;
+                       while (eie && eie->next)
+                               eie = eie->next;
+                       if (eie)
+                               eie->next = ref2->inode_list;
+                       else
+                               ref1->inode_list = ref2->inode_list;
+                       ref1->count += ref2->count;
+
                        list_del(&ref2->list);
                        kfree(ref2);
                }
@@ -890,8 +899,7 @@ again:
        while (!list_empty(&prefs)) {
                ref = list_first_entry(&prefs, struct __prelim_ref, list);
                list_del(&ref->list);
-               if (ref->count < 0)
-                       WARN_ON(1);
+               WARN_ON(ref->count < 0);
                if (ref->count && ref->root_id && ref->parent == 0) {
                        /* no parent == root of tree */
                        ret = ulist_add(roots, ref->root_id, 0, GFP_NOFS);