int raid_disks;
int delta_disks;
+ int data_offset;
int raid10_copies;
struct mddev md;
{ CTR_FLAG_REGION_SIZE, "region_size"},
{ CTR_FLAG_RAID10_COPIES, "raid10_copies"},
{ CTR_FLAG_RAID10_FORMAT, "raid10_format"},
+ { CTR_FLAG_DATA_OFFSET, "data_offset"},
+ { CTR_FLAG_DELTA_DISKS, "delta_disks"},
+ { CTR_FLAG_RAID10_USE_NEAR_SETS, "raid10_use_near_sets"},
};
/* Return argument name string for given @flag */
* Second, parse the unordered optional arguments
*/
for (i = 0; i < num_raid_params; i++) {
- arg = dm_shift_arg(as);
- if (!arg)
+ key = dm_shift_arg(as);
+ if (!key)
return ti_error_einval(rs->ti, "Not enough raid parameters given");
- if (!strcasecmp(arg, "nosync")) {
+ if (!strcasecmp(key, _argname_by_flag(CTR_FLAG_NOSYNC))) {
+ if (_test_and_set_flag(CTR_FLAG_NOSYNC, &rs->ctr_flags))
+ return ti_error_einval(rs->ti, "Only one 'nosync' argument allowed");
rs->md.recovery_cp = MaxSector;
- _set_flag(CTR_FLAG_NOSYNC, &rs->ctr_flags);
continue;
}
- if (!strcasecmp(arg, "sync")) {
+ if (!strcasecmp(key, _argname_by_flag(CTR_FLAG_SYNC))) {
+ if (_test_and_set_flag(CTR_FLAG_SYNC, &rs->ctr_flags))
+ return ti_error_einval(rs->ti, "Only one 'sync' argument allowed");
rs->md.recovery_cp = 0;
- _set_flag(CTR_FLAG_SYNC, &rs->ctr_flags);
+ continue;
+ }
+ if (!strcasecmp(key, _argname_by_flag(CTR_FLAG_RAID10_USE_NEAR_SETS))) {
+ if (_test_and_set_flag(CTR_FLAG_RAID10_USE_NEAR_SETS, &rs->ctr_flags))
+ return ti_error_einval(rs->ti, "Only one 'raid10_use_new_sets' argument allowed");
continue;
}
- key = arg;
arg = dm_shift_arg(as);
i++; /* Account for the argument pairs */
if (!arg)
if (!strcasecmp(key, _argname_by_flag(CTR_FLAG_RAID10_FORMAT))) {
if (_test_and_set_flag(CTR_FLAG_RAID10_FORMAT, &rs->ctr_flags))
- return ti_error_einval(rs->ti, "Only one raid10_format argument pair allowed");
+ return ti_error_einval(rs->ti, "Only one 'raid10_format' argument pair allowed");
if (!rt_is_raid10(rt))
return ti_error_einval(rs->ti, "'raid10_format' is an invalid parameter for this RAID type");
raid10_format = raid10_name_to_format(arg);
if (!value || (value > MAX_SCHEDULE_TIMEOUT))
return ti_error_einval(rs->ti, "daemon sleep period out of range");
rs->md.bitmap_info.daemon_sleep = value;
+ } else if (!strcasecmp(key, _argname_by_flag(CTR_FLAG_DATA_OFFSET))) {
+ /* Userspace passes new data_offset after having extended the the data image LV */
+ if (_test_and_set_flag(CTR_FLAG_DATA_OFFSET, &rs->ctr_flags))
+ return ti_error_einval(rs->ti, "Only one data_offset argument pair allowed");
+
+ /* Ensure sensible data offset */
+ if (value < 0)
+ return ti_error_einval(rs->ti, "Bogus data_offset value");
+
+ rs->data_offset = value;
+ } else if (!strcasecmp(key, _argname_by_flag(CTR_FLAG_DELTA_DISKS))) {
+ /* Define the +/-# of disks to add to/remove from the given raid set */
+ if (_test_and_set_flag(CTR_FLAG_DELTA_DISKS, &rs->ctr_flags))
+ return ti_error_einval(rs->ti, "Only one delta_disks argument pair allowed");
+
+ /* Ensure MAX_RAID_DEVICES and raid type minimal_devs! */
+ if (!_in_range(abs(value), 1, MAX_RAID_DEVICES - rt->minimal_devs))
+ return ti_error_einval(rs->ti, "Too many delta_disk requested");
+
+ rs->delta_disks = value;
} else if (!strcasecmp(key, _argname_by_flag(CTR_FLAG_STRIPE_CACHE))) {
if (_test_and_set_flag(CTR_FLAG_STRIPE_CACHE, &rs->ctr_flags))
return ti_error_einval(rs->ti, "Only one stripe_cache argument pair allowed");
if ((rt->algorithm == ALGORITHM_RAID10_DEFAULT ||
rt->algorithm == ALGORITHM_RAID10_NEAR) &&
_test_flag(CTR_FLAG_RAID10_USE_NEAR_SETS, rs->ctr_flags))
- return ti_error_einval(rs->ti, "RAID10 format \"near\" and \"raid10_use_near_sets\" are incompatible");
+ return ti_error_einval(rs->ti, "RAID10 format 'near' and 'raid10_use_near_sets' are incompatible");
/* (Len * #mirrors) / #devices */
sectors_per_dev = rs->ti->len * raid10_copies;