btrfs: factor out gather_device_info()
Factor out gather_device_info() from __btrfs_alloc_chunk(). This
function iterates over devices list and gather information about
devices. This commit also introduces "max_avail" and
"dev_extent_min" to fold the same calculation to one variable.
This commit has no functional changes.
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 9ae5f0c..84c12ff 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -4865,22 +4865,97 @@
}
}
+static int gather_device_info(struct btrfs_fs_devices *fs_devices,
+ struct alloc_chunk_ctl *ctl,
+ struct btrfs_device_info *devices_info)
+{
+ struct btrfs_fs_info *info = fs_devices->fs_info;
+ struct btrfs_device *device;
+ u64 total_avail;
+ u64 dev_extent_want = ctl->max_stripe_size * ctl->dev_stripes;
+ u64 dev_extent_min = BTRFS_STRIPE_LEN * ctl->dev_stripes;
+ int ret;
+ int ndevs = 0;
+ u64 max_avail;
+ u64 dev_offset;
+
+ /*
+ * in the first pass through the devices list, we gather information
+ * about the available holes on each device.
+ */
+ list_for_each_entry(device, &fs_devices->alloc_list, dev_alloc_list) {
+ if (!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) {
+ WARN(1, KERN_ERR
+ "BTRFS: read-only device in alloc_list\n");
+ continue;
+ }
+
+ if (!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA,
+ &device->dev_state) ||
+ test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state))
+ continue;
+
+ if (device->total_bytes > device->bytes_used)
+ total_avail = device->total_bytes - device->bytes_used;
+ else
+ total_avail = 0;
+
+ /* If there is no space on this device, skip it. */
+ if (total_avail == 0)
+ continue;
+
+ ret = find_free_dev_extent(device, dev_extent_want, &dev_offset,
+ &max_avail);
+ if (ret && ret != -ENOSPC)
+ return ret;
+
+ if (ret == 0)
+ max_avail = dev_extent_want;
+
+ if (max_avail < dev_extent_min) {
+ if (btrfs_test_opt(info, ENOSPC_DEBUG))
+ btrfs_debug(info,
+ "%s: devid %llu has no free space, have=%llu want=%llu",
+ __func__, device->devid, max_avail,
+ dev_extent_min);
+ continue;
+ }
+
+ if (ndevs == fs_devices->rw_devices) {
+ WARN(1, "%s: found more than %llu devices\n",
+ __func__, fs_devices->rw_devices);
+ break;
+ }
+ devices_info[ndevs].dev_offset = dev_offset;
+ devices_info[ndevs].max_avail = max_avail;
+ devices_info[ndevs].total_avail = total_avail;
+ devices_info[ndevs].dev = device;
+ ++ndevs;
+ }
+ ctl->ndevs = ndevs;
+
+ /*
+ * now sort the devices by hole size / available space
+ */
+ sort(devices_info, ndevs, sizeof(struct btrfs_device_info),
+ btrfs_cmp_device_info, NULL);
+
+ return 0;
+}
+
static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
u64 start, u64 type)
{
struct btrfs_fs_info *info = trans->fs_info;
struct btrfs_fs_devices *fs_devices = info->fs_devices;
- struct btrfs_device *device;
struct map_lookup *map = NULL;
struct extent_map_tree *em_tree;
struct extent_map *em;
struct btrfs_device_info *devices_info = NULL;
struct alloc_chunk_ctl ctl;
- u64 total_avail;
- int data_stripes; /* number of stripes that count for
- block group size */
+ /* Number of stripes that count for block group size */
+ int data_stripes;
int ret;
- int ndevs;
int i;
int j;
@@ -4910,71 +4985,9 @@
if (!devices_info)
return -ENOMEM;
- /*
- * in the first pass through the devices list, we gather information
- * about the available holes on each device.
- */
- ndevs = 0;
- list_for_each_entry(device, &fs_devices->alloc_list, dev_alloc_list) {
- u64 max_avail;
- u64 dev_offset;
-
- if (!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) {
- WARN(1, KERN_ERR
- "BTRFS: read-only device in alloc_list\n");
- continue;
- }
-
- if (!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA,
- &device->dev_state) ||
- test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state))
- continue;
-
- if (device->total_bytes > device->bytes_used)
- total_avail = device->total_bytes - device->bytes_used;
- else
- total_avail = 0;
-
- /* If there is no space on this device, skip it. */
- if (total_avail == 0)
- continue;
-
- ret = find_free_dev_extent(
- device, ctl.max_stripe_size * ctl.dev_stripes,
- &dev_offset, &max_avail);
- if (ret && ret != -ENOSPC)
- goto error;
-
- if (ret == 0)
- max_avail = ctl.max_stripe_size * ctl.dev_stripes;
-
- if (max_avail < BTRFS_STRIPE_LEN * ctl.dev_stripes) {
- if (btrfs_test_opt(info, ENOSPC_DEBUG))
- btrfs_debug(info,
- "%s: devid %llu has no free space, have=%llu want=%u",
- __func__, device->devid, max_avail,
- BTRFS_STRIPE_LEN * ctl.dev_stripes);
- continue;
- }
-
- if (ndevs == fs_devices->rw_devices) {
- WARN(1, "%s: found more than %llu devices\n",
- __func__, fs_devices->rw_devices);
- break;
- }
- devices_info[ndevs].dev_offset = dev_offset;
- devices_info[ndevs].max_avail = max_avail;
- devices_info[ndevs].total_avail = total_avail;
- devices_info[ndevs].dev = device;
- ++ndevs;
- }
- ctl.ndevs = ndevs;
-
- /*
- * now sort the devices by hole size / available space
- */
- sort(devices_info, ctl.ndevs, sizeof(struct btrfs_device_info),
- btrfs_cmp_device_info, NULL);
+ ret = gather_device_info(fs_devices, &ctl, devices_info);
+ if (ret < 0)
+ goto error;
/*
* Round down to number of usable stripes, devs_increment can be any