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: |
