From: NeilBrown Date: Fri, 18 Jun 2010 11:29:20 +0000 (+1000) Subject: modify: avoid breaking an PrimaryRef chain X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=1f21ae190baad7233c6d7a16c72d29b55f7655df;p=LaFS.git modify: avoid breaking an PrimaryRef chain 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 --- diff --git a/modify.c b/modify.c index 648e57b..71d6c3f 100644 --- 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;