aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorYan Zheng <zheng.yan@oracle.com>2008-12-12 10:03:26 -0500
committerChris Mason <chris.mason@oracle.com>2008-12-12 10:03:26 -0500
commite4404d6e8da678d852b7f767f665f8edf76c9e9f (patch)
treeaf6b52e5251d8e939f91e1feab760c1f06021410 /fs/btrfs/volumes.c
parentd2fb3437e4d8d12c73c587615ad187d5288547ec (diff)
Btrfs: shared seed device
This patch makes seed device possible to be shared by multiple mounted file systems. The sharing is achieved by cloning seed device's btrfs_fs_devices structure. Thanks you, Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c240
1 files changed, 131 insertions, 109 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 4d210a731d40..6672adcec9f8 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -47,7 +47,6 @@ static int init_first_rw_device(struct btrfs_trans_handle *trans,
47 struct btrfs_device *device); 47 struct btrfs_device *device);
48static int btrfs_relocate_sys_chunks(struct btrfs_root *root); 48static int btrfs_relocate_sys_chunks(struct btrfs_root *root);
49 49
50
51#define map_lookup_size(n) (sizeof(struct map_lookup) + \ 50#define map_lookup_size(n) (sizeof(struct map_lookup) + \
52 (sizeof(struct btrfs_bio_stripe) * (n))) 51 (sizeof(struct btrfs_bio_stripe) * (n)))
53 52
@@ -74,34 +73,29 @@ static void unlock_chunks(struct btrfs_root *root)
74 mutex_unlock(&root->fs_info->chunk_mutex); 73 mutex_unlock(&root->fs_info->chunk_mutex);
75} 74}
76 75
76static void free_fs_devices(struct btrfs_fs_devices *fs_devices)
77{
78 struct btrfs_device *device;
79 WARN_ON(fs_devices->opened);
80 while (!list_empty(&fs_devices->devices)) {
81 device = list_entry(fs_devices->devices.next,
82 struct btrfs_device, dev_list);
83 list_del(&device->dev_list);
84 kfree(device->name);
85 kfree(device);
86 }
87 kfree(fs_devices);
88}
89
77int btrfs_cleanup_fs_uuids(void) 90int btrfs_cleanup_fs_uuids(void)
78{ 91{
79 struct btrfs_fs_devices *fs_devices; 92 struct btrfs_fs_devices *fs_devices;
80 struct btrfs_device *dev;
81 93
82 while (!list_empty(&fs_uuids)) { 94 while (!list_empty(&fs_uuids)) {
83 fs_devices = list_entry(fs_uuids.next, 95 fs_devices = list_entry(fs_uuids.next,
84 struct btrfs_fs_devices, list); 96 struct btrfs_fs_devices, list);
85 list_del(&fs_devices->list); 97 list_del(&fs_devices->list);
86 while(!list_empty(&fs_devices->devices)) { 98 free_fs_devices(fs_devices);
87 dev = list_entry(fs_devices->devices.next,
88 struct btrfs_device, dev_list);
89 if (dev->bdev) {
90 close_bdev_exclusive(dev->bdev, dev->mode);
91 fs_devices->open_devices--;
92 }
93 fs_devices->num_devices--;
94 if (dev->writeable)
95 fs_devices->rw_devices--;
96 list_del(&dev->dev_list);
97 list_del(&dev->dev_alloc_list);
98 kfree(dev->name);
99 kfree(dev);
100 }
101 WARN_ON(fs_devices->num_devices);
102 WARN_ON(fs_devices->open_devices);
103 WARN_ON(fs_devices->rw_devices);
104 kfree(fs_devices);
105 } 99 }
106 return 0; 100 return 0;
107} 101}
@@ -304,12 +298,55 @@ static noinline int device_list_add(const char *path,
304 return 0; 298 return 0;
305} 299}
306 300
301static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig)
302{
303 struct btrfs_fs_devices *fs_devices;
304 struct btrfs_device *device;
305 struct btrfs_device *orig_dev;
306
307 fs_devices = kzalloc(sizeof(*fs_devices), GFP_NOFS);
308 if (!fs_devices)
309 return ERR_PTR(-ENOMEM);
310
311 INIT_LIST_HEAD(&fs_devices->devices);
312 INIT_LIST_HEAD(&fs_devices->alloc_list);
313 INIT_LIST_HEAD(&fs_devices->list);
314 fs_devices->latest_devid = orig->latest_devid;
315 fs_devices->latest_trans = orig->latest_trans;
316 memcpy(fs_devices->fsid, orig->fsid, sizeof(fs_devices->fsid));
317
318 list_for_each_entry(orig_dev, &orig->devices, dev_list) {
319 device = kzalloc(sizeof(*device), GFP_NOFS);
320 if (!device)
321 goto error;
322
323 device->name = kstrdup(orig_dev->name, GFP_NOFS);
324 if (!device->name)
325 goto error;
326
327 device->devid = orig_dev->devid;
328 device->work.func = pending_bios_fn;
329 memcpy(device->uuid, orig_dev->uuid, sizeof(device->uuid));
330 device->barriers = 1;
331 spin_lock_init(&device->io_lock);
332 INIT_LIST_HEAD(&device->dev_list);
333 INIT_LIST_HEAD(&device->dev_alloc_list);
334
335 list_add(&device->dev_list, &fs_devices->devices);
336 device->fs_devices = fs_devices;
337 fs_devices->num_devices++;
338 }
339 return fs_devices;
340error:
341 free_fs_devices(fs_devices);
342 return ERR_PTR(-ENOMEM);
343}
344
307int btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices) 345int btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices)
308{ 346{
309 struct list_head *tmp; 347 struct list_head *tmp;
310 struct list_head *cur; 348 struct list_head *cur;
311 struct btrfs_device *device; 349 struct btrfs_device *device;
312 int seed_devices = 0;
313 350
314 mutex_lock(&uuid_mutex); 351 mutex_lock(&uuid_mutex);
315again: 352again:
@@ -328,17 +365,14 @@ again:
328 device->writeable = 0; 365 device->writeable = 0;
329 fs_devices->rw_devices--; 366 fs_devices->rw_devices--;
330 } 367 }
331 if (!seed_devices) { 368 list_del_init(&device->dev_list);
332 list_del_init(&device->dev_list); 369 fs_devices->num_devices--;
333 fs_devices->num_devices--; 370 kfree(device->name);
334 kfree(device->name); 371 kfree(device);
335 kfree(device);
336 }
337 } 372 }
338 373
339 if (fs_devices->seed) { 374 if (fs_devices->seed) {
340 fs_devices = fs_devices->seed; 375 fs_devices = fs_devices->seed;
341 seed_devices = 1;
342 goto again; 376 goto again;
343 } 377 }
344 378
@@ -348,10 +382,9 @@ again:
348 382
349static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices) 383static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
350{ 384{
351 struct btrfs_fs_devices *seed_devices;
352 struct list_head *cur; 385 struct list_head *cur;
353 struct btrfs_device *device; 386 struct btrfs_device *device;
354again: 387
355 if (--fs_devices->opened > 0) 388 if (--fs_devices->opened > 0)
356 return 0; 389 return 0;
357 390
@@ -370,31 +403,38 @@ again:
370 device->writeable = 0; 403 device->writeable = 0;
371 device->in_fs_metadata = 0; 404 device->in_fs_metadata = 0;
372 } 405 }
406 WARN_ON(fs_devices->open_devices);
407 WARN_ON(fs_devices->rw_devices);
373 fs_devices->opened = 0; 408 fs_devices->opened = 0;
374 fs_devices->seeding = 0; 409 fs_devices->seeding = 0;
375 fs_devices->sprouted = 0;
376 410
377 seed_devices = fs_devices->seed;
378 fs_devices->seed = NULL;
379 if (seed_devices) {
380 fs_devices = seed_devices;
381 goto again;
382 }
383 return 0; 411 return 0;
384} 412}
385 413
386int btrfs_close_devices(struct btrfs_fs_devices *fs_devices) 414int btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
387{ 415{
416 struct btrfs_fs_devices *seed_devices = NULL;
388 int ret; 417 int ret;
389 418
390 mutex_lock(&uuid_mutex); 419 mutex_lock(&uuid_mutex);
391 ret = __btrfs_close_devices(fs_devices); 420 ret = __btrfs_close_devices(fs_devices);
421 if (!fs_devices->opened) {
422 seed_devices = fs_devices->seed;
423 fs_devices->seed = NULL;
424 }
392 mutex_unlock(&uuid_mutex); 425 mutex_unlock(&uuid_mutex);
426
427 while (seed_devices) {
428 fs_devices = seed_devices;
429 seed_devices = fs_devices->seed;
430 __btrfs_close_devices(fs_devices);
431 free_fs_devices(fs_devices);
432 }
393 return ret; 433 return ret;
394} 434}
395 435
396int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, 436static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
397 fmode_t flags, void *holder) 437 fmode_t flags, void *holder)
398{ 438{
399 struct block_device *bdev; 439 struct block_device *bdev;
400 struct list_head *head = &fs_devices->devices; 440 struct list_head *head = &fs_devices->devices;
@@ -490,12 +530,8 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
490 530
491 mutex_lock(&uuid_mutex); 531 mutex_lock(&uuid_mutex);
492 if (fs_devices->opened) { 532 if (fs_devices->opened) {
493 if (fs_devices->sprouted) { 533 fs_devices->opened++;
494 ret = -EBUSY; 534 ret = 0;
495 } else {
496 fs_devices->opened++;
497 ret = 0;
498 }
499 } else { 535 } else {
500 ret = __btrfs_open_devices(fs_devices, flags, holder); 536 ret = __btrfs_open_devices(fs_devices, flags, holder);
501 } 537 }
@@ -1043,12 +1079,8 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
1043 goto error_brelse; 1079 goto error_brelse;
1044 1080
1045 device->in_fs_metadata = 0; 1081 device->in_fs_metadata = 0;
1046 if (device->fs_devices == root->fs_info->fs_devices) { 1082 list_del_init(&device->dev_list);
1047 list_del_init(&device->dev_list); 1083 device->fs_devices->num_devices--;
1048 root->fs_info->fs_devices->num_devices--;
1049 if (device->bdev)
1050 device->fs_devices->open_devices--;
1051 }
1052 1084
1053 next_device = list_entry(root->fs_info->fs_devices->devices.next, 1085 next_device = list_entry(root->fs_info->fs_devices->devices.next,
1054 struct btrfs_device, dev_list); 1086 struct btrfs_device, dev_list);
@@ -1057,34 +1089,27 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
1057 if (device->bdev == root->fs_info->fs_devices->latest_bdev) 1089 if (device->bdev == root->fs_info->fs_devices->latest_bdev)
1058 root->fs_info->fs_devices->latest_bdev = next_device->bdev; 1090 root->fs_info->fs_devices->latest_bdev = next_device->bdev;
1059 1091
1092 if (device->bdev) {
1093 close_bdev_exclusive(device->bdev, device->mode);
1094 device->bdev = NULL;
1095 device->fs_devices->open_devices--;
1096 }
1097
1060 num_devices = btrfs_super_num_devices(&root->fs_info->super_copy) - 1; 1098 num_devices = btrfs_super_num_devices(&root->fs_info->super_copy) - 1;
1061 btrfs_set_super_num_devices(&root->fs_info->super_copy, num_devices); 1099 btrfs_set_super_num_devices(&root->fs_info->super_copy, num_devices);
1062 1100
1063 if (device->fs_devices != root->fs_info->fs_devices) { 1101 if (device->fs_devices->open_devices == 0) {
1064 BUG_ON(device->writeable); 1102 struct btrfs_fs_devices *fs_devices;
1065 brelse(bh); 1103 fs_devices = root->fs_info->fs_devices;
1066 if (bdev) 1104 while (fs_devices) {
1067 close_bdev_exclusive(bdev, FMODE_READ); 1105 if (fs_devices->seed == device->fs_devices)
1068 1106 break;
1069 if (device->bdev) { 1107 fs_devices = fs_devices->seed;
1070 close_bdev_exclusive(device->bdev, device->mode);
1071 device->bdev = NULL;
1072 device->fs_devices->open_devices--;
1073 }
1074 if (device->fs_devices->open_devices == 0) {
1075 struct btrfs_fs_devices *fs_devices;
1076 fs_devices = root->fs_info->fs_devices;
1077 while (fs_devices) {
1078 if (fs_devices->seed == device->fs_devices)
1079 break;
1080 fs_devices = fs_devices->seed;
1081 }
1082 fs_devices->seed = device->fs_devices->seed;
1083 device->fs_devices->seed = NULL;
1084 __btrfs_close_devices(device->fs_devices);
1085 } 1108 }
1086 ret = 0; 1109 fs_devices->seed = device->fs_devices->seed;
1087 goto out; 1110 device->fs_devices->seed = NULL;
1111 __btrfs_close_devices(device->fs_devices);
1112 free_fs_devices(device->fs_devices);
1088 } 1113 }
1089 1114
1090 /* 1115 /*
@@ -1099,20 +1124,10 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
1099 set_buffer_dirty(bh); 1124 set_buffer_dirty(bh);
1100 sync_dirty_buffer(bh); 1125 sync_dirty_buffer(bh);
1101 } 1126 }
1102 brelse(bh);
1103 1127
1104 if (device->bdev) {
1105 /* one close for the device struct or super_block */
1106 close_bdev_exclusive(device->bdev, device->mode);
1107 }
1108 if (bdev) {
1109 /* one close for us */
1110 close_bdev_exclusive(bdev, FMODE_READ);
1111 }
1112 kfree(device->name); 1128 kfree(device->name);
1113 kfree(device); 1129 kfree(device);
1114 ret = 0; 1130 ret = 0;
1115 goto out;
1116 1131
1117error_brelse: 1132error_brelse:
1118 brelse(bh); 1133 brelse(bh);
@@ -1133,34 +1148,41 @@ static int btrfs_prepare_sprout(struct btrfs_trans_handle *trans,
1133{ 1148{
1134 struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices; 1149 struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
1135 struct btrfs_fs_devices *old_devices; 1150 struct btrfs_fs_devices *old_devices;
1151 struct btrfs_fs_devices *seed_devices;
1136 struct btrfs_super_block *disk_super = &root->fs_info->super_copy; 1152 struct btrfs_super_block *disk_super = &root->fs_info->super_copy;
1137 struct btrfs_device *device; 1153 struct btrfs_device *device;
1138 u64 super_flags; 1154 u64 super_flags;
1139 1155
1140 BUG_ON(!mutex_is_locked(&uuid_mutex)); 1156 BUG_ON(!mutex_is_locked(&uuid_mutex));
1141 if (!fs_devices->seeding || fs_devices->opened != 1) 1157 if (!fs_devices->seeding)
1142 return -EINVAL; 1158 return -EINVAL;
1143 1159
1144 old_devices = kzalloc(sizeof(*fs_devices), GFP_NOFS); 1160 seed_devices = kzalloc(sizeof(*fs_devices), GFP_NOFS);
1145 if (!old_devices) 1161 if (!seed_devices)
1146 return -ENOMEM; 1162 return -ENOMEM;
1147 1163
1148 memcpy(old_devices, fs_devices, sizeof(*old_devices)); 1164 old_devices = clone_fs_devices(fs_devices);
1149 old_devices->opened = 1; 1165 if (IS_ERR(old_devices)) {
1150 old_devices->sprouted = 1; 1166 kfree(seed_devices);
1151 INIT_LIST_HEAD(&old_devices->devices); 1167 return PTR_ERR(old_devices);
1152 INIT_LIST_HEAD(&old_devices->alloc_list);
1153 list_splice_init(&fs_devices->devices, &old_devices->devices);
1154 list_splice_init(&fs_devices->alloc_list, &old_devices->alloc_list);
1155 list_for_each_entry(device, &old_devices->devices, dev_list) {
1156 device->fs_devices = old_devices;
1157 } 1168 }
1169
1158 list_add(&old_devices->list, &fs_uuids); 1170 list_add(&old_devices->list, &fs_uuids);
1159 1171
1172 memcpy(seed_devices, fs_devices, sizeof(*seed_devices));
1173 seed_devices->opened = 1;
1174 INIT_LIST_HEAD(&seed_devices->devices);
1175 INIT_LIST_HEAD(&seed_devices->alloc_list);
1176 list_splice_init(&fs_devices->devices, &seed_devices->devices);
1177 list_splice_init(&fs_devices->alloc_list, &seed_devices->alloc_list);
1178 list_for_each_entry(device, &seed_devices->devices, dev_list) {
1179 device->fs_devices = seed_devices;
1180 }
1181
1160 fs_devices->seeding = 0; 1182 fs_devices->seeding = 0;
1161 fs_devices->num_devices = 0; 1183 fs_devices->num_devices = 0;
1162 fs_devices->open_devices = 0; 1184 fs_devices->open_devices = 0;
1163 fs_devices->seed = old_devices; 1185 fs_devices->seed = seed_devices;
1164 1186
1165 generate_random_uuid(fs_devices->fsid); 1187 generate_random_uuid(fs_devices->fsid);
1166 memcpy(root->fs_info->fsid, fs_devices->fsid, BTRFS_FSID_SIZE); 1188 memcpy(root->fs_info->fsid, fs_devices->fsid, BTRFS_FSID_SIZE);
@@ -2642,7 +2664,6 @@ int btrfs_unplug_page(struct btrfs_mapping_tree *map_tree,
2642 NULL, 0, page); 2664 NULL, 0, page);
2643} 2665}
2644 2666
2645
2646static void end_bio_multi_stripe(struct bio *bio, int err) 2667static void end_bio_multi_stripe(struct bio *bio, int err)
2647{ 2668{
2648 struct btrfs_multi_bio *multi = bio->bi_private; 2669 struct btrfs_multi_bio *multi = bio->bi_private;
@@ -2840,6 +2861,7 @@ static struct btrfs_device *add_missing_dev(struct btrfs_root *root,
2840 device->dev_root = root->fs_info->dev_root; 2861 device->dev_root = root->fs_info->dev_root;
2841 device->devid = devid; 2862 device->devid = devid;
2842 device->work.func = pending_bios_fn; 2863 device->work.func = pending_bios_fn;
2864 device->fs_devices = fs_devices;
2843 fs_devices->num_devices++; 2865 fs_devices->num_devices++;
2844 spin_lock_init(&device->io_lock); 2866 spin_lock_init(&device->io_lock);
2845 INIT_LIST_HEAD(&device->dev_alloc_list); 2867 INIT_LIST_HEAD(&device->dev_alloc_list);
@@ -2980,8 +3002,10 @@ static int open_seed_devices(struct btrfs_root *root, u8 *fsid)
2980 ret = -ENOENT; 3002 ret = -ENOENT;
2981 goto out; 3003 goto out;
2982 } 3004 }
2983 if (fs_devices->opened) { 3005
2984 ret = -EBUSY; 3006 fs_devices = clone_fs_devices(fs_devices);
3007 if (IS_ERR(fs_devices)) {
3008 ret = PTR_ERR(fs_devices);
2985 goto out; 3009 goto out;
2986 } 3010 }
2987 3011
@@ -2992,13 +3016,13 @@ static int open_seed_devices(struct btrfs_root *root, u8 *fsid)
2992 3016
2993 if (!fs_devices->seeding) { 3017 if (!fs_devices->seeding) {
2994 __btrfs_close_devices(fs_devices); 3018 __btrfs_close_devices(fs_devices);
3019 free_fs_devices(fs_devices);
2995 ret = -EINVAL; 3020 ret = -EINVAL;
2996 goto out; 3021 goto out;
2997 } 3022 }
2998 3023
2999 fs_devices->seed = root->fs_info->fs_devices->seed; 3024 fs_devices->seed = root->fs_info->fs_devices->seed;
3000 root->fs_info->fs_devices->seed = fs_devices; 3025 root->fs_info->fs_devices->seed = fs_devices;
3001 fs_devices->sprouted = 1;
3002out: 3026out:
3003 mutex_unlock(&uuid_mutex); 3027 mutex_unlock(&uuid_mutex);
3004 return ret; 3028 return ret;
@@ -3011,7 +3035,6 @@ static int read_one_dev(struct btrfs_root *root,
3011 struct btrfs_device *device; 3035 struct btrfs_device *device;
3012 u64 devid; 3036 u64 devid;
3013 int ret; 3037 int ret;
3014 int seed_devices = 0;
3015 u8 fs_uuid[BTRFS_UUID_SIZE]; 3038 u8 fs_uuid[BTRFS_UUID_SIZE];
3016 u8 dev_uuid[BTRFS_UUID_SIZE]; 3039 u8 dev_uuid[BTRFS_UUID_SIZE];
3017 3040
@@ -3025,14 +3048,13 @@ static int read_one_dev(struct btrfs_root *root,
3025 3048
3026 if (memcmp(fs_uuid, root->fs_info->fsid, BTRFS_UUID_SIZE)) { 3049 if (memcmp(fs_uuid, root->fs_info->fsid, BTRFS_UUID_SIZE)) {
3027 ret = open_seed_devices(root, fs_uuid); 3050 ret = open_seed_devices(root, fs_uuid);
3028 if (ret) 3051 if (ret && !btrfs_test_opt(root, DEGRADED))
3029 return ret; 3052 return ret;
3030 seed_devices = 1;
3031 } 3053 }
3032 3054
3033 device = btrfs_find_device(root, devid, dev_uuid, fs_uuid); 3055 device = btrfs_find_device(root, devid, dev_uuid, fs_uuid);
3034 if (!device || !device->bdev) { 3056 if (!device || !device->bdev) {
3035 if (!btrfs_test_opt(root, DEGRADED) || seed_devices) 3057 if (!btrfs_test_opt(root, DEGRADED))
3036 return -EIO; 3058 return -EIO;
3037 3059
3038 if (!device) { 3060 if (!device) {
@@ -3074,7 +3096,7 @@ int btrfs_read_super_device(struct btrfs_root *root, struct extent_buffer *buf)
3074 return read_one_dev(root, buf, dev_item); 3096 return read_one_dev(root, buf, dev_item);
3075} 3097}
3076 3098
3077int btrfs_read_sys_array(struct btrfs_root *root, u64 sb_bytenr) 3099int btrfs_read_sys_array(struct btrfs_root *root)
3078{ 3100{
3079 struct btrfs_super_block *super_copy = &root->fs_info->super_copy; 3101 struct btrfs_super_block *super_copy = &root->fs_info->super_copy;
3080 struct extent_buffer *sb; 3102 struct extent_buffer *sb;
@@ -3089,7 +3111,7 @@ int btrfs_read_sys_array(struct btrfs_root *root, u64 sb_bytenr)
3089 u32 cur; 3111 u32 cur;
3090 struct btrfs_key key; 3112 struct btrfs_key key;
3091 3113
3092 sb = btrfs_find_create_tree_block(root, sb_bytenr, 3114 sb = btrfs_find_create_tree_block(root, BTRFS_SUPER_INFO_OFFSET,
3093 BTRFS_SUPER_INFO_SIZE); 3115 BTRFS_SUPER_INFO_SIZE);
3094 if (!sb) 3116 if (!sb)
3095 return -ENOMEM; 3117 return -ENOMEM;