]> git.neil.brown.name Git - LaFS.git/commitdiff
modify: avoid breaking an PrimaryRef chain
authorNeilBrown <neilb@suse.de>
Fri, 18 Jun 2010 11:29:20 +0000 (21:29 +1000)
committerNeilBrown <neilb@suse.de>
Fri, 18 Jun 2010 11:29:20 +0000 (21:29 +1000)
When we insert a new block into a PrimaryRef chain, we need to take
the new refcnt on the new block (which is now primary for the
following block) rather than than the block from which we split (on
which a primary_ref is already held).

Signed-off-by: NeilBrown <neilb@suse.de>
modify.c

index 648e57b620cd19d83386d532e23be736acaa79b1..71d6c3f9358d29051ac83879d0a93161a42199cb 100644 (file)
--- a/modify.c
+++ b/modify.c
@@ -1400,9 +1400,15 @@ static int do_incorporate_leaf(struct fs *fs, struct indexblock *ib,
        spin_unlock(&fs->lock);
 
        new->depth = ib->depth;
-       list_add(&new->b.siblings, &ib->b.siblings);
-       getiref(ib, MKREF(primary));
+       if (ib->b.siblings.next != &ib->b.parent->children &&
+           test_bit(B_PrimaryRef, &list_entry(ib->b.siblings.next,
+                                              struct block, siblings)->flags))
+               /* Inserting into a PrimaryRef chain */
+               getiref(new, MKREF(primary));
+       else
+               getiref(ib, MKREF(primary));
        set_bit(B_PrimaryRef, &new->b.flags);
+       list_add(&new->b.siblings, &ib->b.siblings);
        new->b.parent = ib->b.parent;
        (void)getiref(new->b.parent, MKREF(child));
        new->b.inode = ib->b.inode;
@@ -1537,9 +1543,15 @@ static int do_incorporate_internal(struct fs *fs, struct indexblock *ib,
        spin_unlock(&fs->lock);
 
        new->depth = ib->depth;
-       list_add(&new->b.siblings, &ib->b.siblings);
-       getiref(ib, MKREF(primary));
+       if (ib->b.siblings.next != &ib->b.parent->children &&
+           test_bit(B_PrimaryRef, &list_entry(ib->b.siblings.next,
+                                              struct block, siblings)->flags))
+               /* Inserting into a PrimaryRef chain */
+               getiref(new, MKREF(primary));
+       else
+               getiref(ib, MKREF(primary));
        set_bit(B_PrimaryRef, &new->b.flags);
+       list_add(&new->b.siblings, &ib->b.siblings);
        new->b.parent = ib->b.parent;
        (void)getiref(new->b.parent, MKREF(child));
        new->b.inode = ib->b.inode;