]> git.neil.brown.name Git - LaFS.git/commitdiff
Make sure we don't wait forever on writeback
authorNeilBrown <neilb@suse.de>
Fri, 9 Jul 2010 10:49:54 +0000 (20:49 +1000)
committerNeilBrown <neilb@suse.de>
Fri, 9 Jul 2010 21:32:01 +0000 (07:32 +1000)
If we ever wait on writeback on a block, we need to cluster_flush
quite promptly or we could wait forever.

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

diff --git a/clean.c b/clean.c
index 54405d4370a73f303507c31b0c1a7ef75940c46a..709dc92e82881ea4538a11ea70d01570b2f9d631 100644 (file)
--- a/clean.c
+++ b/clean.c
@@ -92,6 +92,9 @@ static int cleaner(void *data)
                         timeout);
                clear_bit(CleanerNeeded, &fs->fsstate);
 
+               if (test_and_clear_bit(FlushNeeded, &fs->fsstate))
+                       lafs_cluster_flush(fs, 0);
+
                timeout = MAX_SCHEDULE_TIMEOUT;
                to = lafs_do_checkpoint(fs);
                if (to < timeout)
@@ -139,6 +142,15 @@ void lafs_wake_cleaner(struct fs *fs)
        wake_up(&fs->async_complete);
 }
 
+void lafs_trigger_flush(struct block *b)
+{
+       struct fs *fs = fs_from_inode(b->inode);
+
+       if (test_bit(B_Writeback, &b->flags) &&
+           !test_and_set_bit(FlushNeeded, &fs->fsstate))
+               lafs_wake_cleaner(fs);
+}
+
 static int mark_cleaning(struct block *b)
 {
        int err;
diff --git a/io.c b/io.c
index 7d35a45f5ad21841c2226d0fc8d689b18744f851..82d92a6ba7522b52b2f676814ff821f1d1cfd350 100644 (file)
--- a/io.c
+++ b/io.c
@@ -373,6 +373,7 @@ static void wait_writeback(struct block *b)
 {
        if (test_bit(B_Writeback, &b->flags)) {
                DEFINE_WAIT(wq);
+               lafs_trigger_flush(b);
                for (;;) {
                        prepare_to_wait(&block_wait, &wq, TASK_UNINTERRUPTIBLE);
                        if (test_bit(B_Writeback, &b->flags))
@@ -404,6 +405,7 @@ int _lafs_iolock_written_async(struct block *b)
                        /* Writeback was set by a racing thread.. */
                        lafs_iounlock_block(b);
                }
+               lafs_trigger_flush(b);
                if (test_and_set_bit(B_Async, &b->flags))
                        return 0;
 
diff --git a/lafs.h b/lafs.h
index 1024a8755caac2b48e0bd905c306e709ca359157..4043e9bf44f5758359c70594494979bf56541cba 100644 (file)
--- a/lafs.h
+++ b/lafs.h
@@ -641,6 +641,7 @@ 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);
+void lafs_trigger_flush(struct block *b);
 
 /* cluster.c */
 int lafs_cluster_allocate(struct block *b, int cnum);
diff --git a/state.h b/state.h
index b9d462f6b5a015be6b44b6682a10d87009d92079..95b96c55f7552ab8d1a51e6b4c43731d287be5a8 100644 (file)
--- a/state.h
+++ b/state.h
@@ -99,6 +99,9 @@ struct fs {
                         * be full and new allocation requests get
                         * -ENOSPC
                         */
+#define FlushNeeded 8  /* Need to flush the current cluster because
+                       * someone is waiting on writeback
+                       */
 
        struct work_struct done_work;   /* used for handling
                                         * refile after write completes */