aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>2014-03-16 14:39:03 +0900
committerDaniel Phillips <daniel@tux3.org>2014-03-16 14:39:03 +0900
commit6d50f7f63826cde6a755458cea9a3a8bbeb25b99 (patch)
tree855debd6524c8be8cd22e9e5a5a1d1be4094a157
parent9d190848f26c1b07332d9872cf973f09bf2746f7 (diff)
downloadlinux-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.c17
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