]> git.neil.brown.name Git - LaFS.git/commitdiff
Clean up handling of B_Async
authorNeilBrown <neilb@suse.de>
Fri, 9 Jul 2010 04:36:50 +0000 (14:36 +1000)
committerNeilBrown <neilb@suse.de>
Fri, 9 Jul 2010 04:36:50 +0000 (14:36 +1000)
Follow a uniform structure for the functions that set/clear this bit.

Make sure cleaner is always woken if a block becomes available while
this bit is set.

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

diff --git a/clean.c b/clean.c
index 3744ec304c9cb99f71405c3cad507461847ca73b..d59dc428a4c747208136cfad3c2f6dc2ce89aadc 100644 (file)
--- a/clean.c
+++ b/clean.c
@@ -528,8 +528,10 @@ void lafs_unclean(struct datablock *db)
                        list_del_init(&db->cleaning);
                        putdref(db, MKREF(cleaning));
                        iput(db->b.inode);
-                       if (test_and_clear_bit(B_Async, &db->b.flags))
+                       if (test_and_clear_bit(B_Async, &db->b.flags)) {
                                putdref(db, MKREF(async));
+                               lafs_wake_cleaner(fs);
+                       }
                }
                mutex_unlock(&fs->cleaner.lock);
        }
diff --git a/io.c b/io.c
index aa78a37b798eae76c76dbf417ac43f9dec82a6e5..7d35a45f5ad21841c2226d0fc8d689b18744f851 100644 (file)
--- a/io.c
+++ b/io.c
@@ -212,16 +212,20 @@ void _lafs_iolock_block(struct block *b)
        }
 }
 
-int _lafs_iolock_block_async(struct block *b) {
-       if (test_bit(B_IOLock, &b->flags))
-               if (!test_and_set_bit(B_Async, &b->flags))
-                       getref(b, MKREF(async));
-       if (test_and_set_bit(B_IOLock, &b->flags))
-               return 0;
-
-       if (test_and_clear_bit(B_Async, &b->flags))
-               putref(b, MKREF(async));
-       return 1;
+int _lafs_iolock_block_async(struct block *b)
+{
+       for(;;) {
+               if (!test_and_set_bit(B_IOLock, &b->flags)) {
+                       /* just got the lock! */
+                       if (test_and_clear_bit(B_Async, &b->flags))
+                               putref(b, MKREF(async));
+                       return 1;
+               }
+               if (test_and_set_bit(B_Async, &b->flags))
+                       /* already have async set */
+                       return 0;
+               getref(b, MKREF(async));
+       }
 }
 
 void
@@ -349,20 +353,20 @@ lafs_wait_block(struct block *b)
 int __must_check
 lafs_wait_block_async(struct block *b)
 {
-       if (test_bit(B_IOLock, &b->flags)) {
-               if (!test_and_set_bit(B_Async, &b->flags))
-                       getref(b, MKREF(async));
+       for (;;) {
+               if (!test_bit(B_IOLock, &b->flags) ||
+                   test_bit(B_Valid, &b->flags)) {
+                       if (test_and_clear_bit(B_Async, &b->flags))
+                               putref(b, MKREF(async));
+                       if (test_bit(B_Valid, &b->flags))
+                               return 0;
+                       else
+                               return -EIO;
+               }
+               if (test_and_set_bit(B_Async, &b->flags))
+                       return -EAGAIN;
+               getref(b, MKREF(async));
        }
-       if (!test_bit(B_IOLock, &b->flags) ||
-           test_bit(B_Valid, &b->flags)) {
-               if (test_and_clear_bit(B_Async, &b->flags))
-                       putref(b, MKREF(async));
-               if (test_bit(B_Valid, &b->flags))
-                       return 0;
-               else
-                       return -EIO;
-       } else
-               return -EAGAIN;
 }
 
 static void wait_writeback(struct block *b)
@@ -388,17 +392,23 @@ void _lafs_iolock_written(struct block *b)
 
 int _lafs_iolock_written_async(struct block *b)
 {
-       if (!_lafs_iolock_block_async(b))
-               return 0;
-       if (test_bit(B_Writeback, &b->flags))
-               if (!test_and_set_bit(B_Async, &b->flags))
-                       getref(b, MKREF(async));
-       if (test_bit(B_Writeback, &b->flags))
-               return 0;
+       for (;;) {
+               if (!test_bit(B_Writeback, &b->flags) &&
+                   !test_and_set_bit(B_IOLock, &b->flags)) {
+                       if (!test_bit(B_Writeback, &b->flags)) {
+                               /* Have lock without writeback */
+                               if (test_and_clear_bit(B_Async, &b->flags))
+                                       putref(b, MKREF(async));
+                               return 1;
+                       }
+                       /* Writeback was set by a racing thread.. */
+                       lafs_iounlock_block(b);
+               }
+               if (test_and_set_bit(B_Async, &b->flags))
+                       return 0;
 
-       if (test_and_clear_bit(B_Async, &b->flags))
-               putref(b, MKREF(async));
-       return 1;
+               getref(b, MKREF(async));
+       }
 }
 
 static void