}
}
-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
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)
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