]> git.neil.brown.name Git - LaFS.git/commitdiff
Add proper locking to inode_handle_orphan
authorNeilBrown <neilb@suse.de>
Sat, 2 Oct 2010 00:59:32 +0000 (10:59 +1000)
committerNeilBrown <neilb@suse.de>
Sat, 2 Oct 2010 04:42:00 +0000 (14:42 +1000)
When walking the indexblock looking for things to purge
we need to hold the inode private_lock.

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

diff --git a/inode.c b/inode.c
index 88c76d1d221c628c031d5fba5ab4d49c2bbbf0a5..c70a934553dfc47ef6c91394ef0b0c78ff58f891 100644 (file)
--- a/inode.c
+++ b/inode.c
@@ -860,10 +860,7 @@ int lafs_inode_handle_orphan(struct datablock *b)
                        err = -EBUSY; /* Try again after the checkpoint */
                        goto out2;
                }
-               /* FIXME I need some sort of lock to safely walk
-                * down this list */
 
-               ib2 = ib;
                lastaddr = (i_size_read(ino) +
                            fs->blocksize - 1)
                        >> fs->blocksize_bits;
@@ -874,7 +871,8 @@ int lafs_inode_handle_orphan(struct datablock *b)
                 * If there are none, descend the last block that
                 * is not after EOF and look at its children.
                 */
-               next = ib;
+               ib2 = next = ib;
+               spin_lock(&ib->b.inode->i_data.private_lock);
                while (next) {
                        ib2 = next;
                        next = NULL;
@@ -889,6 +887,7 @@ int lafs_inode_handle_orphan(struct datablock *b)
                }
                if (ib2->b.fileaddr < lastaddr) {
                        /* Must be all done */
+                       spin_unlock(&ib->b.inode->i_data.private_lock);
                        clear_bit(I_Trunc, &LAFSI(ino)->iflags);
                        if (!test_bit(I_Deleting, &LAFSI(ino)->iflags))
                                iput(ino);
@@ -897,6 +896,7 @@ int lafs_inode_handle_orphan(struct datablock *b)
                        goto out2;
                }
                getiref(ib2, MKREF(inode_handle_orphan2));
+               spin_unlock(&ib->b.inode->i_data.private_lock);
 
                /* ib2 is an index block beyond EOF with no
                 * Pinned children.