diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2012-12-16 04:44:41 +0900 |
---|---|---|
committer | Daniel Phillips <daniel@tux3.org> | 2012-12-16 04:44:41 +0900 |
commit | 0c5a7b1b4f51726b0e6046105ec62ba588a71ef5 (patch) | |
tree | b9ee2f3dc44ddf41c9f61694da34c37dbdf41567 | |
parent | 1b52f3c12d81ef8c9879e33c7c7617cc7efa1e65 (diff) | |
download | linux-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.c | 66 | ||||
-rw-r--r-- | fs/tux3/buffer_fork.c | 4 | ||||
-rw-r--r-- | fs/tux3/dir.c | 10 | ||||
-rw-r--r-- | fs/tux3/namei.c | 5 | ||||
-rw-r--r-- | fs/tux3/xattr.c | 12 |
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); } |