]> git.neil.brown.name Git - LaFS.git/commitdiff
cleaner: don't iput while still holding a ref to a block.
authorNeilBrown <neilb@suse.de>
Wed, 28 Jul 2010 11:21:09 +0000 (21:21 +1000)
committerNeilBrown <neilb@suse.de>
Mon, 9 Aug 2010 01:58:12 +0000 (11:58 +1000)
As the block->inode ref isn't counted, this isn't really safe.
The inode could disappear and the block might not get killed
when the address-space is truncated.

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

diff --git a/clean.c b/clean.c
index 909874862855e5595dc1b477ef491e3e2f55580e..fefe18edefdf0d8277a59b8a39a247831e3e3b0a 100644 (file)
--- a/clean.c
+++ b/clean.c
@@ -465,9 +465,9 @@ static int try_clean(struct fs *fs, struct toclean *tc)
                            (LAFSI(ino)->type >= TypeBase &&
                             ((loff_t)bnum << ino->i_blkbits)
                             >= i_size_read(ino))) {
-                               iput(ino);
                                list_del_init(&b->cleaning);
                                putdref(b, MKREF(cleaning));
+                               iput(ino);
                        }
                        putdref(b, MKREF(cleaning));
                }
@@ -491,8 +491,9 @@ static int try_clean(struct fs *fs, struct toclean *tc)
                if (err) {
                        /* Eeek, what do I do?? */
                        list_del_init(&b->cleaning);
-                       iput(b->b.inode);
+                       ino = b->b.inode;
                        putdref(b, MKREF(cleaning));
+                       iput(ino);
                        continue;
                }
                cb = first_in_seg(&b->b, fs, tc->dev, tc->seg, MKREF(clean2));
@@ -501,16 +502,18 @@ static int try_clean(struct fs *fs, struct toclean *tc)
                        /* Moved, don't want this. */
                        dprintk("Not in seg\n");
                        list_del_init(&b->cleaning);
-                       iput(b->b.inode);
+                       ino = b->b.inode;
                        putdref(b, MKREF(cleaning));
+                       iput(ino);
                        continue;
                }
                err = lafs_load_block(cb, NULL);
                if (err) {
                        list_del_init(&b->cleaning);
-                       iput(b->b.inode);
+                       ino = b->b.inode;
                        putdref(b, MKREF(cleaning));
                        putref(cb, MKREF(clean2));
+                       iput(ino);
                        continue;
                }
                err = lafs_wait_block_async(cb);
@@ -521,9 +524,10 @@ static int try_clean(struct fs *fs, struct toclean *tc)
 
                if (err) {
                        list_del_init(&b->cleaning);
-                       iput(b->b.inode);
+                       ino = b->b.inode;
                        putref(cb, MKREF(clean2));
                        putdref(b, MKREF(cleaning));
+                       iput(ino);
                        continue;
                }
 
@@ -536,9 +540,10 @@ static int try_clean(struct fs *fs, struct toclean *tc)
                 * ref now
                 */
                list_del_init(&b->cleaning);
-               iput(b->b.inode);
+               ino = b->b.inode;
                putdref(b, MKREF(cleaning));
                putref(cb, MKREF(clean2));
+               iput(ino);
                rv = -1;
                if (err)
                        goto out;