diff options
author | Stefan Behrens <sbehrens@giantdisaster.de> | 2012-11-05 11:33:06 -0500 |
---|---|---|
committer | Josef Bacik <jbacik@fusionio.com> | 2012-12-12 17:15:41 -0500 |
commit | e93c89c1aaaaaec3487c4c18dd02360371790722 (patch) | |
tree | 359c310c736d0db5cfd724c628fdb9f2f680a3d3 /fs/btrfs/volumes.c | |
parent | ff023aac31198e88507d626825379b28ea481d4d (diff) |
Btrfs: add new sources for device replace code
This adds a new file to the sources together with the header file
and the changes to ioctl.h and ctree.h that are required by the
new C source file. Additionally, 4 new functions are added to
volume.c that deal with device creation and destruction.
Signed-off-by: Stefan Behrens <sbehrens@giantdisaster.de>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 415862885b67..5777e6a9aab1 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -1537,6 +1537,53 @@ error_undo: | |||
1537 | goto error_brelse; | 1537 | goto error_brelse; |
1538 | } | 1538 | } |
1539 | 1539 | ||
1540 | void btrfs_rm_dev_replace_srcdev(struct btrfs_fs_info *fs_info, | ||
1541 | struct btrfs_device *srcdev) | ||
1542 | { | ||
1543 | WARN_ON(!mutex_is_locked(&fs_info->fs_devices->device_list_mutex)); | ||
1544 | list_del_rcu(&srcdev->dev_list); | ||
1545 | list_del_rcu(&srcdev->dev_alloc_list); | ||
1546 | fs_info->fs_devices->num_devices--; | ||
1547 | if (srcdev->missing) { | ||
1548 | fs_info->fs_devices->missing_devices--; | ||
1549 | fs_info->fs_devices->rw_devices++; | ||
1550 | } | ||
1551 | if (srcdev->can_discard) | ||
1552 | fs_info->fs_devices->num_can_discard--; | ||
1553 | if (srcdev->bdev) | ||
1554 | fs_info->fs_devices->open_devices--; | ||
1555 | |||
1556 | call_rcu(&srcdev->rcu, free_device); | ||
1557 | } | ||
1558 | |||
1559 | void btrfs_destroy_dev_replace_tgtdev(struct btrfs_fs_info *fs_info, | ||
1560 | struct btrfs_device *tgtdev) | ||
1561 | { | ||
1562 | struct btrfs_device *next_device; | ||
1563 | |||
1564 | WARN_ON(!tgtdev); | ||
1565 | mutex_lock(&fs_info->fs_devices->device_list_mutex); | ||
1566 | if (tgtdev->bdev) { | ||
1567 | btrfs_scratch_superblock(tgtdev); | ||
1568 | fs_info->fs_devices->open_devices--; | ||
1569 | } | ||
1570 | fs_info->fs_devices->num_devices--; | ||
1571 | if (tgtdev->can_discard) | ||
1572 | fs_info->fs_devices->num_can_discard++; | ||
1573 | |||
1574 | next_device = list_entry(fs_info->fs_devices->devices.next, | ||
1575 | struct btrfs_device, dev_list); | ||
1576 | if (tgtdev->bdev == fs_info->sb->s_bdev) | ||
1577 | fs_info->sb->s_bdev = next_device->bdev; | ||
1578 | if (tgtdev->bdev == fs_info->fs_devices->latest_bdev) | ||
1579 | fs_info->fs_devices->latest_bdev = next_device->bdev; | ||
1580 | list_del_rcu(&tgtdev->dev_list); | ||
1581 | |||
1582 | call_rcu(&tgtdev->rcu, free_device); | ||
1583 | |||
1584 | mutex_unlock(&fs_info->fs_devices->device_list_mutex); | ||
1585 | } | ||
1586 | |||
1540 | int btrfs_find_device_by_path(struct btrfs_root *root, char *device_path, | 1587 | int btrfs_find_device_by_path(struct btrfs_root *root, char *device_path, |
1541 | struct btrfs_device **device) | 1588 | struct btrfs_device **device) |
1542 | { | 1589 | { |
@@ -1931,6 +1978,98 @@ error: | |||
1931 | return ret; | 1978 | return ret; |
1932 | } | 1979 | } |
1933 | 1980 | ||
1981 | int btrfs_init_dev_replace_tgtdev(struct btrfs_root *root, char *device_path, | ||
1982 | struct btrfs_device **device_out) | ||
1983 | { | ||
1984 | struct request_queue *q; | ||
1985 | struct btrfs_device *device; | ||
1986 | struct block_device *bdev; | ||
1987 | struct btrfs_fs_info *fs_info = root->fs_info; | ||
1988 | struct list_head *devices; | ||
1989 | struct rcu_string *name; | ||
1990 | int ret = 0; | ||
1991 | |||
1992 | *device_out = NULL; | ||
1993 | if (fs_info->fs_devices->seeding) | ||
1994 | return -EINVAL; | ||
1995 | |||
1996 | bdev = blkdev_get_by_path(device_path, FMODE_WRITE | FMODE_EXCL, | ||
1997 | fs_info->bdev_holder); | ||
1998 | if (IS_ERR(bdev)) | ||
1999 | return PTR_ERR(bdev); | ||
2000 | |||
2001 | filemap_write_and_wait(bdev->bd_inode->i_mapping); | ||
2002 | |||
2003 | devices = &fs_info->fs_devices->devices; | ||
2004 | list_for_each_entry(device, devices, dev_list) { | ||
2005 | if (device->bdev == bdev) { | ||
2006 | ret = -EEXIST; | ||
2007 | goto error; | ||
2008 | } | ||
2009 | } | ||
2010 | |||
2011 | device = kzalloc(sizeof(*device), GFP_NOFS); | ||
2012 | if (!device) { | ||
2013 | ret = -ENOMEM; | ||
2014 | goto error; | ||
2015 | } | ||
2016 | |||
2017 | name = rcu_string_strdup(device_path, GFP_NOFS); | ||
2018 | if (!name) { | ||
2019 | kfree(device); | ||
2020 | ret = -ENOMEM; | ||
2021 | goto error; | ||
2022 | } | ||
2023 | rcu_assign_pointer(device->name, name); | ||
2024 | |||
2025 | q = bdev_get_queue(bdev); | ||
2026 | if (blk_queue_discard(q)) | ||
2027 | device->can_discard = 1; | ||
2028 | mutex_lock(&root->fs_info->fs_devices->device_list_mutex); | ||
2029 | device->writeable = 1; | ||
2030 | device->work.func = pending_bios_fn; | ||
2031 | generate_random_uuid(device->uuid); | ||
2032 | device->devid = BTRFS_DEV_REPLACE_DEVID; | ||
2033 | spin_lock_init(&device->io_lock); | ||
2034 | device->generation = 0; | ||
2035 | device->io_width = root->sectorsize; | ||
2036 | device->io_align = root->sectorsize; | ||
2037 | device->sector_size = root->sectorsize; | ||
2038 | device->total_bytes = i_size_read(bdev->bd_inode); | ||
2039 | device->disk_total_bytes = device->total_bytes; | ||
2040 | device->dev_root = fs_info->dev_root; | ||
2041 | device->bdev = bdev; | ||
2042 | device->in_fs_metadata = 1; | ||
2043 | device->is_tgtdev_for_dev_replace = 1; | ||
2044 | device->mode = FMODE_EXCL; | ||
2045 | set_blocksize(device->bdev, 4096); | ||
2046 | device->fs_devices = fs_info->fs_devices; | ||
2047 | list_add(&device->dev_list, &fs_info->fs_devices->devices); | ||
2048 | fs_info->fs_devices->num_devices++; | ||
2049 | fs_info->fs_devices->open_devices++; | ||
2050 | if (device->can_discard) | ||
2051 | fs_info->fs_devices->num_can_discard++; | ||
2052 | mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); | ||
2053 | |||
2054 | *device_out = device; | ||
2055 | return ret; | ||
2056 | |||
2057 | error: | ||
2058 | blkdev_put(bdev, FMODE_EXCL); | ||
2059 | return ret; | ||
2060 | } | ||
2061 | |||
2062 | void btrfs_init_dev_replace_tgtdev_for_resume(struct btrfs_fs_info *fs_info, | ||
2063 | struct btrfs_device *tgtdev) | ||
2064 | { | ||
2065 | WARN_ON(fs_info->fs_devices->rw_devices == 0); | ||
2066 | tgtdev->io_width = fs_info->dev_root->sectorsize; | ||
2067 | tgtdev->io_align = fs_info->dev_root->sectorsize; | ||
2068 | tgtdev->sector_size = fs_info->dev_root->sectorsize; | ||
2069 | tgtdev->dev_root = fs_info->dev_root; | ||
2070 | tgtdev->in_fs_metadata = 1; | ||
2071 | } | ||
2072 | |||
1934 | static noinline int btrfs_update_device(struct btrfs_trans_handle *trans, | 2073 | static noinline int btrfs_update_device(struct btrfs_trans_handle *trans, |
1935 | struct btrfs_device *device) | 2074 | struct btrfs_device *device) |
1936 | { | 2075 | { |