]> git.neil.brown.name Git - LaFS.git/commitdiff
Better handling of upward recursive empty index deletion.
authorNeilBrown <neilb@suse.de>
Sun, 13 Jun 2010 07:51:00 +0000 (17:51 +1000)
committerNeilBrown <neilb@suse.de>
Sun, 13 Jun 2010 07:57:46 +0000 (17:57 +1000)
When an empty index blocks makes the parent empty, we recurse
up.
When we do that, we need to again perform the check for there
being children, and for this being an InoIdx block.
So jump further back, and tidy up the exit path to ensure we still
unlock properly.

This makes the extra check for InoIdx pointless.

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

index ace2d267d422c8f2ff69b1fc4719117375417cb3..89745f5f43b20fc98fdb69b541e2f69dd6b98c0d 100644 (file)
--- a/modify.c
+++ b/modify.c
@@ -1687,7 +1687,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, *nxt;
+       struct indexblock *new = NULL, *orig_ib, *locked_ib, *nxt;
        struct block *uninc = NULL;
        int rv = 0;
        u32 next;
@@ -1914,6 +1914,9 @@ void lafs_incorporate(struct fs *fs, struct indexblock *ib)
         * first block in the parent, we need to recurse up and
         * resolve the parent in the same way.
         */
+       orig_ib = ib;
+       locked_ib = ib;
+ recurse:
        if (!list_empty(&ib->children))
                /* If there are children, we cannot treat this block as empty. */
                return;
@@ -1930,15 +1933,13 @@ void lafs_incorporate(struct fs *fs, struct indexblock *ib)
                /* Don't need to dirty the inode - the fact that we just
                 * did incorporation should ensure it is already dirty
                 */
-               return;
+               goto out2;
        }
        if (ib->depth > 1 && ! lafs_index_empty(ib))
-               return;
+               goto out2;
        if (ib->depth == 1 && lafs_leaf_next(ib, 0) != 0xFFFFFFFF)
-               return;
+               goto out2;
 
-       orig_ib = ib;
- recurse:
        /* OK, it is empty now.  There are various ways we can handle
         * this.  All involve modification of the parent in some way,
         * so we need to get a lock on said parent.
@@ -1957,6 +1958,7 @@ void lafs_incorporate(struct fs *fs, struct indexblock *ib)
         */
        lafs_iounlock_block(&ib->b);
        lafs_iolock_block(&ib->b.parent->b);
+       locked_ib = ib->b.parent;
        /* Now anything looking for an address that could be in ib will
         * block on the parent first, so we don't need i_alloc_sem
         * any more.
@@ -2013,8 +2015,7 @@ void lafs_incorporate(struct fs *fs, struct indexblock *ib)
                 * Need to check for block in cache and re-address
                 */
                readdress_index(ib->b.inode, next, ib->depth, ib->b.fileaddr);
-       } else if (ib->b.parent->b.fileaddr == ib->b.fileaddr &&
-                  !test_bit(B_InoIdx, &ib->b.parent->b.flags)) {
+       } else if (ib->b.parent->b.fileaddr == ib->b.fileaddr) {
                /* The parent has just become empty and needs to be 
                 * removed from it's parent.
                 */
@@ -2025,8 +2026,11 @@ void lafs_incorporate(struct fs *fs, struct indexblock *ib)
         * which is a descendent.
         * Need to return with iolock on orig_ib.
         */
-       lafs_iolock_block(&orig_ib->b);
-       lafs_iounlock_block(&ib->b.parent->b);
+out2:
+       if (locked_ib != orig_ib) {
+               lafs_iolock_block(&orig_ib->b);
+               lafs_iounlock_block(&locked_ib->b);
+       }
 }
 
 /***************************************************************