diff options
author | Yan Zheng <zheng.yan@oracle.com> | 2008-12-12 10:03:26 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-12-12 10:03:26 -0500 |
commit | e4404d6e8da678d852b7f767f665f8edf76c9e9f (patch) | |
tree | af6b52e5251d8e939f91e1feab760c1f06021410 | |
parent | d2fb3437e4d8d12c73c587615ad187d5288547ec (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>
-rw-r--r-- | fs/btrfs/disk-io.c | 2 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 37 | ||||
-rw-r--r-- | fs/btrfs/super.c | 8 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 240 | ||||
-rw-r--r-- | fs/btrfs/volumes.h | 3 |
5 files changed, 156 insertions, 134 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 6f042de1ac43..541a8279ac71 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1711,7 +1711,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1711 | } | 1711 | } |
1712 | 1712 | ||
1713 | mutex_lock(&fs_info->chunk_mutex); | 1713 | mutex_lock(&fs_info->chunk_mutex); |
1714 | ret = btrfs_read_sys_array(tree_root, btrfs_super_bytenr(disk_super)); | 1714 | ret = btrfs_read_sys_array(tree_root); |
1715 | mutex_unlock(&fs_info->chunk_mutex); | 1715 | mutex_unlock(&fs_info->chunk_mutex); |
1716 | if (ret) { | 1716 | if (ret) { |
1717 | printk("btrfs: failed to read the system array on %s\n", | 1717 | printk("btrfs: failed to read the system array on %s\n", |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 1cc89246ee2f..171057a32679 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -218,7 +218,7 @@ static int cache_block_group(struct btrfs_root *root, | |||
218 | struct btrfs_key key; | 218 | struct btrfs_key key; |
219 | struct extent_buffer *leaf; | 219 | struct extent_buffer *leaf; |
220 | int slot; | 220 | int slot; |
221 | u64 last = block_group->key.objectid; | 221 | u64 last; |
222 | 222 | ||
223 | if (!block_group) | 223 | if (!block_group) |
224 | return 0; | 224 | return 0; |
@@ -239,7 +239,8 @@ static int cache_block_group(struct btrfs_root *root, | |||
239 | * skip the locking here | 239 | * skip the locking here |
240 | */ | 240 | */ |
241 | path->skip_locking = 1; | 241 | path->skip_locking = 1; |
242 | key.objectid = max_t(u64, last, BTRFS_SUPER_INFO_OFFSET); | 242 | last = max_t(u64, block_group->key.objectid, BTRFS_SUPER_INFO_OFFSET); |
243 | key.objectid = last; | ||
243 | key.offset = 0; | 244 | key.offset = 0; |
244 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 245 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
245 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 246 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
@@ -5335,8 +5336,20 @@ static int noinline relocate_one_extent(struct btrfs_root *extent_root, | |||
5335 | prev_block = block_start; | 5336 | prev_block = block_start; |
5336 | } | 5337 | } |
5337 | 5338 | ||
5338 | if (ref_path->owner_objectid >= BTRFS_FIRST_FREE_OBJECTID && | 5339 | btrfs_record_root_in_trans(found_root); |
5339 | pass >= 2) { | 5340 | if (ref_path->owner_objectid >= BTRFS_FIRST_FREE_OBJECTID) { |
5341 | /* | ||
5342 | * try to update data extent references while | ||
5343 | * keeping metadata shared between snapshots. | ||
5344 | */ | ||
5345 | if (pass == 1) { | ||
5346 | ret = relocate_one_path(trans, found_root, | ||
5347 | path, &first_key, ref_path, | ||
5348 | group, reloc_inode); | ||
5349 | if (ret < 0) | ||
5350 | goto out; | ||
5351 | continue; | ||
5352 | } | ||
5340 | /* | 5353 | /* |
5341 | * use fallback method to process the remaining | 5354 | * use fallback method to process the remaining |
5342 | * references. | 5355 | * references. |
@@ -5359,23 +5372,9 @@ static int noinline relocate_one_extent(struct btrfs_root *extent_root, | |||
5359 | path, extent_key, | 5372 | path, extent_key, |
5360 | &first_key, ref_path, | 5373 | &first_key, ref_path, |
5361 | new_extents, nr_extents); | 5374 | new_extents, nr_extents); |
5362 | if (ret < 0) | 5375 | } else { |
5363 | goto out; | ||
5364 | continue; | ||
5365 | } | ||
5366 | |||
5367 | btrfs_record_root_in_trans(found_root); | ||
5368 | if (ref_path->owner_objectid < BTRFS_FIRST_FREE_OBJECTID) { | ||
5369 | ret = relocate_tree_block(trans, found_root, path, | 5376 | ret = relocate_tree_block(trans, found_root, path, |
5370 | &first_key, ref_path); | 5377 | &first_key, ref_path); |
5371 | } else { | ||
5372 | /* | ||
5373 | * try to update data extent references while | ||
5374 | * keeping metadata shared between snapshots. | ||
5375 | */ | ||
5376 | ret = relocate_one_path(trans, found_root, path, | ||
5377 | &first_key, ref_path, | ||
5378 | group, reloc_inode); | ||
5379 | } | 5378 | } |
5380 | if (ret < 0) | 5379 | if (ret < 0) |
5381 | goto out; | 5380 | goto out; |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 09908f25fca9..84c3b66564d0 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -58,14 +58,15 @@ static struct super_operations btrfs_super_ops; | |||
58 | static void btrfs_put_super (struct super_block * sb) | 58 | static void btrfs_put_super (struct super_block * sb) |
59 | { | 59 | { |
60 | struct btrfs_root *root = btrfs_sb(sb); | 60 | struct btrfs_root *root = btrfs_sb(sb); |
61 | struct btrfs_fs_info *fs = root->fs_info; | ||
62 | int ret; | 61 | int ret; |
63 | 62 | ||
64 | ret = close_ctree(root); | 63 | ret = close_ctree(root); |
65 | if (ret) { | 64 | if (ret) { |
66 | printk("close ctree returns %d\n", ret); | 65 | printk("close ctree returns %d\n", ret); |
67 | } | 66 | } |
68 | btrfs_sysfs_del_super(fs); | 67 | #if 0 |
68 | btrfs_sysfs_del_super(root->fs_info); | ||
69 | #endif | ||
69 | sb->s_fs_info = NULL; | 70 | sb->s_fs_info = NULL; |
70 | } | 71 | } |
71 | 72 | ||
@@ -349,11 +350,12 @@ static int btrfs_fill_super(struct super_block * sb, | |||
349 | err = -ENOMEM; | 350 | err = -ENOMEM; |
350 | goto fail_close; | 351 | goto fail_close; |
351 | } | 352 | } |
352 | 353 | #if 0 | |
353 | /* this does the super kobj at the same time */ | 354 | /* this does the super kobj at the same time */ |
354 | err = btrfs_sysfs_add_super(tree_root->fs_info); | 355 | err = btrfs_sysfs_add_super(tree_root->fs_info); |
355 | if (err) | 356 | if (err) |
356 | goto fail_close; | 357 | goto fail_close; |
358 | #endif | ||
357 | 359 | ||
358 | sb->s_root = root_dentry; | 360 | sb->s_root = root_dentry; |
359 | 361 | ||
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); |
48 | static int btrfs_relocate_sys_chunks(struct btrfs_root *root); | 48 | static 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 | ||
76 | static 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 | |||
77 | int btrfs_cleanup_fs_uuids(void) | 90 | int 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 | ||
301 | static 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; | ||
340 | error: | ||
341 | free_fs_devices(fs_devices); | ||
342 | return ERR_PTR(-ENOMEM); | ||
343 | } | ||
344 | |||
307 | int btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices) | 345 | int 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); |
315 | again: | 352 | again: |
@@ -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 | ||
349 | static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices) | 383 | static 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; |
354 | again: | 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 | ||
386 | int btrfs_close_devices(struct btrfs_fs_devices *fs_devices) | 414 | int 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 | ||
396 | int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices, | 436 | static 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 | ||
1117 | error_brelse: | 1132 | error_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 | |||
2646 | static void end_bio_multi_stripe(struct bio *bio, int err) | 2667 | static 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; | ||
3002 | out: | 3026 | out: |
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 | ||
3077 | int btrfs_read_sys_array(struct btrfs_root *root, u64 sb_bytenr) | 3099 | int 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; |
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index bdebe83c3195..86c44e9ae110 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h | |||
@@ -93,7 +93,6 @@ struct btrfs_fs_devices { | |||
93 | 93 | ||
94 | struct btrfs_fs_devices *seed; | 94 | struct btrfs_fs_devices *seed; |
95 | int seeding; | 95 | int seeding; |
96 | int sprouted; | ||
97 | 96 | ||
98 | int opened; | 97 | int opened; |
99 | }; | 98 | }; |
@@ -127,7 +126,7 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, | |||
127 | int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, | 126 | int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, |
128 | u64 chunk_start, u64 physical, u64 devid, | 127 | u64 chunk_start, u64 physical, u64 devid, |
129 | u64 **logical, int *naddrs, int *stripe_len); | 128 | u64 **logical, int *naddrs, int *stripe_len); |
130 | int btrfs_read_sys_array(struct btrfs_root *root, u64 sb_bytenr); | 129 | int btrfs_read_sys_array(struct btrfs_root *root); |
131 | int btrfs_read_chunk_tree(struct btrfs_root *root); | 130 | int btrfs_read_chunk_tree(struct btrfs_root *root); |
132 | int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | 131 | int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, |
133 | struct btrfs_root *extent_root, u64 type); | 132 | struct btrfs_root *extent_root, u64 type); |