summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Sterba <dsterba@suse.com>2017-08-29 17:22:39 +0200
committerDavid Sterba <dsterba@suse.com>2017-09-08 16:15:05 +0200
commitc6487a7d1d0ae7c4c37785838c4817bd4f864fb7 (patch)
tree4ca699980d049db0d4d6f3fea32f36603a24be92
parentc4dd5fef8a97543630fe945e5d5a365e40cb17f0 (diff)
btrfs-progs: handle transaction start failure in close_ctree
Closing the fs will try to commit a pending transaction, but may fail to do so if the filesystem state is not well defined. This will eg. fail for some fuzz tests. The data structures are freed but no furhter attempt to commit is made. Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--disk-io.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/disk-io.c b/disk-io.c
index 29aec0ba..f5edc479 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -1623,6 +1623,7 @@ int write_ctree_super(struct btrfs_trans_handle *trans,
int close_ctree_fs_info(struct btrfs_fs_info *fs_info)
{
int ret;
+ int err = 0;
struct btrfs_trans_handle *trans;
struct btrfs_root *root = fs_info->tree_root;
@@ -1630,7 +1631,10 @@ int close_ctree_fs_info(struct btrfs_fs_info *fs_info)
fs_info->generation) {
BUG_ON(!root);
trans = btrfs_start_transaction(root, 1);
- BUG_ON(IS_ERR(trans));
+ if (IS_ERR(trans)) {
+ err = PTR_ERR(trans);
+ goto skip_commit;
+ }
btrfs_commit_transaction(trans, root);
trans = btrfs_start_transaction(root, 1);
BUG_ON(IS_ERR(trans));
@@ -1650,6 +1654,8 @@ int close_ctree_fs_info(struct btrfs_fs_info *fs_info)
fprintf(stderr,
"failed to write new super block err %d\n", ret);
}
+
+skip_commit:
btrfs_free_block_groups(fs_info);
free_fs_roots_tree(&fs_info->fs_root_tree);
@@ -1658,7 +1664,9 @@ int close_ctree_fs_info(struct btrfs_fs_info *fs_info)
ret = btrfs_close_devices(fs_info->fs_devices);
btrfs_cleanup_all_caches(fs_info);
btrfs_free_fs_info(fs_info);
- return ret;
+ if (!err)
+ err = ret;
+ return err;
}
int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,