diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/btrfs_inode.h | 1 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 28 | ||||
-rw-r--r-- | fs/btrfs/dir-item.c | 47 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 71 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 368 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 13 | ||||
-rw-r--r-- | fs/btrfs/orphan.c | 20 | ||||
-rw-r--r-- | fs/btrfs/root-tree.c | 69 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 10 |
9 files changed, 459 insertions, 168 deletions
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index ea1ea0af8c0e..82ee56bba299 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h | |||
@@ -138,6 +138,7 @@ struct btrfs_inode { | |||
138 | * of these. | 138 | * of these. |
139 | */ | 139 | */ |
140 | unsigned ordered_data_close:1; | 140 | unsigned ordered_data_close:1; |
141 | unsigned dummy_inode:1; | ||
141 | 142 | ||
142 | struct inode vfs_inode; | 143 | struct inode vfs_inode; |
143 | }; | 144 | }; |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 746a9acd2189..6ade48b227e9 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -114,6 +114,10 @@ struct btrfs_ordered_sum; | |||
114 | */ | 114 | */ |
115 | #define BTRFS_DEV_ITEMS_OBJECTID 1ULL | 115 | #define BTRFS_DEV_ITEMS_OBJECTID 1ULL |
116 | 116 | ||
117 | #define BTRFS_BTREE_INODE_OBJECTID 1 | ||
118 | |||
119 | #define BTRFS_EMPTY_SUBVOL_DIR_OBJECTID 2 | ||
120 | |||
117 | /* | 121 | /* |
118 | * we can actually store much bigger names, but lets not confuse the rest | 122 | * we can actually store much bigger names, but lets not confuse the rest |
119 | * of linux | 123 | * of linux |
@@ -792,6 +796,8 @@ struct btrfs_fs_info { | |||
792 | 796 | ||
793 | /* the log root tree is a directory of all the other log roots */ | 797 | /* the log root tree is a directory of all the other log roots */ |
794 | struct btrfs_root *log_root_tree; | 798 | struct btrfs_root *log_root_tree; |
799 | |||
800 | spinlock_t fs_roots_radix_lock; | ||
795 | struct radix_tree_root fs_roots_radix; | 801 | struct radix_tree_root fs_roots_radix; |
796 | 802 | ||
797 | /* block group cache stuff */ | 803 | /* block group cache stuff */ |
@@ -1011,6 +1017,8 @@ struct btrfs_root { | |||
1011 | u64 highest_objectid; | 1017 | u64 highest_objectid; |
1012 | int ref_cows; | 1018 | int ref_cows; |
1013 | int track_dirty; | 1019 | int track_dirty; |
1020 | int in_radix; | ||
1021 | |||
1014 | u64 defrag_trans_start; | 1022 | u64 defrag_trans_start; |
1015 | struct btrfs_key defrag_progress; | 1023 | struct btrfs_key defrag_progress; |
1016 | struct btrfs_key defrag_max; | 1024 | struct btrfs_key defrag_max; |
@@ -2111,12 +2119,15 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans, | |||
2111 | struct extent_buffer *parent); | 2119 | struct extent_buffer *parent); |
2112 | /* root-item.c */ | 2120 | /* root-item.c */ |
2113 | int btrfs_find_root_ref(struct btrfs_root *tree_root, | 2121 | int btrfs_find_root_ref(struct btrfs_root *tree_root, |
2114 | struct btrfs_path *path, | 2122 | struct btrfs_path *path, |
2115 | u64 root_id, u64 ref_id); | 2123 | u64 root_id, u64 ref_id); |
2116 | int btrfs_add_root_ref(struct btrfs_trans_handle *trans, | 2124 | int btrfs_add_root_ref(struct btrfs_trans_handle *trans, |
2117 | struct btrfs_root *tree_root, | 2125 | struct btrfs_root *tree_root, |
2118 | u64 root_id, u8 type, u64 ref_id, | 2126 | u64 root_id, u64 ref_id, u64 dirid, u64 sequence, |
2119 | u64 dirid, u64 sequence, | 2127 | const char *name, int name_len); |
2128 | int btrfs_del_root_ref(struct btrfs_trans_handle *trans, | ||
2129 | struct btrfs_root *tree_root, | ||
2130 | u64 root_id, u64 ref_id, u64 dirid, u64 *sequence, | ||
2120 | const char *name, int name_len); | 2131 | const char *name, int name_len); |
2121 | int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 2132 | int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
2122 | struct btrfs_key *key); | 2133 | struct btrfs_key *key); |
@@ -2149,6 +2160,10 @@ btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, | |||
2149 | struct btrfs_path *path, u64 dir, | 2160 | struct btrfs_path *path, u64 dir, |
2150 | u64 objectid, const char *name, int name_len, | 2161 | u64 objectid, const char *name, int name_len, |
2151 | int mod); | 2162 | int mod); |
2163 | struct btrfs_dir_item * | ||
2164 | btrfs_search_dir_index_item(struct btrfs_root *root, | ||
2165 | struct btrfs_path *path, u64 dirid, | ||
2166 | const char *name, int name_len); | ||
2152 | struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, | 2167 | struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, |
2153 | struct btrfs_path *path, | 2168 | struct btrfs_path *path, |
2154 | const char *name, int name_len); | 2169 | const char *name, int name_len); |
@@ -2171,6 +2186,7 @@ int btrfs_insert_orphan_item(struct btrfs_trans_handle *trans, | |||
2171 | struct btrfs_root *root, u64 offset); | 2186 | struct btrfs_root *root, u64 offset); |
2172 | int btrfs_del_orphan_item(struct btrfs_trans_handle *trans, | 2187 | int btrfs_del_orphan_item(struct btrfs_trans_handle *trans, |
2173 | struct btrfs_root *root, u64 offset); | 2188 | struct btrfs_root *root, u64 offset); |
2189 | int btrfs_find_orphan_item(struct btrfs_root *root, u64 offset); | ||
2174 | 2190 | ||
2175 | /* inode-map.c */ | 2191 | /* inode-map.c */ |
2176 | int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, | 2192 | int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, |
@@ -2243,6 +2259,10 @@ int btrfs_unlink_inode(struct btrfs_trans_handle *trans, | |||
2243 | int btrfs_add_link(struct btrfs_trans_handle *trans, | 2259 | int btrfs_add_link(struct btrfs_trans_handle *trans, |
2244 | struct inode *parent_inode, struct inode *inode, | 2260 | struct inode *parent_inode, struct inode *inode, |
2245 | const char *name, int name_len, int add_backref, u64 index); | 2261 | const char *name, int name_len, int add_backref, u64 index); |
2262 | int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, | ||
2263 | struct btrfs_root *root, | ||
2264 | struct inode *dir, u64 objectid, | ||
2265 | const char *name, int name_len); | ||
2246 | int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, | 2266 | int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, |
2247 | struct btrfs_root *root, | 2267 | struct btrfs_root *root, |
2248 | struct inode *inode, u64 new_size, | 2268 | struct inode *inode, u64 new_size, |
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c index 1d70236ba00c..f3a6075519cc 100644 --- a/fs/btrfs/dir-item.c +++ b/fs/btrfs/dir-item.c | |||
@@ -281,6 +281,53 @@ btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, | |||
281 | return btrfs_match_dir_item_name(root, path, name, name_len); | 281 | return btrfs_match_dir_item_name(root, path, name, name_len); |
282 | } | 282 | } |
283 | 283 | ||
284 | struct btrfs_dir_item * | ||
285 | btrfs_search_dir_index_item(struct btrfs_root *root, | ||
286 | struct btrfs_path *path, u64 dirid, | ||
287 | const char *name, int name_len) | ||
288 | { | ||
289 | struct extent_buffer *leaf; | ||
290 | struct btrfs_dir_item *di; | ||
291 | struct btrfs_key key; | ||
292 | u32 nritems; | ||
293 | int ret; | ||
294 | |||
295 | key.objectid = dirid; | ||
296 | key.type = BTRFS_DIR_INDEX_KEY; | ||
297 | key.offset = 0; | ||
298 | |||
299 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | ||
300 | if (ret < 0) | ||
301 | return ERR_PTR(ret); | ||
302 | |||
303 | leaf = path->nodes[0]; | ||
304 | nritems = btrfs_header_nritems(leaf); | ||
305 | |||
306 | while (1) { | ||
307 | if (path->slots[0] >= nritems) { | ||
308 | ret = btrfs_next_leaf(root, path); | ||
309 | if (ret < 0) | ||
310 | return ERR_PTR(ret); | ||
311 | if (ret > 0) | ||
312 | break; | ||
313 | leaf = path->nodes[0]; | ||
314 | nritems = btrfs_header_nritems(leaf); | ||
315 | continue; | ||
316 | } | ||
317 | |||
318 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); | ||
319 | if (key.objectid != dirid || key.type != BTRFS_DIR_INDEX_KEY) | ||
320 | break; | ||
321 | |||
322 | di = btrfs_match_dir_item_name(root, path, name, name_len); | ||
323 | if (di) | ||
324 | return di; | ||
325 | |||
326 | path->slots[0]++; | ||
327 | } | ||
328 | return NULL; | ||
329 | } | ||
330 | |||
284 | struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, | 331 | struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, |
285 | struct btrfs_root *root, | 332 | struct btrfs_root *root, |
286 | struct btrfs_path *path, u64 dir, | 333 | struct btrfs_path *path, u64 dir, |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 790f4b61a3d7..a4f531047c4a 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -41,6 +41,7 @@ | |||
41 | 41 | ||
42 | static struct extent_io_ops btree_extent_io_ops; | 42 | static struct extent_io_ops btree_extent_io_ops; |
43 | static void end_workqueue_fn(struct btrfs_work *work); | 43 | static void end_workqueue_fn(struct btrfs_work *work); |
44 | static void free_fs_root(struct btrfs_root *root); | ||
44 | 45 | ||
45 | static atomic_t btrfs_bdi_num = ATOMIC_INIT(0); | 46 | static atomic_t btrfs_bdi_num = ATOMIC_INIT(0); |
46 | 47 | ||
@@ -951,14 +952,16 @@ static int find_and_setup_root(struct btrfs_root *tree_root, | |||
951 | root, fs_info, objectid); | 952 | root, fs_info, objectid); |
952 | ret = btrfs_find_last_root(tree_root, objectid, | 953 | ret = btrfs_find_last_root(tree_root, objectid, |
953 | &root->root_item, &root->root_key); | 954 | &root->root_item, &root->root_key); |
955 | if (ret > 0) | ||
956 | return -ENOENT; | ||
954 | BUG_ON(ret); | 957 | BUG_ON(ret); |
955 | 958 | ||
956 | generation = btrfs_root_generation(&root->root_item); | 959 | generation = btrfs_root_generation(&root->root_item); |
957 | blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); | 960 | blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item)); |
958 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), | 961 | root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item), |
959 | blocksize, generation); | 962 | blocksize, generation); |
960 | root->commit_root = btrfs_root_node(root); | ||
961 | BUG_ON(!root->node); | 963 | BUG_ON(!root->node); |
964 | root->commit_root = btrfs_root_node(root); | ||
962 | return 0; | 965 | return 0; |
963 | } | 966 | } |
964 | 967 | ||
@@ -1176,39 +1179,66 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info, | |||
1176 | return fs_info->dev_root; | 1179 | return fs_info->dev_root; |
1177 | if (location->objectid == BTRFS_CSUM_TREE_OBJECTID) | 1180 | if (location->objectid == BTRFS_CSUM_TREE_OBJECTID) |
1178 | return fs_info->csum_root; | 1181 | return fs_info->csum_root; |
1179 | 1182 | again: | |
1183 | spin_lock(&fs_info->fs_roots_radix_lock); | ||
1180 | root = radix_tree_lookup(&fs_info->fs_roots_radix, | 1184 | root = radix_tree_lookup(&fs_info->fs_roots_radix, |
1181 | (unsigned long)location->objectid); | 1185 | (unsigned long)location->objectid); |
1186 | spin_unlock(&fs_info->fs_roots_radix_lock); | ||
1182 | if (root) | 1187 | if (root) |
1183 | return root; | 1188 | return root; |
1184 | 1189 | ||
1190 | ret = btrfs_find_orphan_item(fs_info->tree_root, location->objectid); | ||
1191 | if (ret == 0) | ||
1192 | ret = -ENOENT; | ||
1193 | if (ret < 0) | ||
1194 | return ERR_PTR(ret); | ||
1195 | |||
1185 | root = btrfs_read_fs_root_no_radix(fs_info->tree_root, location); | 1196 | root = btrfs_read_fs_root_no_radix(fs_info->tree_root, location); |
1186 | if (IS_ERR(root)) | 1197 | if (IS_ERR(root)) |
1187 | return root; | 1198 | return root; |
1188 | 1199 | ||
1200 | WARN_ON(btrfs_root_refs(&root->root_item) == 0); | ||
1189 | set_anon_super(&root->anon_super, NULL); | 1201 | set_anon_super(&root->anon_super, NULL); |
1190 | 1202 | ||
1203 | ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM); | ||
1204 | if (ret) | ||
1205 | goto fail; | ||
1206 | |||
1207 | spin_lock(&fs_info->fs_roots_radix_lock); | ||
1191 | ret = radix_tree_insert(&fs_info->fs_roots_radix, | 1208 | ret = radix_tree_insert(&fs_info->fs_roots_radix, |
1192 | (unsigned long)root->root_key.objectid, | 1209 | (unsigned long)root->root_key.objectid, |
1193 | root); | 1210 | root); |
1211 | if (ret == 0) | ||
1212 | root->in_radix = 1; | ||
1213 | spin_unlock(&fs_info->fs_roots_radix_lock); | ||
1214 | radix_tree_preload_end(); | ||
1194 | if (ret) { | 1215 | if (ret) { |
1195 | free_extent_buffer(root->node); | 1216 | if (ret == -EEXIST) { |
1196 | kfree(root); | 1217 | free_fs_root(root); |
1197 | return ERR_PTR(ret); | 1218 | goto again; |
1219 | } | ||
1220 | goto fail; | ||
1198 | } | 1221 | } |
1199 | if (!(fs_info->sb->s_flags & MS_RDONLY)) { | 1222 | |
1200 | ret = btrfs_find_dead_roots(fs_info->tree_root, | 1223 | ret = btrfs_find_dead_roots(fs_info->tree_root, |
1201 | root->root_key.objectid); | 1224 | root->root_key.objectid); |
1202 | BUG_ON(ret); | 1225 | WARN_ON(ret); |
1226 | |||
1227 | if (!(fs_info->sb->s_flags & MS_RDONLY)) | ||
1203 | btrfs_orphan_cleanup(root); | 1228 | btrfs_orphan_cleanup(root); |
1204 | } | 1229 | |
1205 | return root; | 1230 | return root; |
1231 | fail: | ||
1232 | free_fs_root(root); | ||
1233 | return ERR_PTR(ret); | ||
1206 | } | 1234 | } |
1207 | 1235 | ||
1208 | struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, | 1236 | struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, |
1209 | struct btrfs_key *location, | 1237 | struct btrfs_key *location, |
1210 | const char *name, int namelen) | 1238 | const char *name, int namelen) |
1211 | { | 1239 | { |
1240 | return btrfs_read_fs_root_no_name(fs_info, location); | ||
1241 | #if 0 | ||
1212 | struct btrfs_root *root; | 1242 | struct btrfs_root *root; |
1213 | int ret; | 1243 | int ret; |
1214 | 1244 | ||
@@ -1225,7 +1255,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, | |||
1225 | kfree(root); | 1255 | kfree(root); |
1226 | return ERR_PTR(ret); | 1256 | return ERR_PTR(ret); |
1227 | } | 1257 | } |
1228 | #if 0 | 1258 | |
1229 | ret = btrfs_sysfs_add_root(root); | 1259 | ret = btrfs_sysfs_add_root(root); |
1230 | if (ret) { | 1260 | if (ret) { |
1231 | free_extent_buffer(root->node); | 1261 | free_extent_buffer(root->node); |
@@ -1233,9 +1263,9 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, | |||
1233 | kfree(root); | 1263 | kfree(root); |
1234 | return ERR_PTR(ret); | 1264 | return ERR_PTR(ret); |
1235 | } | 1265 | } |
1236 | #endif | ||
1237 | root->in_sysfs = 1; | 1266 | root->in_sysfs = 1; |
1238 | return root; | 1267 | return root; |
1268 | #endif | ||
1239 | } | 1269 | } |
1240 | 1270 | ||
1241 | static int btrfs_congested_fn(void *congested_data, int bdi_bits) | 1271 | static int btrfs_congested_fn(void *congested_data, int bdi_bits) |
@@ -2229,20 +2259,25 @@ int write_ctree_super(struct btrfs_trans_handle *trans, | |||
2229 | 2259 | ||
2230 | int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) | 2260 | int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) |
2231 | { | 2261 | { |
2232 | WARN_ON(!RB_EMPTY_ROOT(&root->inode_tree)); | 2262 | spin_lock(&fs_info->fs_roots_radix_lock); |
2233 | radix_tree_delete(&fs_info->fs_roots_radix, | 2263 | radix_tree_delete(&fs_info->fs_roots_radix, |
2234 | (unsigned long)root->root_key.objectid); | 2264 | (unsigned long)root->root_key.objectid); |
2265 | spin_unlock(&fs_info->fs_roots_radix_lock); | ||
2266 | free_fs_root(root); | ||
2267 | return 0; | ||
2268 | } | ||
2269 | |||
2270 | static void free_fs_root(struct btrfs_root *root) | ||
2271 | { | ||
2272 | WARN_ON(!RB_EMPTY_ROOT(&root->inode_tree)); | ||
2235 | if (root->anon_super.s_dev) { | 2273 | if (root->anon_super.s_dev) { |
2236 | down_write(&root->anon_super.s_umount); | 2274 | down_write(&root->anon_super.s_umount); |
2237 | kill_anon_super(&root->anon_super); | 2275 | kill_anon_super(&root->anon_super); |
2238 | } | 2276 | } |
2239 | if (root->node) | 2277 | free_extent_buffer(root->node); |
2240 | free_extent_buffer(root->node); | 2278 | free_extent_buffer(root->commit_root); |
2241 | if (root->commit_root) | ||
2242 | free_extent_buffer(root->commit_root); | ||
2243 | kfree(root->name); | 2279 | kfree(root->name); |
2244 | kfree(root); | 2280 | kfree(root); |
2245 | return 0; | ||
2246 | } | 2281 | } |
2247 | 2282 | ||
2248 | static int del_fs_roots(struct btrfs_fs_info *fs_info) | 2283 | static int del_fs_roots(struct btrfs_fs_info *fs_info) |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 9e81f3184f24..6036b36789cc 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -2373,6 +2373,69 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | |||
2373 | return ret; | 2373 | return ret; |
2374 | } | 2374 | } |
2375 | 2375 | ||
2376 | int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, | ||
2377 | struct btrfs_root *root, | ||
2378 | struct inode *dir, u64 objectid, | ||
2379 | const char *name, int name_len) | ||
2380 | { | ||
2381 | struct btrfs_path *path; | ||
2382 | struct extent_buffer *leaf; | ||
2383 | struct btrfs_dir_item *di; | ||
2384 | struct btrfs_key key; | ||
2385 | u64 index; | ||
2386 | int ret; | ||
2387 | |||
2388 | path = btrfs_alloc_path(); | ||
2389 | if (!path) | ||
2390 | return -ENOMEM; | ||
2391 | |||
2392 | di = btrfs_lookup_dir_item(trans, root, path, dir->i_ino, | ||
2393 | name, name_len, -1); | ||
2394 | BUG_ON(!di || IS_ERR(di)); | ||
2395 | |||
2396 | leaf = path->nodes[0]; | ||
2397 | btrfs_dir_item_key_to_cpu(leaf, di, &key); | ||
2398 | WARN_ON(key.type != BTRFS_ROOT_ITEM_KEY || key.objectid != objectid); | ||
2399 | ret = btrfs_delete_one_dir_name(trans, root, path, di); | ||
2400 | BUG_ON(ret); | ||
2401 | btrfs_release_path(root, path); | ||
2402 | |||
2403 | ret = btrfs_del_root_ref(trans, root->fs_info->tree_root, | ||
2404 | objectid, root->root_key.objectid, | ||
2405 | dir->i_ino, &index, name, name_len); | ||
2406 | if (ret < 0) { | ||
2407 | BUG_ON(ret != -ENOENT); | ||
2408 | di = btrfs_search_dir_index_item(root, path, dir->i_ino, | ||
2409 | name, name_len); | ||
2410 | BUG_ON(!di || IS_ERR(di)); | ||
2411 | |||
2412 | leaf = path->nodes[0]; | ||
2413 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); | ||
2414 | btrfs_release_path(root, path); | ||
2415 | index = key.offset; | ||
2416 | } | ||
2417 | |||
2418 | di = btrfs_lookup_dir_index_item(trans, root, path, dir->i_ino, | ||
2419 | index, name, name_len, -1); | ||
2420 | BUG_ON(!di || IS_ERR(di)); | ||
2421 | |||
2422 | leaf = path->nodes[0]; | ||
2423 | btrfs_dir_item_key_to_cpu(leaf, di, &key); | ||
2424 | WARN_ON(key.type != BTRFS_ROOT_ITEM_KEY || key.objectid != objectid); | ||
2425 | ret = btrfs_delete_one_dir_name(trans, root, path, di); | ||
2426 | BUG_ON(ret); | ||
2427 | btrfs_release_path(root, path); | ||
2428 | |||
2429 | btrfs_i_size_write(dir, dir->i_size - name_len * 2); | ||
2430 | dir->i_mtime = dir->i_ctime = CURRENT_TIME; | ||
2431 | ret = btrfs_update_inode(trans, root, dir); | ||
2432 | BUG_ON(ret); | ||
2433 | dir->i_sb->s_dirt = 1; | ||
2434 | |||
2435 | btrfs_free_path(path); | ||
2436 | return 0; | ||
2437 | } | ||
2438 | |||
2376 | static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) | 2439 | static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) |
2377 | { | 2440 | { |
2378 | struct inode *inode = dentry->d_inode; | 2441 | struct inode *inode = dentry->d_inode; |
@@ -2382,29 +2445,31 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
2382 | struct btrfs_trans_handle *trans; | 2445 | struct btrfs_trans_handle *trans; |
2383 | unsigned long nr = 0; | 2446 | unsigned long nr = 0; |
2384 | 2447 | ||
2385 | /* | ||
2386 | * the FIRST_FREE_OBJECTID check makes sure we don't try to rmdir | ||
2387 | * the root of a subvolume or snapshot | ||
2388 | */ | ||
2389 | if (inode->i_size > BTRFS_EMPTY_DIR_SIZE || | 2448 | if (inode->i_size > BTRFS_EMPTY_DIR_SIZE || |
2390 | inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) { | 2449 | inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) |
2391 | return -ENOTEMPTY; | 2450 | return -ENOTEMPTY; |
2392 | } | ||
2393 | 2451 | ||
2394 | trans = btrfs_start_transaction(root, 1); | 2452 | trans = btrfs_start_transaction(root, 1); |
2395 | btrfs_set_trans_block_group(trans, dir); | 2453 | btrfs_set_trans_block_group(trans, dir); |
2396 | 2454 | ||
2455 | if (unlikely(inode->i_ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) { | ||
2456 | err = btrfs_unlink_subvol(trans, root, dir, | ||
2457 | BTRFS_I(inode)->location.objectid, | ||
2458 | dentry->d_name.name, | ||
2459 | dentry->d_name.len); | ||
2460 | goto out; | ||
2461 | } | ||
2462 | |||
2397 | err = btrfs_orphan_add(trans, inode); | 2463 | err = btrfs_orphan_add(trans, inode); |
2398 | if (err) | 2464 | if (err) |
2399 | goto fail_trans; | 2465 | goto out; |
2400 | 2466 | ||
2401 | /* now the directory is empty */ | 2467 | /* now the directory is empty */ |
2402 | err = btrfs_unlink_inode(trans, root, dir, dentry->d_inode, | 2468 | err = btrfs_unlink_inode(trans, root, dir, dentry->d_inode, |
2403 | dentry->d_name.name, dentry->d_name.len); | 2469 | dentry->d_name.name, dentry->d_name.len); |
2404 | if (!err) | 2470 | if (!err) |
2405 | btrfs_i_size_write(inode, 0); | 2471 | btrfs_i_size_write(inode, 0); |
2406 | 2472 | out: | |
2407 | fail_trans: | ||
2408 | nr = trans->blocks_used; | 2473 | nr = trans->blocks_used; |
2409 | ret = btrfs_end_transaction_throttle(trans, root); | 2474 | ret = btrfs_end_transaction_throttle(trans, root); |
2410 | btrfs_btree_balance_dirty(root, nr); | 2475 | btrfs_btree_balance_dirty(root, nr); |
@@ -3091,29 +3156,67 @@ out_err: | |||
3091 | * is kind of like crossing a mount point. | 3156 | * is kind of like crossing a mount point. |
3092 | */ | 3157 | */ |
3093 | static int fixup_tree_root_location(struct btrfs_root *root, | 3158 | static int fixup_tree_root_location(struct btrfs_root *root, |
3094 | struct btrfs_key *location, | 3159 | struct inode *dir, |
3095 | struct btrfs_root **sub_root, | 3160 | struct dentry *dentry, |
3096 | struct dentry *dentry) | 3161 | struct btrfs_key *location, |
3162 | struct btrfs_root **sub_root) | ||
3097 | { | 3163 | { |
3098 | struct btrfs_root_item *ri; | 3164 | struct btrfs_path *path; |
3165 | struct btrfs_root *new_root; | ||
3166 | struct btrfs_root_ref *ref; | ||
3167 | struct extent_buffer *leaf; | ||
3168 | int ret; | ||
3169 | int err = 0; | ||
3099 | 3170 | ||
3100 | if (btrfs_key_type(location) != BTRFS_ROOT_ITEM_KEY) | 3171 | path = btrfs_alloc_path(); |
3101 | return 0; | 3172 | if (!path) { |
3102 | if (location->objectid == BTRFS_ROOT_TREE_OBJECTID) | 3173 | err = -ENOMEM; |
3103 | return 0; | 3174 | goto out; |
3175 | } | ||
3104 | 3176 | ||
3105 | *sub_root = btrfs_read_fs_root(root->fs_info, location, | 3177 | err = -ENOENT; |
3106 | dentry->d_name.name, | 3178 | ret = btrfs_find_root_ref(root->fs_info->tree_root, path, |
3107 | dentry->d_name.len); | 3179 | BTRFS_I(dir)->root->root_key.objectid, |
3108 | if (IS_ERR(*sub_root)) | 3180 | location->objectid); |
3109 | return PTR_ERR(*sub_root); | 3181 | if (ret) { |
3182 | if (ret < 0) | ||
3183 | err = ret; | ||
3184 | goto out; | ||
3185 | } | ||
3110 | 3186 | ||
3111 | ri = &(*sub_root)->root_item; | 3187 | leaf = path->nodes[0]; |
3112 | location->objectid = btrfs_root_dirid(ri); | 3188 | ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref); |
3113 | btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY); | 3189 | if (btrfs_root_ref_dirid(leaf, ref) != dir->i_ino || |
3114 | location->offset = 0; | 3190 | btrfs_root_ref_name_len(leaf, ref) != dentry->d_name.len) |
3191 | goto out; | ||
3115 | 3192 | ||
3116 | return 0; | 3193 | ret = memcmp_extent_buffer(leaf, dentry->d_name.name, |
3194 | (unsigned long)(ref + 1), | ||
3195 | dentry->d_name.len); | ||
3196 | if (ret) | ||
3197 | goto out; | ||
3198 | |||
3199 | btrfs_release_path(root->fs_info->tree_root, path); | ||
3200 | |||
3201 | new_root = btrfs_read_fs_root_no_name(root->fs_info, location); | ||
3202 | if (IS_ERR(new_root)) { | ||
3203 | err = PTR_ERR(new_root); | ||
3204 | goto out; | ||
3205 | } | ||
3206 | |||
3207 | if (btrfs_root_refs(&new_root->root_item) == 0) { | ||
3208 | err = -ENOENT; | ||
3209 | goto out; | ||
3210 | } | ||
3211 | |||
3212 | *sub_root = new_root; | ||
3213 | location->objectid = btrfs_root_dirid(&new_root->root_item); | ||
3214 | location->type = BTRFS_INODE_ITEM_KEY; | ||
3215 | location->offset = 0; | ||
3216 | err = 0; | ||
3217 | out: | ||
3218 | btrfs_free_path(path); | ||
3219 | return err; | ||
3117 | } | 3220 | } |
3118 | 3221 | ||
3119 | static void inode_tree_add(struct inode *inode) | 3222 | static void inode_tree_add(struct inode *inode) |
@@ -3246,11 +3349,34 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location, | |||
3246 | return inode; | 3349 | return inode; |
3247 | } | 3350 | } |
3248 | 3351 | ||
3352 | static struct inode *new_simple_dir(struct super_block *s, | ||
3353 | struct btrfs_key *key, | ||
3354 | struct btrfs_root *root) | ||
3355 | { | ||
3356 | struct inode *inode = new_inode(s); | ||
3357 | |||
3358 | if (!inode) | ||
3359 | return ERR_PTR(-ENOMEM); | ||
3360 | |||
3361 | init_btrfs_i(inode); | ||
3362 | |||
3363 | BTRFS_I(inode)->root = root; | ||
3364 | memcpy(&BTRFS_I(inode)->location, key, sizeof(*key)); | ||
3365 | BTRFS_I(inode)->dummy_inode = 1; | ||
3366 | |||
3367 | inode->i_ino = BTRFS_EMPTY_SUBVOL_DIR_OBJECTID; | ||
3368 | inode->i_op = &simple_dir_inode_operations; | ||
3369 | inode->i_fop = &simple_dir_operations; | ||
3370 | inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO; | ||
3371 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | ||
3372 | |||
3373 | return inode; | ||
3374 | } | ||
3375 | |||
3249 | struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) | 3376 | struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) |
3250 | { | 3377 | { |
3251 | struct inode *inode; | 3378 | struct inode *inode; |
3252 | struct btrfs_inode *bi = BTRFS_I(dir); | 3379 | struct btrfs_root *root = BTRFS_I(dir)->root; |
3253 | struct btrfs_root *root = bi->root; | ||
3254 | struct btrfs_root *sub_root = root; | 3380 | struct btrfs_root *sub_root = root; |
3255 | struct btrfs_key location; | 3381 | struct btrfs_key location; |
3256 | int ret; | 3382 | int ret; |
@@ -3263,17 +3389,25 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) | |||
3263 | if (ret < 0) | 3389 | if (ret < 0) |
3264 | return ERR_PTR(ret); | 3390 | return ERR_PTR(ret); |
3265 | 3391 | ||
3266 | inode = NULL; | 3392 | if (location.objectid == 0) |
3267 | if (location.objectid) { | 3393 | return NULL; |
3268 | ret = fixup_tree_root_location(root, &location, &sub_root, | 3394 | |
3269 | dentry); | 3395 | if (location.type == BTRFS_INODE_ITEM_KEY) { |
3270 | if (ret < 0) | 3396 | inode = btrfs_iget(dir->i_sb, &location, root); |
3271 | return ERR_PTR(ret); | 3397 | return inode; |
3272 | if (ret > 0) | 3398 | } |
3273 | return ERR_PTR(-ENOENT); | 3399 | |
3400 | BUG_ON(location.type != BTRFS_ROOT_ITEM_KEY); | ||
3401 | |||
3402 | ret = fixup_tree_root_location(root, dir, dentry, | ||
3403 | &location, &sub_root); | ||
3404 | if (ret < 0) { | ||
3405 | if (ret != -ENOENT) | ||
3406 | inode = ERR_PTR(ret); | ||
3407 | else | ||
3408 | inode = new_simple_dir(dir->i_sb, &location, sub_root); | ||
3409 | } else { | ||
3274 | inode = btrfs_iget(dir->i_sb, &location, sub_root); | 3410 | inode = btrfs_iget(dir->i_sb, &location, sub_root); |
3275 | if (IS_ERR(inode)) | ||
3276 | return ERR_CAST(inode); | ||
3277 | } | 3411 | } |
3278 | return inode; | 3412 | return inode; |
3279 | } | 3413 | } |
@@ -3283,9 +3417,6 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | |||
3283 | { | 3417 | { |
3284 | struct inode *inode; | 3418 | struct inode *inode; |
3285 | 3419 | ||
3286 | if (dentry->d_name.len > BTRFS_NAME_LEN) | ||
3287 | return ERR_PTR(-ENAMETOOLONG); | ||
3288 | |||
3289 | inode = btrfs_lookup_dentry(dir, dentry); | 3420 | inode = btrfs_lookup_dentry(dir, dentry); |
3290 | if (IS_ERR(inode)) | 3421 | if (IS_ERR(inode)) |
3291 | return ERR_CAST(inode); | 3422 | return ERR_CAST(inode); |
@@ -3691,26 +3822,35 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, | |||
3691 | struct inode *parent_inode, struct inode *inode, | 3822 | struct inode *parent_inode, struct inode *inode, |
3692 | const char *name, int name_len, int add_backref, u64 index) | 3823 | const char *name, int name_len, int add_backref, u64 index) |
3693 | { | 3824 | { |
3694 | int ret; | 3825 | int ret = 0; |
3695 | struct btrfs_key key; | 3826 | struct btrfs_key key; |
3696 | struct btrfs_root *root = BTRFS_I(parent_inode)->root; | 3827 | struct btrfs_root *root = BTRFS_I(parent_inode)->root; |
3697 | 3828 | ||
3698 | key.objectid = inode->i_ino; | 3829 | if (unlikely(inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)) { |
3699 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); | 3830 | memcpy(&key, &BTRFS_I(inode)->root->root_key, sizeof(key)); |
3700 | key.offset = 0; | 3831 | } else { |
3832 | key.objectid = inode->i_ino; | ||
3833 | btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); | ||
3834 | key.offset = 0; | ||
3835 | } | ||
3836 | |||
3837 | if (unlikely(inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)) { | ||
3838 | ret = btrfs_add_root_ref(trans, root->fs_info->tree_root, | ||
3839 | key.objectid, root->root_key.objectid, | ||
3840 | parent_inode->i_ino, | ||
3841 | index, name, name_len); | ||
3842 | } else if (add_backref) { | ||
3843 | ret = btrfs_insert_inode_ref(trans, root, | ||
3844 | name, name_len, inode->i_ino, | ||
3845 | parent_inode->i_ino, index); | ||
3846 | } | ||
3701 | 3847 | ||
3702 | ret = btrfs_insert_dir_item(trans, root, name, name_len, | ||
3703 | parent_inode->i_ino, | ||
3704 | &key, btrfs_inode_type(inode), | ||
3705 | index); | ||
3706 | if (ret == 0) { | 3848 | if (ret == 0) { |
3707 | if (add_backref) { | 3849 | ret = btrfs_insert_dir_item(trans, root, name, name_len, |
3708 | ret = btrfs_insert_inode_ref(trans, root, | 3850 | parent_inode->i_ino, &key, |
3709 | name, name_len, | 3851 | btrfs_inode_type(inode), index); |
3710 | inode->i_ino, | 3852 | BUG_ON(ret); |
3711 | parent_inode->i_ino, | 3853 | |
3712 | index); | ||
3713 | } | ||
3714 | btrfs_i_size_write(parent_inode, parent_inode->i_size + | 3854 | btrfs_i_size_write(parent_inode, parent_inode->i_size + |
3715 | name_len * 2); | 3855 | name_len * 2); |
3716 | parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME; | 3856 | parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME; |
@@ -4800,31 +4940,29 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
4800 | { | 4940 | { |
4801 | struct btrfs_trans_handle *trans; | 4941 | struct btrfs_trans_handle *trans; |
4802 | struct btrfs_root *root = BTRFS_I(old_dir)->root; | 4942 | struct btrfs_root *root = BTRFS_I(old_dir)->root; |
4943 | struct btrfs_root *dest = BTRFS_I(new_dir)->root; | ||
4803 | struct inode *new_inode = new_dentry->d_inode; | 4944 | struct inode *new_inode = new_dentry->d_inode; |
4804 | struct inode *old_inode = old_dentry->d_inode; | 4945 | struct inode *old_inode = old_dentry->d_inode; |
4805 | struct timespec ctime = CURRENT_TIME; | 4946 | struct timespec ctime = CURRENT_TIME; |
4806 | u64 index = 0; | 4947 | u64 index = 0; |
4948 | u64 root_objectid; | ||
4807 | int ret; | 4949 | int ret; |
4808 | 4950 | ||
4809 | /* we're not allowed to rename between subvolumes */ | 4951 | /* we only allow rename subvolume link between subvolumes */ |
4810 | if (BTRFS_I(old_inode)->root->root_key.objectid != | 4952 | if (old_inode->i_ino != BTRFS_FIRST_FREE_OBJECTID && root != dest) |
4811 | BTRFS_I(new_dir)->root->root_key.objectid) | ||
4812 | return -EXDEV; | 4953 | return -EXDEV; |
4813 | 4954 | ||
4814 | if (S_ISDIR(old_inode->i_mode) && new_inode && | 4955 | if (old_inode->i_ino == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID || |
4815 | new_inode->i_size > BTRFS_EMPTY_DIR_SIZE) { | 4956 | (new_inode && new_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)) |
4816 | return -ENOTEMPTY; | 4957 | return -ENOTEMPTY; |
4817 | } | ||
4818 | 4958 | ||
4819 | /* to rename a snapshot or subvolume, we need to juggle the | 4959 | if (S_ISDIR(old_inode->i_mode) && new_inode && |
4820 | * backrefs. This isn't coded yet | 4960 | new_inode->i_size > BTRFS_EMPTY_DIR_SIZE) |
4821 | */ | 4961 | return -ENOTEMPTY; |
4822 | if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) | ||
4823 | return -EXDEV; | ||
4824 | 4962 | ||
4825 | ret = btrfs_check_metadata_free_space(root); | 4963 | ret = btrfs_check_metadata_free_space(root); |
4826 | if (ret) | 4964 | if (ret) |
4827 | goto out_unlock; | 4965 | return ret; |
4828 | 4966 | ||
4829 | /* | 4967 | /* |
4830 | * we're using rename to replace one file with another. | 4968 | * we're using rename to replace one file with another. |
@@ -4837,6 +4975,9 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
4837 | 4975 | ||
4838 | trans = btrfs_start_transaction(root, 1); | 4976 | trans = btrfs_start_transaction(root, 1); |
4839 | 4977 | ||
4978 | if (dest != root) | ||
4979 | btrfs_record_root_in_trans(trans, dest); | ||
4980 | |||
4840 | /* | 4981 | /* |
4841 | * make sure the inode gets flushed if it is replacing | 4982 | * make sure the inode gets flushed if it is replacing |
4842 | * something. | 4983 | * something. |
@@ -4846,18 +4987,22 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
4846 | btrfs_add_ordered_operation(trans, root, old_inode); | 4987 | btrfs_add_ordered_operation(trans, root, old_inode); |
4847 | } | 4988 | } |
4848 | 4989 | ||
4849 | /* | 4990 | if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) { |
4850 | * this is an ugly little race, but the rename is required to make | 4991 | /* force full log commit if subvolume involved. */ |
4851 | * sure that if we crash, the inode is either at the old name | 4992 | root->fs_info->last_trans_log_full_commit = trans->transid; |
4852 | * or the new one. pinning the log transaction lets us make sure | 4993 | } else { |
4853 | * we don't allow a log commit to come in after we unlink the | 4994 | /* |
4854 | * name but before we add the new name back in. | 4995 | * this is an ugly little race, but the rename is required |
4855 | */ | 4996 | * to make sure that if we crash, the inode is either at the |
4856 | btrfs_pin_log_trans(root); | 4997 | * old name or the new one. pinning the log transaction lets |
4998 | * us make sure we don't allow a log commit to come in after | ||
4999 | * we unlink the name but before we add the new name back in. | ||
5000 | */ | ||
5001 | btrfs_pin_log_trans(root); | ||
5002 | } | ||
4857 | 5003 | ||
4858 | btrfs_set_trans_block_group(trans, new_dir); | 5004 | btrfs_set_trans_block_group(trans, new_dir); |
4859 | 5005 | ||
4860 | btrfs_inc_nlink(old_dentry->d_inode); | ||
4861 | old_dir->i_ctime = old_dir->i_mtime = ctime; | 5006 | old_dir->i_ctime = old_dir->i_mtime = ctime; |
4862 | new_dir->i_ctime = new_dir->i_mtime = ctime; | 5007 | new_dir->i_ctime = new_dir->i_mtime = ctime; |
4863 | old_inode->i_ctime = ctime; | 5008 | old_inode->i_ctime = ctime; |
@@ -4865,47 +5010,58 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
4865 | if (old_dentry->d_parent != new_dentry->d_parent) | 5010 | if (old_dentry->d_parent != new_dentry->d_parent) |
4866 | btrfs_record_unlink_dir(trans, old_dir, old_inode, 1); | 5011 | btrfs_record_unlink_dir(trans, old_dir, old_inode, 1); |
4867 | 5012 | ||
4868 | ret = btrfs_unlink_inode(trans, root, old_dir, old_dentry->d_inode, | 5013 | if (unlikely(old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID)) { |
4869 | old_dentry->d_name.name, | 5014 | root_objectid = BTRFS_I(old_inode)->root->root_key.objectid; |
4870 | old_dentry->d_name.len); | 5015 | ret = btrfs_unlink_subvol(trans, root, old_dir, root_objectid, |
4871 | if (ret) | 5016 | old_dentry->d_name.name, |
4872 | goto out_fail; | 5017 | old_dentry->d_name.len); |
5018 | } else { | ||
5019 | btrfs_inc_nlink(old_dentry->d_inode); | ||
5020 | ret = btrfs_unlink_inode(trans, root, old_dir, | ||
5021 | old_dentry->d_inode, | ||
5022 | old_dentry->d_name.name, | ||
5023 | old_dentry->d_name.len); | ||
5024 | } | ||
5025 | BUG_ON(ret); | ||
4873 | 5026 | ||
4874 | if (new_inode) { | 5027 | if (new_inode) { |
4875 | new_inode->i_ctime = CURRENT_TIME; | 5028 | new_inode->i_ctime = CURRENT_TIME; |
4876 | ret = btrfs_unlink_inode(trans, root, new_dir, | 5029 | if (unlikely(new_inode->i_ino == |
4877 | new_dentry->d_inode, | 5030 | BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) { |
4878 | new_dentry->d_name.name, | 5031 | root_objectid = BTRFS_I(new_inode)->location.objectid; |
4879 | new_dentry->d_name.len); | 5032 | ret = btrfs_unlink_subvol(trans, dest, new_dir, |
4880 | if (ret) | 5033 | root_objectid, |
4881 | goto out_fail; | 5034 | new_dentry->d_name.name, |
5035 | new_dentry->d_name.len); | ||
5036 | BUG_ON(new_inode->i_nlink == 0); | ||
5037 | } else { | ||
5038 | ret = btrfs_unlink_inode(trans, dest, new_dir, | ||
5039 | new_dentry->d_inode, | ||
5040 | new_dentry->d_name.name, | ||
5041 | new_dentry->d_name.len); | ||
5042 | } | ||
5043 | BUG_ON(ret); | ||
4882 | if (new_inode->i_nlink == 0) { | 5044 | if (new_inode->i_nlink == 0) { |
4883 | ret = btrfs_orphan_add(trans, new_dentry->d_inode); | 5045 | ret = btrfs_orphan_add(trans, new_dentry->d_inode); |
4884 | if (ret) | 5046 | BUG_ON(ret); |
4885 | goto out_fail; | ||
4886 | } | 5047 | } |
4887 | |||
4888 | } | 5048 | } |
4889 | ret = btrfs_set_inode_index(new_dir, &index); | 5049 | ret = btrfs_set_inode_index(new_dir, &index); |
4890 | if (ret) | 5050 | BUG_ON(ret); |
4891 | goto out_fail; | ||
4892 | 5051 | ||
4893 | ret = btrfs_add_link(trans, new_dentry->d_parent->d_inode, | 5052 | ret = btrfs_add_link(trans, new_dir, old_inode, |
4894 | old_inode, new_dentry->d_name.name, | 5053 | new_dentry->d_name.name, |
4895 | new_dentry->d_name.len, 1, index); | 5054 | new_dentry->d_name.len, 1, index); |
4896 | if (ret) | 5055 | BUG_ON(ret); |
4897 | goto out_fail; | ||
4898 | 5056 | ||
4899 | btrfs_log_new_name(trans, old_inode, old_dir, | 5057 | if (old_inode->i_ino != BTRFS_FIRST_FREE_OBJECTID) { |
4900 | new_dentry->d_parent); | 5058 | btrfs_log_new_name(trans, old_inode, old_dir, |
4901 | out_fail: | 5059 | new_dentry->d_parent); |
5060 | btrfs_end_log_trans(root); | ||
5061 | } | ||
4902 | 5062 | ||
4903 | /* this btrfs_end_log_trans just allows the current | ||
4904 | * log-sub transaction to complete | ||
4905 | */ | ||
4906 | btrfs_end_log_trans(root); | ||
4907 | btrfs_end_transaction_throttle(trans, root); | 5063 | btrfs_end_transaction_throttle(trans, root); |
4908 | out_unlock: | 5064 | |
4909 | return ret; | 5065 | return ret; |
4910 | } | 5066 | } |
4911 | 5067 | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index ef0188fb3cc4..9b3a88755e51 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -322,20 +322,9 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
322 | ret = btrfs_update_inode(trans, root, dir); | 322 | ret = btrfs_update_inode(trans, root, dir); |
323 | BUG_ON(ret); | 323 | BUG_ON(ret); |
324 | 324 | ||
325 | /* add the backref first */ | ||
326 | ret = btrfs_add_root_ref(trans, root->fs_info->tree_root, | 325 | ret = btrfs_add_root_ref(trans, root->fs_info->tree_root, |
327 | objectid, BTRFS_ROOT_BACKREF_KEY, | 326 | objectid, root->root_key.objectid, |
328 | root->root_key.objectid, | ||
329 | dir->i_ino, index, name, namelen); | 327 | dir->i_ino, index, name, namelen); |
330 | |||
331 | BUG_ON(ret); | ||
332 | |||
333 | /* now add the forward ref */ | ||
334 | ret = btrfs_add_root_ref(trans, root->fs_info->tree_root, | ||
335 | root->root_key.objectid, BTRFS_ROOT_REF_KEY, | ||
336 | objectid, | ||
337 | dir->i_ino, index, name, namelen); | ||
338 | |||
339 | BUG_ON(ret); | 328 | BUG_ON(ret); |
340 | 329 | ||
341 | ret = btrfs_commit_transaction(trans, root); | 330 | ret = btrfs_commit_transaction(trans, root); |
diff --git a/fs/btrfs/orphan.c b/fs/btrfs/orphan.c index 3c0d52af4f80..79cba5fbc28e 100644 --- a/fs/btrfs/orphan.c +++ b/fs/btrfs/orphan.c | |||
@@ -65,3 +65,23 @@ out: | |||
65 | btrfs_free_path(path); | 65 | btrfs_free_path(path); |
66 | return ret; | 66 | return ret; |
67 | } | 67 | } |
68 | |||
69 | int btrfs_find_orphan_item(struct btrfs_root *root, u64 offset) | ||
70 | { | ||
71 | struct btrfs_path *path; | ||
72 | struct btrfs_key key; | ||
73 | int ret; | ||
74 | |||
75 | key.objectid = BTRFS_ORPHAN_OBJECTID; | ||
76 | key.type = BTRFS_ORPHAN_ITEM_KEY; | ||
77 | key.offset = offset; | ||
78 | |||
79 | path = btrfs_alloc_path(); | ||
80 | if (!path) | ||
81 | return -ENOMEM; | ||
82 | |||
83 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | ||
84 | |||
85 | btrfs_free_path(path); | ||
86 | return ret; | ||
87 | } | ||
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 0ddc6d61c55a..5ef72599a581 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c | |||
@@ -278,31 +278,57 @@ out: | |||
278 | return ret; | 278 | return ret; |
279 | } | 279 | } |
280 | 280 | ||
281 | #if 0 /* this will get used when snapshot deletion is implemented */ | ||
282 | int btrfs_del_root_ref(struct btrfs_trans_handle *trans, | 281 | int btrfs_del_root_ref(struct btrfs_trans_handle *trans, |
283 | struct btrfs_root *tree_root, | 282 | struct btrfs_root *tree_root, |
284 | u64 root_id, u8 type, u64 ref_id) | 283 | u64 root_id, u64 ref_id, u64 dirid, u64 *sequence, |
284 | const char *name, int name_len) | ||
285 | |||
285 | { | 286 | { |
287 | struct btrfs_path *path; | ||
288 | struct btrfs_root_ref *ref; | ||
289 | struct extent_buffer *leaf; | ||
286 | struct btrfs_key key; | 290 | struct btrfs_key key; |
291 | unsigned long ptr; | ||
292 | int err = 0; | ||
287 | int ret; | 293 | int ret; |
288 | struct btrfs_path *path; | ||
289 | 294 | ||
290 | path = btrfs_alloc_path(); | 295 | path = btrfs_alloc_path(); |
296 | if (!path) | ||
297 | return -ENOMEM; | ||
291 | 298 | ||
292 | key.objectid = root_id; | 299 | key.objectid = root_id; |
293 | key.type = type; | 300 | key.type = BTRFS_ROOT_BACKREF_KEY; |
294 | key.offset = ref_id; | 301 | key.offset = ref_id; |
295 | 302 | again: | |
296 | ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1); | 303 | ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1); |
297 | BUG_ON(ret); | 304 | BUG_ON(ret < 0); |
298 | 305 | if (ret == 0) { | |
299 | ret = btrfs_del_item(trans, tree_root, path); | 306 | leaf = path->nodes[0]; |
300 | BUG_ON(ret); | 307 | ref = btrfs_item_ptr(leaf, path->slots[0], |
308 | struct btrfs_root_ref); | ||
309 | |||
310 | WARN_ON(btrfs_root_ref_dirid(leaf, ref) != dirid); | ||
311 | WARN_ON(btrfs_root_ref_name_len(leaf, ref) != name_len); | ||
312 | ptr = (unsigned long)(ref + 1); | ||
313 | WARN_ON(memcmp_extent_buffer(leaf, name, ptr, name_len)); | ||
314 | *sequence = btrfs_root_ref_sequence(leaf, ref); | ||
315 | |||
316 | ret = btrfs_del_item(trans, tree_root, path); | ||
317 | BUG_ON(ret); | ||
318 | } else | ||
319 | err = -ENOENT; | ||
320 | |||
321 | if (key.type == BTRFS_ROOT_BACKREF_KEY) { | ||
322 | btrfs_release_path(tree_root, path); | ||
323 | key.objectid = ref_id; | ||
324 | key.type = BTRFS_ROOT_REF_KEY; | ||
325 | key.offset = root_id; | ||
326 | goto again; | ||
327 | } | ||
301 | 328 | ||
302 | btrfs_free_path(path); | 329 | btrfs_free_path(path); |
303 | return ret; | 330 | return err; |
304 | } | 331 | } |
305 | #endif | ||
306 | 332 | ||
307 | int btrfs_find_root_ref(struct btrfs_root *tree_root, | 333 | int btrfs_find_root_ref(struct btrfs_root *tree_root, |
308 | struct btrfs_path *path, | 334 | struct btrfs_path *path, |
@@ -319,7 +345,6 @@ int btrfs_find_root_ref(struct btrfs_root *tree_root, | |||
319 | return ret; | 345 | return ret; |
320 | } | 346 | } |
321 | 347 | ||
322 | |||
323 | /* | 348 | /* |
324 | * add a btrfs_root_ref item. type is either BTRFS_ROOT_REF_KEY | 349 | * add a btrfs_root_ref item. type is either BTRFS_ROOT_REF_KEY |
325 | * or BTRFS_ROOT_BACKREF_KEY. | 350 | * or BTRFS_ROOT_BACKREF_KEY. |
@@ -335,8 +360,7 @@ int btrfs_find_root_ref(struct btrfs_root *tree_root, | |||
335 | */ | 360 | */ |
336 | int btrfs_add_root_ref(struct btrfs_trans_handle *trans, | 361 | int btrfs_add_root_ref(struct btrfs_trans_handle *trans, |
337 | struct btrfs_root *tree_root, | 362 | struct btrfs_root *tree_root, |
338 | u64 root_id, u8 type, u64 ref_id, | 363 | u64 root_id, u64 ref_id, u64 dirid, u64 sequence, |
339 | u64 dirid, u64 sequence, | ||
340 | const char *name, int name_len) | 364 | const char *name, int name_len) |
341 | { | 365 | { |
342 | struct btrfs_key key; | 366 | struct btrfs_key key; |
@@ -346,13 +370,14 @@ int btrfs_add_root_ref(struct btrfs_trans_handle *trans, | |||
346 | struct extent_buffer *leaf; | 370 | struct extent_buffer *leaf; |
347 | unsigned long ptr; | 371 | unsigned long ptr; |
348 | 372 | ||
349 | |||
350 | path = btrfs_alloc_path(); | 373 | path = btrfs_alloc_path(); |
374 | if (!path) | ||
375 | return -ENOMEM; | ||
351 | 376 | ||
352 | key.objectid = root_id; | 377 | key.objectid = root_id; |
353 | key.type = type; | 378 | key.type = BTRFS_ROOT_BACKREF_KEY; |
354 | key.offset = ref_id; | 379 | key.offset = ref_id; |
355 | 380 | again: | |
356 | ret = btrfs_insert_empty_item(trans, tree_root, path, &key, | 381 | ret = btrfs_insert_empty_item(trans, tree_root, path, &key, |
357 | sizeof(*ref) + name_len); | 382 | sizeof(*ref) + name_len); |
358 | BUG_ON(ret); | 383 | BUG_ON(ret); |
@@ -366,6 +391,14 @@ int btrfs_add_root_ref(struct btrfs_trans_handle *trans, | |||
366 | write_extent_buffer(leaf, name, ptr, name_len); | 391 | write_extent_buffer(leaf, name, ptr, name_len); |
367 | btrfs_mark_buffer_dirty(leaf); | 392 | btrfs_mark_buffer_dirty(leaf); |
368 | 393 | ||
394 | if (key.type == BTRFS_ROOT_BACKREF_KEY) { | ||
395 | btrfs_release_path(tree_root, path); | ||
396 | key.objectid = ref_id; | ||
397 | key.type = BTRFS_ROOT_REF_KEY; | ||
398 | key.offset = root_id; | ||
399 | goto again; | ||
400 | } | ||
401 | |||
369 | btrfs_free_path(path); | 402 | btrfs_free_path(path); |
370 | return ret; | 403 | return 0; |
371 | } | 404 | } |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 94f816cb6e35..915077725fea 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -779,24 +779,14 @@ static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info, | |||
779 | ret = btrfs_update_inode(trans, parent_root, parent_inode); | 779 | ret = btrfs_update_inode(trans, parent_root, parent_inode); |
780 | BUG_ON(ret); | 780 | BUG_ON(ret); |
781 | 781 | ||
782 | /* add the backref first */ | ||
783 | ret = btrfs_add_root_ref(trans, parent_root->fs_info->tree_root, | 782 | ret = btrfs_add_root_ref(trans, parent_root->fs_info->tree_root, |
784 | pending->root_key.objectid, | 783 | pending->root_key.objectid, |
785 | BTRFS_ROOT_BACKREF_KEY, | ||
786 | parent_root->root_key.objectid, | 784 | parent_root->root_key.objectid, |
787 | parent_inode->i_ino, index, pending->name, | 785 | parent_inode->i_ino, index, pending->name, |
788 | namelen); | 786 | namelen); |
789 | 787 | ||
790 | BUG_ON(ret); | 788 | BUG_ON(ret); |
791 | 789 | ||
792 | /* now add the forward ref */ | ||
793 | ret = btrfs_add_root_ref(trans, parent_root->fs_info->tree_root, | ||
794 | parent_root->root_key.objectid, | ||
795 | BTRFS_ROOT_REF_KEY, | ||
796 | pending->root_key.objectid, | ||
797 | parent_inode->i_ino, index, pending->name, | ||
798 | namelen); | ||
799 | |||
800 | inode = btrfs_lookup_dentry(parent_inode, pending->dentry); | 790 | inode = btrfs_lookup_dentry(parent_inode, pending->dentry); |
801 | d_instantiate(pending->dentry, inode); | 791 | d_instantiate(pending->dentry, inode); |
802 | fail: | 792 | fail: |