Tsutomu Itoh
2011-Jun-13 05:37 UTC
[PATCH] Btrfs: turn to readonly when btrfs_join_transaction() fails
When btrfs_join_transaction()/btrfs_join_transaction_nolock() fails,
we should call btrfs_std_error() properly for filesystem to readonly.
Signed-off-by: Tsutomu Itoh <t-itoh@jp.fujitsu.com>
---
This patch is dependent on
http://marc.info/?l=linux-btrfs&m=130761239706076&w=2
(it is necessary to define btrfs_abort_transaction function)
fs/btrfs/delayed-inode.c | 4 +++-
fs/btrfs/disk-io.c | 8 ++++++--
fs/btrfs/extent-tree.c | 17 +++++++++++++----
fs/btrfs/inode.c | 14 +++++++++++---
fs/btrfs/ioctl.c | 7 ++++++-
fs/btrfs/relocation.c | 13 +++++++++----
fs/btrfs/transaction.c | 1 +
7 files changed, 49 insertions(+), 15 deletions(-)
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
index 6462c29..f829d6a 100644
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -1131,8 +1131,10 @@ static void btrfs_async_run_delayed_node_done(struct
btrfs_work *work)
root = delayed_node->root;
trans = btrfs_join_transaction(root);
- if (IS_ERR(trans))
+ if (IS_ERR(trans)) {
+ btrfs_abort_transaction(root, PTR_ERR(trans));
goto free_path;
+ }
ret = btrfs_insert_delayed_items(trans, path, root, delayed_node);
if (!ret)
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 9f68c68..00312c3 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2478,14 +2478,18 @@ int btrfs_commit_super(struct btrfs_root *root)
up_write(&root->fs_info->cleanup_work_sem);
trans = btrfs_join_transaction(root);
- if (IS_ERR(trans))
+ if (IS_ERR(trans)) {
+ btrfs_abort_transaction(root, PTR_ERR(trans));
return PTR_ERR(trans);
+ }
ret = btrfs_commit_transaction(trans, root);
BUG_ON(ret);
/* run commit again to drop the original snapshot */
trans = btrfs_join_transaction(root);
- if (IS_ERR(trans))
+ if (IS_ERR(trans)) {
+ btrfs_abort_transaction(root, PTR_ERR(trans));
return PTR_ERR(trans);
+ }
btrfs_commit_transaction(trans, root);
ret = btrfs_write_and_wait_transaction(NULL, root);
BUG_ON(ret);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index b42efc2..2f556b9 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3068,8 +3068,10 @@ again:
alloc:
alloc_target = btrfs_get_alloc_profile(root, 1);
trans = btrfs_join_transaction(root);
- if (IS_ERR(trans))
+ if (IS_ERR(trans)) {
+ btrfs_abort_transaction(root, PTR_ERR(trans));
return PTR_ERR(trans);
+ }
ret = do_chunk_alloc(trans, root->fs_info->extent_root,
bytes + 2 * 1024 * 1024,
@@ -3104,8 +3106,10 @@ commit_trans:
!atomic_read(&root->fs_info->open_ioctl_trans)) {
committed = 1;
trans = btrfs_join_transaction(root);
- if (IS_ERR(trans))
+ if (IS_ERR(trans)) {
+ btrfs_abort_transaction(root, PTR_ERR(trans));
return PTR_ERR(trans);
+ }
ret = btrfs_commit_transaction(trans, root);
if (ret)
return ret;
@@ -3483,8 +3487,10 @@ again:
ret = -ENOSPC;
trans = btrfs_join_transaction(root);
- if (IS_ERR(trans))
+ if (IS_ERR(trans)) {
+ btrfs_abort_transaction(root, PTR_ERR(trans));
goto out;
+ }
ret = btrfs_commit_transaction(trans, root);
if (!ret) {
trans = NULL;
@@ -6568,7 +6574,10 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,
BUG_ON(cache->ro);
trans = btrfs_join_transaction(root);
- BUG_ON(IS_ERR(trans));
+ if (IS_ERR(trans)) {
+ btrfs_abort_transaction(root, PTR_ERR(trans));
+ return PTR_ERR(trans);
+ }
alloc_flags = update_block_group_flags(root, cache->flags);
if (alloc_flags != cache->flags)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index c15636b..bfe6970 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -4274,8 +4274,10 @@ int btrfs_write_inode(struct inode *inode, struct
writeback_control *wbc)
trans = btrfs_join_transaction_nolock(root);
else
trans = btrfs_join_transaction(root);
- if (IS_ERR(trans))
+ if (IS_ERR(trans)) {
+ btrfs_abort_transaction(root, PTR_ERR(trans));
return PTR_ERR(trans);
+ }
if (nolock)
ret = btrfs_end_transaction_nolock(trans, root);
else
@@ -5116,8 +5118,11 @@ again:
btrfs_release_path(path);
trans = btrfs_join_transaction(root);
- if (IS_ERR(trans))
+ if (IS_ERR(trans)) {
+ btrfs_abort_transaction(root,
+ PTR_ERR(trans));
return ERR_CAST(trans);
+ }
goto again;
}
map = kmap(page);
@@ -5360,8 +5365,10 @@ static struct extent_map *btrfs_new_extent_direct(struct
inode *inode,
}
trans = btrfs_join_transaction(root);
- if (IS_ERR(trans))
+ if (IS_ERR(trans)) {
+ btrfs_abort_transaction(root, PTR_ERR(trans));
return ERR_CAST(trans);
+ }
if (start <= BTRFS_I(inode)->disk_i_size && len < 64 * 1024)
btrfs_add_inode_defrag(trans, inode);
@@ -5737,6 +5744,7 @@ again:
trans = btrfs_join_transaction(root);
if (IS_ERR(trans)) {
err = -ENOMEM;
+ btrfs_abort_transaction(root, err);
goto out;
}
trans->block_rsv = &root->fs_info->delalloc_block_rsv;
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index b793d11..1774b42 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -244,7 +244,12 @@ static int btrfs_ioctl_setflags(struct file *file, void
__user *arg)
}
trans = btrfs_join_transaction(root);
- BUG_ON(IS_ERR(trans));
+ if (IS_ERR(trans)) {
+ mnt_drop_write(file->f_path.mnt);
+ ret = PTR_ERR(trans);
+ btrfs_abort_transaction(root, ret);
+ goto out_unlock;
+ }
ret = btrfs_update_inode(trans, root, inode);
BUG_ON(ret);
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index f25b10a..db03031 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -2160,6 +2160,7 @@ again:
if (!err)
btrfs_block_rsv_release(rc->extent_root,
rc->block_rsv, num_bytes);
+ btrfs_abort_transaction(rc->extent_root, PTR_ERR(trans));
return PTR_ERR(trans);
}
@@ -3243,6 +3244,7 @@ truncate:
if (IS_ERR(trans)) {
btrfs_free_path(path);
ret = PTR_ERR(trans);
+ btrfs_abort_transaction(root, ret);
goto out;
}
@@ -3840,9 +3842,10 @@ restart:
/* get rid of pinned extents */
trans = btrfs_join_transaction(rc->extent_root);
- if (IS_ERR(trans))
+ if (IS_ERR(trans)) {
err = PTR_ERR(trans);
- else
+ btrfs_abort_transaction(rc->extent_root, err);
+ } else
btrfs_commit_transaction(trans, rc->extent_root);
out_free:
btrfs_free_block_rsv(rc->extent_root, rc->block_rsv);
@@ -4169,6 +4172,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
if (IS_ERR(trans)) {
unset_reloc_control(rc);
err = PTR_ERR(trans);
+ btrfs_abort_transaction(rc->extent_root, err);
goto out_free;
}
@@ -4200,9 +4204,10 @@ int btrfs_recover_relocation(struct btrfs_root *root)
unset_reloc_control(rc);
trans = btrfs_join_transaction(rc->extent_root);
- if (IS_ERR(trans))
+ if (IS_ERR(trans)) {
err = PTR_ERR(trans);
- else
+ btrfs_abort_transaction(rc->extent_root, err);
+ } else
btrfs_commit_transaction(trans, rc->extent_root);
out_free:
kfree(rc);
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 2b3590b..a20dcbb 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -1103,6 +1103,7 @@ int btrfs_commit_transaction_async(struct
btrfs_trans_handle *trans,
if (IS_ERR(ac->newtrans)) {
int err = PTR_ERR(ac->newtrans);
kfree(ac);
+ btrfs_abort_transaction(root, err);
return err;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs"
in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html