mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
btrfs: allocate root item at snapshot ioctl time
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>
This commit is contained in:
parent
a1ee736268
commit
b0c0ea6338
@ -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);
|
||||
@ -738,6 +745,8 @@ fail:
|
||||
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;
|
||||
|
@ -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)
|
||||
@ -1562,7 +1559,7 @@ clear_skip_qgroup:
|
||||
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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user