diff options
Diffstat (limited to 'fs/btrfs/volumes.c')
| -rw-r--r-- | fs/btrfs/volumes.c | 65 |
1 files changed, 60 insertions, 5 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 6cb82f62cb7c..340a92d08e84 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -508,6 +508,44 @@ static noinline int device_list_add(const char *path, | |||
| 508 | ret = 1; | 508 | ret = 1; |
| 509 | device->fs_devices = fs_devices; | 509 | device->fs_devices = fs_devices; |
| 510 | } else if (!device->name || strcmp(device->name->str, path)) { | 510 | } else if (!device->name || strcmp(device->name->str, path)) { |
| 511 | /* | ||
| 512 | * When FS is already mounted. | ||
| 513 | * 1. If you are here and if the device->name is NULL that | ||
| 514 | * means this device was missing at time of FS mount. | ||
| 515 | * 2. If you are here and if the device->name is different | ||
| 516 | * from 'path' that means either | ||
| 517 | * a. The same device disappeared and reappeared with | ||
| 518 | * different name. or | ||
| 519 | * b. The missing-disk-which-was-replaced, has | ||
| 520 | * reappeared now. | ||
| 521 | * | ||
| 522 | * We must allow 1 and 2a above. But 2b would be a spurious | ||
| 523 | * and unintentional. | ||
| 524 | * | ||
| 525 | * Further in case of 1 and 2a above, the disk at 'path' | ||
| 526 | * would have missed some transaction when it was away and | ||
| 527 | * in case of 2a the stale bdev has to be updated as well. | ||
| 528 | * 2b must not be allowed at all time. | ||
| 529 | */ | ||
| 530 | |||
| 531 | /* | ||
| 532 | * As of now don't allow update to btrfs_fs_device through | ||
| 533 | * the btrfs dev scan cli, after FS has been mounted. | ||
| 534 | */ | ||
| 535 | if (fs_devices->opened) { | ||
| 536 | return -EBUSY; | ||
| 537 | } else { | ||
| 538 | /* | ||
| 539 | * That is if the FS is _not_ mounted and if you | ||
| 540 | * are here, that means there is more than one | ||
| 541 | * disk with same uuid and devid.We keep the one | ||
| 542 | * with larger generation number or the last-in if | ||
| 543 | * generation are equal. | ||
| 544 | */ | ||
| 545 | if (found_transid < device->generation) | ||
| 546 | return -EEXIST; | ||
| 547 | } | ||
| 548 | |||
| 511 | name = rcu_string_strdup(path, GFP_NOFS); | 549 | name = rcu_string_strdup(path, GFP_NOFS); |
| 512 | if (!name) | 550 | if (!name) |
| 513 | return -ENOMEM; | 551 | return -ENOMEM; |
| @@ -519,6 +557,15 @@ static noinline int device_list_add(const char *path, | |||
| 519 | } | 557 | } |
| 520 | } | 558 | } |
| 521 | 559 | ||
| 560 | /* | ||
| 561 | * Unmount does not free the btrfs_device struct but would zero | ||
| 562 | * generation along with most of the other members. So just update | ||
| 563 | * it back. We need it to pick the disk with largest generation | ||
| 564 | * (as above). | ||
| 565 | */ | ||
| 566 | if (!fs_devices->opened) | ||
| 567 | device->generation = found_transid; | ||
| 568 | |||
| 522 | if (found_transid > fs_devices->latest_trans) { | 569 | if (found_transid > fs_devices->latest_trans) { |
| 523 | fs_devices->latest_devid = devid; | 570 | fs_devices->latest_devid = devid; |
| 524 | fs_devices->latest_trans = found_transid; | 571 | fs_devices->latest_trans = found_transid; |
| @@ -1436,7 +1483,7 @@ static int btrfs_add_device(struct btrfs_trans_handle *trans, | |||
| 1436 | btrfs_set_device_io_align(leaf, dev_item, device->io_align); | 1483 | btrfs_set_device_io_align(leaf, dev_item, device->io_align); |
| 1437 | btrfs_set_device_io_width(leaf, dev_item, device->io_width); | 1484 | btrfs_set_device_io_width(leaf, dev_item, device->io_width); |
| 1438 | btrfs_set_device_sector_size(leaf, dev_item, device->sector_size); | 1485 | btrfs_set_device_sector_size(leaf, dev_item, device->sector_size); |
| 1439 | btrfs_set_device_total_bytes(leaf, dev_item, device->total_bytes); | 1486 | btrfs_set_device_total_bytes(leaf, dev_item, device->disk_total_bytes); |
| 1440 | btrfs_set_device_bytes_used(leaf, dev_item, device->bytes_used); | 1487 | btrfs_set_device_bytes_used(leaf, dev_item, device->bytes_used); |
| 1441 | btrfs_set_device_group(leaf, dev_item, 0); | 1488 | btrfs_set_device_group(leaf, dev_item, 0); |
| 1442 | btrfs_set_device_seek_speed(leaf, dev_item, 0); | 1489 | btrfs_set_device_seek_speed(leaf, dev_item, 0); |
| @@ -1671,7 +1718,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
| 1671 | device->fs_devices->total_devices--; | 1718 | device->fs_devices->total_devices--; |
| 1672 | 1719 | ||
| 1673 | if (device->missing) | 1720 | if (device->missing) |
| 1674 | root->fs_info->fs_devices->missing_devices--; | 1721 | device->fs_devices->missing_devices--; |
| 1675 | 1722 | ||
| 1676 | next_device = list_entry(root->fs_info->fs_devices->devices.next, | 1723 | next_device = list_entry(root->fs_info->fs_devices->devices.next, |
| 1677 | struct btrfs_device, dev_list); | 1724 | struct btrfs_device, dev_list); |
| @@ -1801,8 +1848,12 @@ void btrfs_rm_dev_replace_srcdev(struct btrfs_fs_info *fs_info, | |||
| 1801 | if (srcdev->bdev) { | 1848 | if (srcdev->bdev) { |
| 1802 | fs_info->fs_devices->open_devices--; | 1849 | fs_info->fs_devices->open_devices--; |
| 1803 | 1850 | ||
| 1804 | /* zero out the old super */ | 1851 | /* |
| 1805 | btrfs_scratch_superblock(srcdev); | 1852 | * zero out the old super if it is not writable |
| 1853 | * (e.g. seed device) | ||
| 1854 | */ | ||
| 1855 | if (srcdev->writeable) | ||
| 1856 | btrfs_scratch_superblock(srcdev); | ||
| 1806 | } | 1857 | } |
| 1807 | 1858 | ||
| 1808 | call_rcu(&srcdev->rcu, free_device); | 1859 | call_rcu(&srcdev->rcu, free_device); |
| @@ -1941,6 +1992,9 @@ static int btrfs_prepare_sprout(struct btrfs_root *root) | |||
| 1941 | fs_devices->seeding = 0; | 1992 | fs_devices->seeding = 0; |
| 1942 | fs_devices->num_devices = 0; | 1993 | fs_devices->num_devices = 0; |
| 1943 | fs_devices->open_devices = 0; | 1994 | fs_devices->open_devices = 0; |
| 1995 | fs_devices->missing_devices = 0; | ||
| 1996 | fs_devices->num_can_discard = 0; | ||
| 1997 | fs_devices->rotating = 0; | ||
| 1944 | fs_devices->seed = seed_devices; | 1998 | fs_devices->seed = seed_devices; |
| 1945 | 1999 | ||
| 1946 | generate_random_uuid(fs_devices->fsid); | 2000 | generate_random_uuid(fs_devices->fsid); |
| @@ -5800,7 +5854,8 @@ struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info, | |||
| 5800 | else | 5854 | else |
| 5801 | generate_random_uuid(dev->uuid); | 5855 | generate_random_uuid(dev->uuid); |
| 5802 | 5856 | ||
| 5803 | btrfs_init_work(&dev->work, pending_bios_fn, NULL, NULL); | 5857 | btrfs_init_work(&dev->work, btrfs_submit_helper, |
| 5858 | pending_bios_fn, NULL, NULL); | ||
| 5804 | 5859 | ||
| 5805 | return dev; | 5860 | return dev; |
| 5806 | } | 5861 | } |
