summaryrefslogtreecommitdiff
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
authorDavid Sterba <dsterba@suse.com>2015-11-10 20:54:00 +0300
committerDavid Sterba <dsterba@suse.com>2016-01-07 17:20:54 +0300
commitb0c0ea6338d5018e02d27c5315084fb1a5d099f6 (patch)
treebf2aa288dd2d98143b12ea1753739491c7eda54d /fs/btrfs/ioctl.c
parenta1ee736268448d74af25737568e383acb84c3c18 (diff)
downloadlinux-b0c0ea6338d5018e02d27c5315084fb1a5d099f6.tar.xz
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>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index fa25091e10ab..27fc660b0ff3 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -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;