ext4_bcache: do not allow cache shaking when callback is invoked.
authorngkaho1234 <ngkaho1234@gmail.com>
Thu, 21 Jan 2016 15:53:41 +0000 (23:53 +0800)
committerngkaho1234 <ngkaho1234@gmail.com>
Thu, 21 Jan 2016 16:03:50 +0000 (00:03 +0800)
lwext4/ext4_bcache.h
lwext4/ext4_blockdev.c

index 61751f761b2f907892298273010087864cf586df..bceb75a12fdb490091b04d3e2ed4b4fdc14889d3 100644 (file)
@@ -135,6 +135,9 @@ struct ext4_bcache {
        /**@brief   The blockdev binded to this block cache*/
        struct ext4_blockdev *bdev;
 
+       /**@brief   The cache should not be shaked */
+       bool dont_shake;
+
        /**@brief   A tree holding all bufs*/
        RB_HEAD(ext4_buf_lba, ext4_buf) lba_root;
 
index 37937b6cbd4d9876c92c6bc851ae93b49786e771..23ad9ee3467368699090a6c921ad5186a3c17cab 100644 (file)
@@ -144,19 +144,23 @@ int ext4_block_flush_buf(struct ext4_blockdev *bdev, struct ext4_buf *buf)
        if (ext4_bcache_test_flag(buf, BC_DIRTY) &&
            ext4_bcache_test_flag(buf, BC_UPTODATE)) {
                r = ext4_blocks_set_direct(bdev, buf->data, buf->lba, 1);
-
                if (r) {
-                       if (buf->end_write)
+                       if (buf->end_write) {
+                               bc->dont_shake = true;
                                buf->end_write(bc, buf, r, buf->end_write_arg);
+                               bc->dont_shake = false;
+                       }
 
                        return r;
                }
 
                ext4_bcache_remove_dirty_node(bc, buf);
                ext4_bcache_clear_flag(buf, BC_DIRTY);
-               if (buf->end_write)
+               if (buf->end_write) {
+                       bc->dont_shake = true;
                        buf->end_write(bc, buf, r, buf->end_write_arg);
-
+                       bc->dont_shake = false;
+               }
        }
        return EOK;
 }
@@ -176,22 +180,26 @@ int ext4_block_flush_lba(struct ext4_blockdev *bdev, uint64_t lba)
 
 int ext4_block_cache_shake(struct ext4_blockdev *bdev)
 {
+       int r = EOK;
        struct ext4_buf *buf;
+       if (bdev->bc->dont_shake)
+               return EOK;
+
        while (!RB_EMPTY(&bdev->bc->lru_root) &&
                ext4_bcache_is_full(bdev->bc)) {
 
                buf = ext4_buf_lowest_lru(bdev->bc);
                ext4_assert(buf);
                if (ext4_bcache_test_flag(buf, BC_DIRTY)) {
-                       int r = ext4_block_flush_buf(bdev, buf);
+                       r = ext4_block_flush_buf(bdev, buf);
                        if (r != EOK)
-                               return r;
+                               break;
 
                }
 
                ext4_bcache_drop_buf(bdev->bc, buf);
        }
-       return EOK;
+       return r;
 }
 
 int ext4_block_get_noread(struct ext4_blockdev *bdev, struct ext4_block *b,