Skip to content

Commit

Permalink
btrfs: allocate root item at snapshot ioctl time
Browse files Browse the repository at this point in the history
The actual snapshot creation is delayed until transaction commit. If we
cannot get enough memory for the root item there, we have to fail the
whole transaction commit which is bad. So we'll allocate the memory at
the ioctl call and pass it along with the pending_snapshot struct. The
potential ENOMEM will be returned to the caller of snapshot ioctl.

Signed-off-by: David Sterba <dsterba@suse.com>
  • Loading branch information
David Sterba committed Jan 7, 2016
1 parent a1ee736 commit b0c0ea6
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 6 deletions.
9 changes: 9 additions & 0 deletions fs/btrfs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,13 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
if (!pending_snapshot)
return -ENOMEM;

pending_snapshot->root_item = kzalloc(sizeof(struct btrfs_root_item),
GFP_NOFS);
if (!pending_snapshot->root_item) {
ret = -ENOMEM;
goto free_pending;
}

atomic_inc(&root->will_be_snapshoted);
smp_mb__after_atomic();
btrfs_wait_for_no_snapshoting_writes(root);
Expand Down Expand Up @@ -738,6 +745,8 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
dec_and_free:
if (atomic_dec_and_test(&root->will_be_snapshoted))
wake_up_atomic_t(&root->will_be_snapshoted);
free_pending:
kfree(pending_snapshot->root_item);
kfree(pending_snapshot);

return ret;
Expand Down
9 changes: 3 additions & 6 deletions fs/btrfs/transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -1325,11 +1325,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
return 0;
}

new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS);
if (!new_root_item) {
pending->error = -ENOMEM;
goto root_item_alloc_fail;
}
ASSERT(pending->root_item);
new_root_item = pending->root_item;

pending->error = btrfs_find_free_objectid(tree_root, &objectid);
if (pending->error)
Expand Down Expand Up @@ -1562,7 +1559,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
btrfs_clear_skip_qgroup(trans);
no_free_objectid:
kfree(new_root_item);
root_item_alloc_fail:
pending->root_item = NULL;
btrfs_free_path(path);
return ret;
}
Expand Down
1 change: 1 addition & 0 deletions fs/btrfs/transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ struct btrfs_pending_snapshot {
struct dentry *dentry;
struct inode *dir;
struct btrfs_root *root;
struct btrfs_root_item *root_item;
struct btrfs_root *snap;
struct btrfs_qgroup_inherit *inherit;
/* block reservation for the operation */
Expand Down

0 comments on commit b0c0ea6

Please sign in to comment.