diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2013-03-04 09:44:29 +0000 |
---|---|---|
committer | Josef Bacik <jbacik@fusionio.com> | 2013-03-04 16:33:22 -0500 |
commit | aec8030a8745221c8658f2033b22c98528897b13 (patch) | |
tree | 58634fad399097dbde3d4969e498cb913a48aa96 /fs/btrfs/ioctl.c | |
parent | 9bf7a4890518186238d2579be16ecc5190a707c0 (diff) | |
download | blackbird-obmc-linux-aec8030a8745221c8658f2033b22c98528897b13.tar.gz blackbird-obmc-linux-aec8030a8745221c8658f2033b22c98528897b13.zip |
Btrfs: fix wrong handle at error path of create_snapshot() when the commit fails
There are several bugs at error path of create_snapshot() when the
transaction commitment failed.
- access the freed transaction handler. At the end of the
transaction commitment, the transaction handler was freed, so we
should not access it after the transaction commitment.
- we were not aware of the error which happened during the snapshot
creation if we submitted a async transaction commitment.
- pending snapshot access vs pending snapshot free. when something
wrong happened after we submitted a async transaction commitment,
the transaction committer would cleanup the pending snapshots and
free them. But the snapshot creators were not aware of it, they
would access the freed pending snapshots.
This patch fixes the above problems by:
- remove the dangerous code that accessed the freed handler
- assign ->error if the error happens during the snapshot creation
- the transaction committer doesn't free the pending snapshots,
just assigns the error number and evicts them before we unblock
the transaction.
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 6 |
1 files changed, 1 insertions, 5 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index b908960c9746..94c0e42dfa1e 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -596,12 +596,8 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir, ret = btrfs_commit_transaction(trans, root->fs_info->extent_root); } - if (ret) { - /* cleanup_transaction has freed this for us */ - if (trans->aborted) - pending_snapshot = NULL; + if (ret) goto fail; - } ret = pending_snapshot->error; if (ret) |