aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Sterba <dsterba@suse.com>2015-11-10 12:54:00 -0500
committerDavid Sterba <dsterba@suse.com>2016-01-07 09:20:54 -0500
commitb0c0ea6338d5018e02d27c5315084fb1a5d099f6 (patch)
treebf2aa288dd2d98143b12ea1753739491c7eda54d
parenta1ee736268448d74af25737568e383acb84c3c18 (diff)
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>
-rw-r--r--fs/btrfs/ioctl.c9
-rw-r--r--fs/btrfs/transaction.c9
-rw-r--r--fs/btrfs/transaction.h1
3 files changed, 13 insertions, 6 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,
659 if (!pending_snapshot) 659 if (!pending_snapshot)
660 return -ENOMEM; 660 return -ENOMEM;
661 661
662 pending_snapshot->root_item = kzalloc(sizeof(struct btrfs_root_item),
663 GFP_NOFS);
664 if (!pending_snapshot->root_item) {
665 ret = -ENOMEM;
666 goto free_pending;
667 }
668
662 atomic_inc(&root->will_be_snapshoted); 669 atomic_inc(&root->will_be_snapshoted);
663 smp_mb__after_atomic(); 670 smp_mb__after_atomic();
664 btrfs_wait_for_no_snapshoting_writes(root); 671 btrfs_wait_for_no_snapshoting_writes(root);
@@ -738,6 +745,8 @@ fail:
738dec_and_free: 745dec_and_free:
739 if (atomic_dec_and_test(&root->will_be_snapshoted)) 746 if (atomic_dec_and_test(&root->will_be_snapshoted))
740 wake_up_atomic_t(&root->will_be_snapshoted); 747 wake_up_atomic_t(&root->will_be_snapshoted);
748free_pending:
749 kfree(pending_snapshot->root_item);
741 kfree(pending_snapshot); 750 kfree(pending_snapshot);
742 751
743 return ret; 752 return ret;
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index be8eae80ff65..2074106122d9 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -1325,11 +1325,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
1325 return 0; 1325 return 0;
1326 } 1326 }
1327 1327
1328 new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); 1328 ASSERT(pending->root_item);
1329 if (!new_root_item) { 1329 new_root_item = pending->root_item;
1330 pending->error = -ENOMEM;
1331 goto root_item_alloc_fail;
1332 }
1333 1330
1334 pending->error = btrfs_find_free_objectid(tree_root, &objectid); 1331 pending->error = btrfs_find_free_objectid(tree_root, &objectid);
1335 if (pending->error) 1332 if (pending->error)
@@ -1562,7 +1559,7 @@ clear_skip_qgroup:
1562 btrfs_clear_skip_qgroup(trans); 1559 btrfs_clear_skip_qgroup(trans);
1563no_free_objectid: 1560no_free_objectid:
1564 kfree(new_root_item); 1561 kfree(new_root_item);
1565root_item_alloc_fail: 1562 pending->root_item = NULL;
1566 btrfs_free_path(path); 1563 btrfs_free_path(path);
1567 return ret; 1564 return ret;
1568} 1565}
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 64c8221b6165..b6f9a3c94468 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -137,6 +137,7 @@ struct btrfs_pending_snapshot {
137 struct dentry *dentry; 137 struct dentry *dentry;
138 struct inode *dir; 138 struct inode *dir;
139 struct btrfs_root *root; 139 struct btrfs_root *root;
140 struct btrfs_root_item *root_item;
140 struct btrfs_root *snap; 141 struct btrfs_root *snap;
141 struct btrfs_qgroup_inherit *inherit; 142 struct btrfs_qgroup_inherit *inherit;
142 /* block reservation for the operation */ 143 /* block reservation for the operation */