aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>2012-12-16 04:44:41 +0900
committerDaniel Phillips <daniel@tux3.org>2012-12-16 04:44:41 +0900
commit0c5a7b1b4f51726b0e6046105ec62ba588a71ef5 (patch)
treeb9ee2f3dc44ddf41c9f61694da34c37dbdf41567
parent1b52f3c12d81ef8c9879e33c7c7617cc7efa1e65 (diff)
downloadlinux-tux3-0c5a7b1b4f51726b0e6046105ec62ba588a71ef5.tar.gz
tux3: Fix -EAGAIN handling returned by blockdirty()
We are ignoring -EAGAIN for now. But with asynchronous backend, we have to check it. However, for now, all blockdirty() are used under lock (e.g. ->i_mutex or backend). So, we just need to call assert() if blockdirty() returned -EAGAIN. Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
-rw-r--r--fs/tux3/balloc.c66
-rw-r--r--fs/tux3/buffer_fork.c4
-rw-r--r--fs/tux3/dir.c10
-rw-r--r--fs/tux3/namei.c5
-rw-r--r--fs/tux3/xattr.c12
5 files changed, 77 insertions, 20 deletions
diff --git a/fs/tux3/balloc.c b/fs/tux3/balloc.c
index 91490b4cda6add..d1c317ecf7dde9 100644
--- a/fs/tux3/balloc.c
+++ b/fs/tux3/balloc.c
@@ -129,7 +129,9 @@ block_t balloc_from_range(struct sb *sb, block_t start, block_t count,
for (block_t mapblock = start >> mapshift; mapblock < mapblocks; mapblock++) {
trace_off("search mapblock %x/%x", mapblock, mapblocks);
- struct buffer_head *buffer = blockread(mapping(inode), mapblock);
+ struct buffer_head *buffer, *clone;
+
+ buffer = blockread(mapping(inode), mapblock);
if (!buffer) {
warn("block read failed"); // !!! error return sucks here
return -1;
@@ -158,11 +160,21 @@ block_t balloc_from_range(struct sb *sb, block_t start, block_t count,
goto final_partial_byte;
}
found -= run - 1;
- buffer = blockdirty(buffer, sb->rollup);
- // FIXME: error check of buffer
- set_bits(bufdata(buffer), found & mapmask, run);
- mark_buffer_dirty_non(buffer);
- blockput(buffer);
+
+ /*
+ * The bitmap is modified only by backend.
+ * blockdirty() should never return -EAGAIN.
+ */
+ clone = blockdirty(buffer, sb->rollup);
+ if (IS_ERR(clone)) {
+ assert(PTR_ERR(clone) != -EAGAIN);
+ blockput(buffer);
+ /* FIXME: error handling */
+ return -1;
+ }
+ set_bits(bufdata(clone), found & mapmask, run);
+ mark_buffer_dirty_non(clone);
+ blockput(clone);
sb->nextalloc = found + run;
sb->freeblocks -= run;
//set_sb_dirty(sb);
@@ -206,7 +218,7 @@ int bfree(struct sb *sb, block_t start, unsigned blocks)
unsigned mapmask = (1 << mapshift) - 1;
block_t mapblock = start >> mapshift;
unsigned mapoffset = start & mapmask;
- struct buffer_head *buffer;
+ struct buffer_head *buffer, *clone;
buffer = blockread(mapping(sb->bitmap), mapblock);
if (!buffer) {
@@ -218,11 +230,20 @@ int bfree(struct sb *sb, block_t start, unsigned blocks)
if (!all_set(bufdata(buffer), mapoffset, blocks))
goto double_free;
trace("bfree extent <- [%Lx/%x], ", start, blocks);
- buffer = blockdirty(buffer, sb->rollup);
- // FIXME: error check of buffer
- clear_bits(bufdata(buffer), mapoffset, blocks);
- mark_buffer_dirty_non(buffer);
- blockput(buffer);
+ /*
+ * The bitmap is modified only by backend.
+ * blockdirty() should never return -EAGAIN.
+ */
+ clone = blockdirty(buffer, sb->rollup);
+ if (IS_ERR(clone)) {
+ assert(PTR_ERR(clone) != -EAGAIN);
+ blockput(buffer);
+ /* FIXME: error handling */
+ return PTR_ERR(clone);
+ }
+ clear_bits(bufdata(clone), mapoffset, blocks);
+ mark_buffer_dirty_non(clone);
+ blockput(clone);
sb->freeblocks += blocks;
//set_sb_dirty(sb);
mutex_unlock(&sb->bitmap->i_mutex);
@@ -245,7 +266,7 @@ int replay_update_bitmap(struct replay *rp, block_t start, unsigned count,
unsigned mapmask = (1 << mapshift) - 1;
block_t mapblock = start >> mapshift;
unsigned mapoffset = start & mapmask;
- struct buffer_head *buffer;
+ struct buffer_head *buffer, *clone;
buffer = blockread(mapping(sb->bitmap), mapblock);
if (!buffer)
@@ -260,11 +281,20 @@ int replay_update_bitmap(struct replay *rp, block_t start, unsigned count,
return -EINVAL;
}
- /* FIXME: error check */
- buffer = blockdirty(buffer, sb->rollup);
- (set ? set_bits : clear_bits)(bufdata(buffer), mapoffset, count);
- mark_buffer_dirty_non(buffer);
- blockput(buffer);
+ /*
+ * The bitmap is modified only by backend.
+ * blockdirty() should never return -EAGAIN.
+ */
+ clone = blockdirty(buffer, sb->rollup);
+ if (IS_ERR(clone)) {
+ assert(PTR_ERR(clone) != -EAGAIN);
+ blockput(buffer);
+ /* FIXME: error handling */
+ return PTR_ERR(clone);
+ }
+ (set ? set_bits : clear_bits)(bufdata(clone), mapoffset, count);
+ mark_buffer_dirty_non(clone);
+ blockput(clone);
if (set)
sb->freeblocks -= count;
diff --git a/fs/tux3/buffer_fork.c b/fs/tux3/buffer_fork.c
index 0d4418538d1a38..e204215b179f91 100644
--- a/fs/tux3/buffer_fork.c
+++ b/fs/tux3/buffer_fork.c
@@ -415,7 +415,7 @@ struct buffer_head *blockdirty(struct buffer_head *buffer, unsigned newdelta)
case RET_FORKED:
/* This page was already forked. Retry from lookup page. */
buffer = ERR_PTR(-EAGAIN);
- assert(0); /* FIXME: we have to handle -EAGAIN case */
+ WARN_ON(1);
/* FALLTHRU */
case RET_ALREADY_DIRTY:
/* This buffer was already dirtied. Done. */
@@ -527,7 +527,7 @@ struct page *pagefork_for_blockdirty(struct page *oldpage, unsigned newdelta)
case RET_FORKED:
/* This page was already forked. Retry from lookup page. */
newpage = ERR_PTR(-EAGAIN);
- assert(0); /* FIXME: we have to handle -EAGAIN case */
+ WARN_ON(1);
case RET_ALREADY_DIRTY:
/* This buffer was already dirtied. Done. */
goto out;
diff --git a/fs/tux3/dir.c b/fs/tux3/dir.c
index ca3ddecc4c65fe..81febce0b0262a 100644
--- a/fs/tux3/dir.c
+++ b/fs/tux3/dir.c
@@ -170,8 +170,13 @@ loff_t tux_create_entry(struct inode *dir, const char *name, unsigned len,
assert(!buffer_dirty(buffer));
create:
+ /*
+ * The directory is protected by i_mutex.
+ * blockdirty() should never return -EAGAIN.
+ */
clone = blockdirty(buffer, delta);
if (IS_ERR(clone)) {
+ assert(PTR_ERR(clone) != -EAGAIN);
blockput(buffer);
return PTR_ERR(clone);
}
@@ -352,8 +357,13 @@ int tux_delete_entry(struct inode *dir, struct buffer_head *buffer,
this = next_entry(this);
}
+ /*
+ * The directory is protected by i_mutex.
+ * blockdirty() should never return -EAGAIN.
+ */
clone = blockdirty(buffer, delta);
if (IS_ERR(clone)) {
+ assert(PTR_ERR(clone) != -EAGAIN);
blockput(buffer);
return PTR_ERR(clone);
}
diff --git a/fs/tux3/namei.c b/fs/tux3/namei.c
index 60bcd429fa9b7c..ca9595fae3ede2 100644
--- a/fs/tux3/namei.c
+++ b/fs/tux3/namei.c
@@ -262,8 +262,13 @@ static int tux3_rename(struct inode *old_dir, struct dentry *old_dentry,
goto error;
}
+ /*
+ * The directory is protected by i_mutex.
+ * blockdirty() should never return -EAGAIN.
+ */
clone = blockdirty(new_buffer, delta);
if (IS_ERR(clone)) {
+ assert(PTR_ERR(clone) != -EAGAIN);
blockput(new_buffer);
err = PTR_ERR(clone);
goto error;
diff --git a/fs/tux3/xattr.c b/fs/tux3/xattr.c
index f10b63f463012d..3f47d58fba8693 100644
--- a/fs/tux3/xattr.c
+++ b/fs/tux3/xattr.c
@@ -115,8 +115,14 @@ static loff_t unatom_dict_write(struct inode *atable, atom_t atom, loff_t where)
if (!buffer)
return -EIO;
+ /*
+ * The atable is protected by i_mutex for now.
+ * blockdirty() should never return -EAGAIN.
+ * FIXME: need finer granularity locking
+ */
clone = blockdirty(buffer, delta);
if (IS_ERR(clone)) {
+ assert(PTR_ERR(clone) != -EAGAIN);
blockput(buffer);
return PTR_ERR(clone);
}
@@ -269,8 +275,14 @@ static int update_refcount(struct sb *sb, struct buffer_head *buffer,
struct buffer_head *clone;
__be16 *refcount;
+ /*
+ * The atable is protected by i_mutex for now.
+ * blockdirty() should never return -EAGAIN.
+ * FIXME: need finer granularity locking
+ */
clone = blockdirty(buffer, delta);
if (IS_ERR(clone)) {
+ assert(PTR_ERR(clone) != -EAGAIN);
blockput(buffer);
return PTR_ERR(clone);
}