diff options
-rw-r--r-- | fs/btrfs/transaction.c | 68 |
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; | ||
1126 | fail: | 1147 | fail: |
1127 | dput(parent); | 1148 | dput(parent); |
1128 | trans->block_rsv = rsv; | 1149 | trans->block_rsv = rsv; |
1129 | no_free_objectid: | 1150 | no_free_objectid: |
1130 | kfree(new_root_item); | 1151 | kfree(new_root_item); |
1131 | root_item_alloc_fail: | 1152 | root_item_alloc_fail: |
1153 | btrfs_free_path(path); | ||
1154 | path_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; |