From: NeilBrown Date: Fri, 9 Jul 2010 04:36:50 +0000 (+1000) Subject: Clean up handling of B_Async X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=d353e95b645ace701e30a5b8a84321f95a787842;p=LaFS.git Clean up handling of B_Async 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 --- diff --git a/clean.c b/clean.c index 3744ec3..d59dc42 100644 --- 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 aa78a37..7d35a45 100644 --- 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