diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2014-03-16 14:39:03 +0900 |
---|---|---|
committer | Daniel Phillips <daniel@tux3.org> | 2014-03-16 14:39:03 +0900 |
commit | 6d50f7f63826cde6a755458cea9a3a8bbeb25b99 (patch) | |
tree | 855debd6524c8be8cd22e9e5a5a1d1be4094a157 | |
parent | 9d190848f26c1b07332d9872cf973f09bf2746f7 (diff) | |
download | linux-tux3-6d50f7f63826cde6a755458cea9a3a8bbeb25b99.tar.gz |
tux3: Fix countmap_load() race with forked buffer
If countmap_used() was used in frontend, pin buffer can have forked
buffer.
So, we have to use blockread() if pin has forked buffer.
FIXME: or we should use bigger locking to prevent to set forked buffer
to pin?
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
-rw-r--r-- | fs/tux3/balloc.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/fs/tux3/balloc.c b/fs/tux3/balloc.c index cc642d082c6d7..d504470b3c8aa 100644 --- a/fs/tux3/balloc.c +++ b/fs/tux3/balloc.c @@ -60,7 +60,22 @@ static struct buffer_head *countmap_load(struct sb *sb, block_t group) static void countmap_pin_update(struct sb *sb, struct buffer_head *buffer) { - if (sb->countmap_pin.buffer != buffer) { + /* + * If buffer is forked, don't set the forked buffer to pin, to + * prevent countmap_add() grabs the forked buffer. + * + * NOTE: + * cpu0 cpu1 + * buf0 = blockread() + * clone = blockdirty(buf0) + * [buf0 became forked buffer] + * countmap_pin_update(buf0) + * countmap_pin_update(clone) + * + * Like above, pin can have the forked buffer for short time though. + * cpu0 will update soon. + */ + if (sb->countmap_pin.buffer != buffer && !buffer_forked(buffer)) { countmap_put(&sb->countmap_pin); sb->countmap_pin.buffer = buffer; } else |