diff options
author | Dimitri John Ledkov <xnox@ubuntu.com> | 2018-05-08 14:17:29 -0700 |
---|---|---|
committer | Dimitri John Ledkov <xnox@ubuntu.com> | 2018-05-08 14:17:29 -0700 |
commit | d00c9550da1801a0eaff5cedf4312e24691b31ea (patch) | |
tree | 3881ca1764ef792259e1b70f12c884a3ac0c0715 /volumes.c | |
parent | dab6d2181f1f194ec3a76d900cf2c6533379cbea (diff) |
New upstream release.
Diffstat (limited to 'volumes.c')
-rw-r--r-- | volumes.c | 97 |
1 files changed, 85 insertions, 12 deletions
@@ -30,6 +30,72 @@ #include "utils.h" #include "kernel-lib/raid56.h" +const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = { + [BTRFS_RAID_RAID10] = { + .sub_stripes = 2, + .dev_stripes = 1, + .devs_max = 0, /* 0 == as many as possible */ + .devs_min = 4, + .tolerated_failures = 1, + .devs_increment = 2, + .ncopies = 2, + }, + [BTRFS_RAID_RAID1] = { + .sub_stripes = 1, + .dev_stripes = 1, + .devs_max = 2, + .devs_min = 2, + .tolerated_failures = 1, + .devs_increment = 2, + .ncopies = 2, + }, + [BTRFS_RAID_DUP] = { + .sub_stripes = 1, + .dev_stripes = 2, + .devs_max = 1, + .devs_min = 1, + .tolerated_failures = 0, + .devs_increment = 1, + .ncopies = 2, + }, + [BTRFS_RAID_RAID0] = { + .sub_stripes = 1, + .dev_stripes = 1, + .devs_max = 0, + .devs_min = 2, + .tolerated_failures = 0, + .devs_increment = 1, + .ncopies = 1, + }, + [BTRFS_RAID_SINGLE] = { + .sub_stripes = 1, + .dev_stripes = 1, + .devs_max = 1, + .devs_min = 1, + .tolerated_failures = 0, + .devs_increment = 1, + .ncopies = 1, + }, + [BTRFS_RAID_RAID5] = { + .sub_stripes = 1, + .dev_stripes = 1, + .devs_max = 0, + .devs_min = 2, + .tolerated_failures = 1, + .devs_increment = 1, + .ncopies = 2, + }, + [BTRFS_RAID_RAID6] = { + .sub_stripes = 1, + .dev_stripes = 1, + .devs_max = 0, + .devs_min = 3, + .tolerated_failures = 2, + .devs_increment = 1, + .ncopies = 3, + }, +}; + struct stripe { struct btrfs_device *dev; u64 physical; @@ -54,14 +120,22 @@ static inline int nr_data_stripes(struct map_lookup *map) static LIST_HEAD(fs_uuids); -static struct btrfs_device *__find_device(struct list_head *head, u64 devid, - u8 *uuid) +/* + * Find a device specified by @devid or @uuid in the list of @fs_devices, or + * return NULL. + * + * If devid and uuid are both specified, the match must be exact, otherwise + * only devid is used. + */ +static struct btrfs_device *find_device(struct btrfs_fs_devices *fs_devices, + u64 devid, u8 *uuid) { + struct list_head *head = &fs_devices->devices; struct btrfs_device *dev; list_for_each_entry(dev, head, dev_list) { if (dev->devid == devid && - !memcmp(dev->uuid, uuid, BTRFS_UUID_SIZE)) { + (!uuid || !memcmp(dev->uuid, uuid, BTRFS_UUID_SIZE))) { return dev; } } @@ -100,7 +174,7 @@ static int device_list_add(const char *path, fs_devices->lowest_devid = (u64)-1; device = NULL; } else { - device = __find_device(&fs_devices->devices, devid, + device = find_device(fs_devices, devid, disk_super->dev_item.uuid); } if (!device) { @@ -450,10 +524,10 @@ out: } static int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes, - u64 *start) + u64 *start, u64 *len) { /* FIXME use last free of some kind */ - return find_free_dev_extent_start(device, num_bytes, 0, start, NULL); + return find_free_dev_extent_start(device, num_bytes, 0, start, len); } static int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, @@ -477,7 +551,7 @@ static int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans, * is responsible to make sure it's free. */ if (!convert) { - ret = find_free_dev_extent(device, num_bytes, start); + ret = find_free_dev_extent(device, num_bytes, start, NULL); if (ret) goto err; } @@ -826,7 +900,7 @@ error: return ret; } -#define BTRFS_MAX_DEVS(r) ((BTRFS_LEAF_DATA_SIZE(r->fs_info) \ +#define BTRFS_MAX_DEVS(info) ((BTRFS_LEAF_DATA_SIZE(info) \ - sizeof(struct btrfs_item) \ - sizeof(struct btrfs_chunk)) \ / sizeof(struct btrfs_stripe) + 1) @@ -882,12 +956,12 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, calc_size = SZ_1G; max_chunk_size = 10 * calc_size; min_stripe_size = SZ_64M; - max_stripes = BTRFS_MAX_DEVS(chunk_root); + max_stripes = BTRFS_MAX_DEVS(info); } else if (type & BTRFS_BLOCK_GROUP_METADATA) { calc_size = SZ_1G; max_chunk_size = 4 * calc_size; min_stripe_size = SZ_32M; - max_stripes = BTRFS_MAX_DEVS(chunk_root); + max_stripes = BTRFS_MAX_DEVS(info); } } if (type & BTRFS_BLOCK_GROUP_RAID1) { @@ -1616,8 +1690,7 @@ struct btrfs_device *btrfs_find_device(struct btrfs_fs_info *fs_info, u64 devid, if (!fsid || (!memcmp(cur_devices->fsid, fsid, BTRFS_UUID_SIZE) || fs_info->ignore_fsid_mismatch)) { - device = __find_device(&cur_devices->devices, - devid, uuid); + device = find_device(cur_devices, devid, uuid); if (device) return device; } |