aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorYan, Zheng <zheng.yan@oracle.com>2009-09-21 15:56:00 -0400
committerChris Mason <chris.mason@oracle.com>2009-09-21 15:56:00 -0400
commit4df27c4d5cc1dda54ed7d0a8389347f2df359cf9 (patch)
tree2008f348d28c6c19e31924ae4fb414ca929a01f1 /fs/btrfs/disk-io.c
parent13a8a7c8c47e542b3cdb45bec3f431f96af79361 (diff)
Btrfs: change how subvolumes are organized
btrfs allows subvolumes and snapshots anywhere in the directory tree. If we snapshot a subvolume that contains a link to other subvolume called subvolA, subvolA can be accessed through both the original subvolume and the snapshot. This is similar to creating hard link to directory, and has the very similar problems. The aim of this patch is enforcing there is only one access point to each subvolume. Only the first directory entry (the one added when the subvolume/snapshot was created) is treated as valid access point. The first directory entry is distinguished by checking root forward reference. If the corresponding root forward reference is missing, we know the entry is not the first one. This patch also adds snapshot/subvolume rename support, the code allows rename subvolume link across subvolumes. Signed-off-by: Yan Zheng <zheng.yan@oracle.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c71
1 files changed, 53 insertions, 18 deletions
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
42static struct extent_io_ops btree_extent_io_ops; 42static struct extent_io_ops btree_extent_io_ops;
43static void end_workqueue_fn(struct btrfs_work *work); 43static void end_workqueue_fn(struct btrfs_work *work);
44static void free_fs_root(struct btrfs_root *root);
44 45
45static atomic_t btrfs_bdi_num = ATOMIC_INIT(0); 46static 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 1182again:
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;
1231fail:
1232 free_fs_root(root);
1233 return ERR_PTR(ret);
1206} 1234}
1207 1235
1208struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, 1236struct 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
1241static int btrfs_congested_fn(void *congested_data, int bdi_bits) 1271static 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
2230int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) 2260int 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
2270static 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
2248static int del_fs_roots(struct btrfs_fs_info *fs_info) 2283static int del_fs_roots(struct btrfs_fs_info *fs_info)