summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorngkaho1234 <ngkaho1234@gmail.com>2016-01-21 23:53:41 +0800
committerngkaho1234 <ngkaho1234@gmail.com>2016-01-22 00:03:50 +0800
commitee889f7d84ffbde7acefd23d4b7b7c7a2268242d (patch)
treef86dc8a89cbe71ed4f4da31a3272522aee9fc735
parentfe2cde8c8128fff855522a84a8f2864e6ed69686 (diff)
ext4_bcache: do not allow cache shaking when callback is invoked.
-rw-r--r--lwext4/ext4_bcache.h3
-rw-r--r--lwext4/ext4_blockdev.c22
2 files changed, 18 insertions, 7 deletions
diff --git a/lwext4/ext4_bcache.h b/lwext4/ext4_bcache.h
index 61751f7..bceb75a 100644
--- a/lwext4/ext4_bcache.h
+++ b/lwext4/ext4_bcache.h
@@ -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;
diff --git a/lwext4/ext4_blockdev.c b/lwext4/ext4_blockdev.c
index 37937b6..23ad9ee 100644
--- a/lwext4/ext4_blockdev.c
+++ b/lwext4/ext4_blockdev.c
@@ -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,