From 1f21ae190baad7233c6d7a16c72d29b55f7655df Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 18 Jun 2010 21:29:20 +1000 Subject: [PATCH] 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 --- modify.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) 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; -- 2.39.5