]> git.neil.brown.name Git - LaFS.git/commitdiff
incorporate: don't remove children prematurely.
authorNeilBrown <neilb@suse.de>
Mon, 21 Jun 2010 00:56:28 +0000 (10:56 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 21 Jun 2010 00:56:28 +0000 (10:56 +1000)
We cannot just remove a child.  So to get it out of the PrimaryRef
chain, move it to the end of the child list.

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

index 4e9e09721bc06d7f65634b9f9a25a5e42ab0234f..cba3eac86968b8f367095abb42c4948a174f81cc 100644 (file)
--- a/modify.c
+++ b/modify.c
@@ -1686,7 +1686,7 @@ static void readdress_index(struct inode *ino, u32 addr, int depth,
 void lafs_incorporate(struct fs *fs, struct indexblock *ib)
 {
        int offset;     /* start of block where indexing is */
-       struct indexblock *new = NULL, *orig_ib, *locked_ib, *nxt;
+       struct indexblock *new = NULL, *orig_ib, *locked_ib, *nxt, *prv;
        struct block *uninc = NULL, **bp;
        int rv = 0;
        u32 next;
@@ -2019,38 +2019,38 @@ void lafs_incorporate(struct fs *fs, struct indexblock *ib)
        nxt = NULL;
        if (ib->b.siblings.next != &ib->b.parent->children)
                nxt = list_entry(ib->b.siblings.next, struct indexblock, b.siblings);
+       prv = NULL;
+       if (ib->b.siblings.prev != &ib->b.parent->children)
+               prv = list_entry(ib->b.siblings.prev, struct indexblock, b.siblings);
+       /* we don't need to move to the inode->free_index list as that will
+        * happen when refile drops the ->parent link.
+        * If we completely remove from the list, refile will get confused in
+        * consistency checks.   So just move to the end of the list
+        * to avoid confusing PrimaryRef chains.
+        */
+       list_move_tail(&ib->b.siblings, &ib->b.parent->children);
        lafs_unhash_iblock(ib);
        if (test_and_clear_bit(B_PrimaryRef, &ib->b.flags)) {
-               int cr = 0;
                /* This was not incorporated yet, revert the uninc status */
                if (nxt && test_bit(B_PrimaryRef, &nxt->b.flags)) {
                        /* I was in a PrimaryRef chain */
                        putiref(ib, MKREF(primary));
                } else {
-                       struct indexblock *prev = list_entry(ib->b.siblings.prev,
-                                                            struct indexblock,
-                                                            b.siblings);
-                       putiref(prev, MKREF(primary));
+                       LAFS_BUG(!prv, &ib->b);
+                       putiref(prv, MKREF(primary));
                }
-               list_del_init(&ib->b.siblings);
-               clear_bit(B_Uninc, &ib->b.flags);
-               if (test_and_clear_bit(B_Dirty, &ib->b.flags))
-                       cr++;
-               if (test_and_clear_bit(B_UnincCredit, &ib->b.flags))
-                       cr++;
-               lafs_space_return(fs, cr);
        } else if (nxt && test_bit(B_PrimaryRef, &nxt->b.flags)) {
                /* Next block is not incorporated yet, so simply re-address
                 * it to replace this block.
                 */
+               clear_bit(B_PrimaryRef, &nxt->b.flags);
+               putiref(ib, MKREF(primary));
                readdress_index(ib->b.inode, nxt->b.fileaddr, nxt->depth,
                                ib->b.fileaddr);
                if (test_bit(B_PhysValid, &nxt->b.flags)) {
                        LAFS_BUG(nxt->b.physaddr == 0, &nxt->b);
                        update_index(ib->b.parent, ib->b.fileaddr, nxt->b.physaddr);
                }
-               clear_bit(B_PrimaryRef, &nxt->b.flags);
-               putiref(ib, MKREF(primary));
        } else if ((next = update_index(ib->b.parent, ib->b.fileaddr, 0)) != 0) {
                /* Found a 'next' block in the parent and have updated the parent.
                 * Need to check for block in cache and re-address