From c6487a7d1d0ae7c4c37785838c4817bd4f864fb7 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Tue, 29 Aug 2017 17:22:39 +0200 Subject: [PATCH] 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 --- disk-io.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/disk-io.c b/disk-io.c index 29aec0b..f5edc47 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, -- 2.7.4