aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/transaction.c68
1 files changed, 53 insertions, 15 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 4b6ce5cab44..a86fc723aad 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -955,6 +955,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
955 struct btrfs_root *parent_root; 955 struct btrfs_root *parent_root;
956 struct btrfs_block_rsv *rsv; 956 struct btrfs_block_rsv *rsv;
957 struct inode *parent_inode; 957 struct inode *parent_inode;
958 struct btrfs_path *path;
959 struct btrfs_dir_item *dir_item;
958 struct dentry *parent; 960 struct dentry *parent;
959 struct dentry *dentry; 961 struct dentry *dentry;
960 struct extent_buffer *tmp; 962 struct extent_buffer *tmp;
@@ -967,6 +969,12 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
967 u64 root_flags; 969 u64 root_flags;
968 uuid_le new_uuid; 970 uuid_le new_uuid;
969 971
972 path = btrfs_alloc_path();
973 if (!path) {
974 ret = pending->error = -ENOMEM;
975 goto path_alloc_fail;
976 }
977
970 new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); 978 new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS);
971 if (!new_root_item) { 979 if (!new_root_item) {
972 ret = pending->error = -ENOMEM; 980 ret = pending->error = -ENOMEM;
@@ -1015,23 +1023,20 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
1015 */ 1023 */
1016 ret = btrfs_set_inode_index(parent_inode, &index); 1024 ret = btrfs_set_inode_index(parent_inode, &index);
1017 BUG_ON(ret); /* -ENOMEM */ 1025 BUG_ON(ret); /* -ENOMEM */
1018 ret = btrfs_insert_dir_item(trans, parent_root, 1026
1019 dentry->d_name.name, dentry->d_name.len, 1027 /* check if there is a file/dir which has the same name. */
1020 parent_inode, &key, 1028 dir_item = btrfs_lookup_dir_item(NULL, parent_root, path,
1021 BTRFS_FT_DIR, index); 1029 btrfs_ino(parent_inode),
1022 if (ret == -EEXIST) { 1030 dentry->d_name.name,
1031 dentry->d_name.len, 0);
1032 if (dir_item != NULL && !IS_ERR(dir_item)) {
1023 pending->error = -EEXIST; 1033 pending->error = -EEXIST;
1024 goto fail; 1034 goto fail;
1025 } else if (ret) { 1035 } else if (IS_ERR(dir_item)) {
1036 ret = PTR_ERR(dir_item);
1026 goto abort_trans; 1037 goto abort_trans;
1027 } 1038 }
1028 1039 btrfs_release_path(path);
1029 btrfs_i_size_write(parent_inode, parent_inode->i_size +
1030 dentry->d_name.len * 2);
1031 parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME;
1032 ret = btrfs_update_inode(trans, parent_root, parent_inode);
1033 if (ret)
1034 goto abort_trans;
1035 1040
1036 /* 1041 /*
1037 * pull in the delayed directory update 1042 * pull in the delayed directory update
@@ -1123,12 +1128,30 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
1123 ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); 1128 ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
1124 if (ret) 1129 if (ret)
1125 goto abort_trans; 1130 goto abort_trans;
1131
1132 ret = btrfs_insert_dir_item(trans, parent_root,
1133 dentry->d_name.name, dentry->d_name.len,
1134 parent_inode, &key,
1135 BTRFS_FT_DIR, index);
1136 /* We have check then name at the beginning, so it is impossible. */
1137 BUG_ON(ret == -EEXIST);
1138 if (ret)
1139 goto abort_trans;
1140
1141 btrfs_i_size_write(parent_inode, parent_inode->i_size +
1142 dentry->d_name.len * 2);
1143 parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME;
1144 ret = btrfs_update_inode(trans, parent_root, parent_inode);
1145 if (ret)
1146 goto abort_trans;
1126fail: 1147fail:
1127 dput(parent); 1148 dput(parent);
1128 trans->block_rsv = rsv; 1149 trans->block_rsv = rsv;
1129no_free_objectid: 1150no_free_objectid:
1130 kfree(new_root_item); 1151 kfree(new_root_item);
1131root_item_alloc_fail: 1152root_item_alloc_fail:
1153 btrfs_free_path(path);
1154path_alloc_fail:
1132 btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1); 1155 btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1);
1133 return ret; 1156 return ret;
1134 1157
@@ -1472,13 +1495,28 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1472 */ 1495 */
1473 mutex_lock(&root->fs_info->reloc_mutex); 1496 mutex_lock(&root->fs_info->reloc_mutex);
1474 1497
1475 ret = btrfs_run_delayed_items(trans, root); 1498 /*
1499 * We needn't worry about the delayed items because we will
1500 * deal with them in create_pending_snapshot(), which is the
1501 * core function of the snapshot creation.
1502 */
1503 ret = create_pending_snapshots(trans, root->fs_info);
1476 if (ret) { 1504 if (ret) {
1477 mutex_unlock(&root->fs_info->reloc_mutex); 1505 mutex_unlock(&root->fs_info->reloc_mutex);
1478 goto cleanup_transaction; 1506 goto cleanup_transaction;
1479 } 1507 }
1480 1508
1481 ret = create_pending_snapshots(trans, root->fs_info); 1509 /*
1510 * We insert the dir indexes of the snapshots and update the inode
1511 * of the snapshots' parents after the snapshot creation, so there
1512 * are some delayed items which are not dealt with. Now deal with
1513 * them.
1514 *
1515 * We needn't worry that this operation will corrupt the snapshots,
1516 * because all the tree which are snapshoted will be forced to COW
1517 * the nodes and leaves.
1518 */
1519 ret = btrfs_run_delayed_items(trans, root);
1482 if (ret) { 1520 if (ret) {
1483 mutex_unlock(&root->fs_info->reloc_mutex); 1521 mutex_unlock(&root->fs_info->reloc_mutex);
1484 goto cleanup_transaction; 1522 goto cleanup_transaction;