]> git.neil.brown.name Git - LaFS.git/commitdiff
cleaner: when erasing a datablock, cancel any pending cleaning.
authorNeilBrown <neilb@suse.de>
Fri, 18 Jun 2010 12:32:29 +0000 (22:32 +1000)
committerNeilBrown <neilb@suse.de>
Fri, 18 Jun 2010 12:32:29 +0000 (22:32 +1000)
This requires a bit of locking, but ensure that after erase_dblock,
the block is no longer in use, so truncate orphan handling doesn't
find children that it doesn't expect.

Signed-off-by: NeilBrown <neilb@suse.de>
block.c
clean.c
lafs.h
state.h
super.c

diff --git a/block.c b/block.c
index 8139c254b0ee449b3ee91b2b0e877050f7342479..5e150f8015db0de48582ce7d661eed2c92df20eb 100644 (file)
--- a/block.c
+++ b/block.c
@@ -529,6 +529,7 @@ lafs_erase_dblock(struct datablock *b)
                         &b->b);
 
        clear_bit(B_Valid, &b->b.flags);
+       lafs_unclean(b);
        if (test_and_clear_bit(B_Dirty, &b->b.flags))
                lafs_space_return(fs, 1);
        if (test_and_clear_bit(B_Realloc, &b->b.flags))
diff --git a/clean.c b/clean.c
index 702d00ad7ae6f1b167ea8d917ce38d2e98a5b46f..b935c30046bfc02f6ef2bb84a0dcffb4fbd92376 100644 (file)
--- a/clean.c
+++ b/clean.c
@@ -264,7 +264,9 @@ static int try_clean(struct fs *fs, struct toclean *tc)
        u32 inum, fsnum;
        struct inode *ino = NULL;
        struct datablock *b, *tmp;
+       int rv = 0;
 
+       mutex_lock(&fs->cleaner.lock);
        dprintk("try_clean: state = %d\n", tc->ac.state);
        if (tc->ch == NULL && tc->ss) {
                /* Need to read in the cluster header */
@@ -275,15 +277,17 @@ static int try_clean(struct fs *fs, struct toclean *tc)
                                            fs->prime_sb->s_blocksize),
                                           &tc->ac);
 
+               rv = 0;
                if (err == -EAGAIN)
-                       return 0;
+                       goto out;
                if (err == -EIO) {
                        //printk("CLEANER got IO error !!\n");
                        // FIXME adjust youth to so as not to touch this again
                bad_header:
                        tc->ac.state = 0;
                        tc->ss = 0;
-                       return 0;
+                       rv = 0;
+                       goto out;
                }
                BUG_ON(err);
                // FIXME check checksum of the cluster_header
@@ -472,11 +476,31 @@ static int try_clean(struct fs *fs, struct toclean *tc)
                iput(b->b.inode);
                putdref(b, MKREF(cleaning));
                putref(cb, MKREF(clean2));
+               rv = -1;
                if (err)
-                       return -1;
+                       goto out;
        }
-       return tc->ch == NULL && tc->ss == 0 &&
+       rv = tc->ch == NULL && tc->ss == 0 &&
                list_empty(&tc->cleaning);
+out:
+       mutex_unlock(&fs->cleaner.lock);
+       return rv;
+}
+
+void lafs_unclean(struct datablock *db)
+{
+       if (!list_empty_careful(&db->cleaning)) {
+               struct fs *fs = fs_from_inode(db->b.inode);
+               mutex_lock(&fs->cleaner.lock);
+               if (!list_empty(&db->cleaning)) {
+                       list_del_init(&db->cleaning);
+                       putdref(db, MKREF(cleaning));
+                       iput(db->b.inode);
+                       if (test_and_clear_bit(B_Async, &db->b.flags))
+                               putdref(db, MKREF(async));
+               }
+               mutex_unlock(&fs->cleaner.lock);
+       }
 }
 
 static unsigned long do_clean(struct fs *fs)
diff --git a/lafs.h b/lafs.h
index 580025d9fc1a10f5b0543c692b15f05c4b0bc5e3..39faeeb0b5982d2b5620a60ec6658b899c88b4a8 100644 (file)
--- a/lafs.h
+++ b/lafs.h
@@ -625,6 +625,7 @@ unsigned long lafs_scan_seg(struct fs *fs);
 int lafs_start_cleaner(struct fs *fs);
 void lafs_stop_cleaner(struct fs *fs);
 void lafs_wake_cleaner(struct fs *fs);
+void lafs_unclean(struct datablock *db);
 
 /* cluster.c */
 unsigned long long lafs_cluster_allocate(struct block *b, int cnum);
diff --git a/state.h b/state.h
index 1e789e063f2490e9d09076481cc65e5d00bbfcb4..4fa7aed95e9331ca00f241f101052a33ab7fa09e 100644 (file)
--- a/state.h
+++ b/state.h
@@ -96,6 +96,9 @@ struct fs {
                u32 cleaning;           /* amount of space that is being cleaned
                                         * this checkpoint
                                         */
+               struct mutex lock;      /* protects list mani and refcnt of core
+                                        * cleaner.
+                                        */
                struct toclean {
                        u16 dev;
                        u32 seg;
diff --git a/super.c b/super.c
index b70d8e1e7b9b906819a85aa274971c8dc7094ad7..0bc42ffcfbe6cf3eda721467ffa8d1ed172643a1 100644 (file)
--- a/super.c
+++ b/super.c
@@ -530,6 +530,7 @@ lafs_load(struct options *op, int newest)
        init_waitqueue_head(&fs->sb_writes_wait);
        init_waitqueue_head(&fs->async_complete);
        init_waitqueue_head(&fs->trunc_wait);
+       mutex_init(&fs->cleaner.lock);
        spin_lock_init(&fs->stable_lock);
        spin_lock_init(&fs->alloc_lock);
        spin_lock_init(&fs->lock);