diff options
author | Josef Bacik <josef@redhat.com> | 2010-10-26 12:52:53 -0400 |
---|---|---|
committer | Josef Bacik <josef@redhat.com> | 2010-10-26 12:52:53 -0400 |
commit | 382279336f428c80f344edfc30d53797e3e76146 (patch) | |
tree | 91b1acbc1f60430742ace0b9155c4a014b7dbbaf /fs/btrfs/extent-tree.c | |
parent | 0e78340f3c1fc603e8016c8ac304766bcc65506e (diff) |
Btrfs: set trans to null in reserve_metadata_bytes if we commit the transaction
btrfs_commit_transaction will free our trans, but because we pass trans to
shrink_delalloc we could possibly have a use after free situation. So instead
if we commit the transaction, set trans to null and set committed to true so we
don't keep trying to commit a transaction. This fixes a panic I could reproduce
at will. Thanks,
Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 180a50146ddf..e2dfd4ab3b9b 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -3157,6 +3157,7 @@ static int reserve_metadata_bytes(struct btrfs_trans_handle *trans, | |||
3157 | int retries = 0; | 3157 | int retries = 0; |
3158 | int ret = 0; | 3158 | int ret = 0; |
3159 | bool reserved = false; | 3159 | bool reserved = false; |
3160 | bool committed = false; | ||
3160 | 3161 | ||
3161 | again: | 3162 | again: |
3162 | ret = -ENOSPC; | 3163 | ret = -ENOSPC; |
@@ -3249,17 +3250,19 @@ again: | |||
3249 | goto out; | 3250 | goto out; |
3250 | 3251 | ||
3251 | ret = -EAGAIN; | 3252 | ret = -EAGAIN; |
3252 | if (trans) | 3253 | if (trans || committed) |
3253 | goto out; | 3254 | goto out; |
3254 | 3255 | ||
3255 | |||
3256 | ret = -ENOSPC; | 3256 | ret = -ENOSPC; |
3257 | trans = btrfs_join_transaction(root, 1); | 3257 | trans = btrfs_join_transaction(root, 1); |
3258 | if (IS_ERR(trans)) | 3258 | if (IS_ERR(trans)) |
3259 | goto out; | 3259 | goto out; |
3260 | ret = btrfs_commit_transaction(trans, root); | 3260 | ret = btrfs_commit_transaction(trans, root); |
3261 | if (!ret) | 3261 | if (!ret) { |
3262 | trans = NULL; | ||
3263 | committed = true; | ||
3262 | goto again; | 3264 | goto again; |
3265 | } | ||
3263 | 3266 | ||
3264 | out: | 3267 | out: |
3265 | if (reserved) { | 3268 | if (reserved) { |