]> git.neil.brown.name Git - LaFS.git/commitdiff
Remove incorrect assumption from erase_dblock
authorNeilBrown <neilb@suse.de>
Wed, 2 Sep 2009 00:55:07 +0000 (10:55 +1000)
committerNeilBrown <neilb@suse.de>
Wed, 2 Sep 2009 00:55:07 +0000 (10:55 +1000)
When erasing a pinned dblock, it might not be on the leaf list.
The fact that we have it locked can mean that it wasn't put there
yet.
So check leaf list membership explicitly.

Note that it cannot be in write-back, as we should have
waited for any writeback to finish, and won't have started any.

block.c

diff --git a/block.c b/block.c
index 8d081fc0d7426671c04850c45e0dbf8b4278612a..19e1651c9b067c64c21591032de1f032080bf0b3 100644 (file)
--- a/block.c
+++ b/block.c
@@ -539,13 +539,16 @@ lafs_erase_dblock(struct datablock *b)
 
        spin_lock(&fs->lock);
        if (test_bit(B_Pinned, &b->b.flags)) {
-               /* Erasing a Pinned datablock should only happen when it is
-                * on a 'leaf' list.  If it is not, because there are children
-                * (i.e. an InoIdx block) still pinned, then it should be erased
-                * first.
+               /* When erasing a pinned dblock it will usually be on a
+                * leaf list, so we must remove it.
+                * However it is IOLocked so it might not be on the leaf list.
                 */
-               LAFS_BUG(list_empty(&b->b.lru), &b->b);
-               list_del_init(&b->b.lru);
+               int onlru = 0;
+               LAFS_BUG(test_bit(B_Writeback, &b->b.flags), &b->b);
+               if (!list_empty(&b->b.lru)) {
+                       onlru = 1;
+                       list_del_init(&b->b.lru);
+               }
                if (!test_bit(B_Root, &b->b.flags))
                        atomic_dec(&b->b.parent->pincnt
                                   [!!test_bit(B_Phase1, &b->b.flags)]);
@@ -553,7 +556,8 @@ lafs_erase_dblock(struct datablock *b)
                spin_unlock(&fs->lock);
                if (!test_bit(B_Root, &b->b.flags))
                        lafs_refile(&b->b.parent->b, 0);
-               putiref(b, MKREF(leaf));
+               if (onlru)
+                       putiref(b, MKREF(leaf));
        } else
                spin_unlock(&fs->lock);