The parameter dev_size_mb is read-only and can be modified only when scsi_debug is reloaded. Therefore, loadable scsi_debug is required to specify the desired dev_size_mb. With the built-in scsi_debug, only the default dev_size_mb value can be used. To allow testing with built-in scsi_debug and any dev_size_mb value, make the parameter writable. To take the required actions at the parameter writing and change, allow such writing not through the sysfs module attribute, but through the sysfs driver attribute. The parameter is stored as a global variable and referred to in many places, then changes of the value would causes troubles for existing live hosts. To avoid the troubles, allow the value changes only when there is no host. Users must remove all hosts to write new dev_size_mb values. At the parameter write, call scsi_debug_init_size_parameters() to propagate the dev_size_mb value changes to dependent parameters. Also erase all stores at dev_size_mb change and recreate the store with the new dev_size_mb value. Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@xxxxxxx> --- drivers/scsi/scsi_debug.c | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index c6b32f07a82c..c93cac831d8e 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -558,6 +558,8 @@ static void sdebug_erase_all_stores(bool apart_from_first); static void sdebug_free_queued_cmd(struct sdebug_queued_cmd *sqcp); +static void scsi_debug_init_size_parameters(void); + /* * The following are overflow arrays for cdbs that "hit" the same index in * the opcode_info_arr array. The most time sensitive (or commonly used) cdb @@ -6660,7 +6662,42 @@ static ssize_t dev_size_mb_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", sdebug_dev_size_mb); } -static DRIVER_ATTR_RO(dev_size_mb); + +static ssize_t dev_size_mb_store(struct device_driver *ddp, const char *buf, + size_t count) +{ + bool want_store = sdebug_fake_rw == 0; + int n, ret; + + if (sdebug_num_hosts) { + pr_err("scsi_debug: Can not change dev_size_mb due to existing hosts\n"); + return -EINVAL; + } + + if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 1)) { + sdebug_dev_size_mb = n; + + /* Propagate dev_size_mb change to other parameters */ + scsi_debug_init_size_parameters(); + + /* + * Erase all stores which may have different size. Initialize + * global variables for the stores and recreate the store. + */ + sdebug_erase_all_stores(false); + sdeb_first_idx = -1; + sdeb_most_recent_idx = -1; + if (want_store) { + ret = sdebug_add_store(); + if (ret < 0) + return ret; + } + return count; + } + + return -EINVAL; +} +static DRIVER_ATTR_RW(dev_size_mb); static ssize_t per_host_store_show(struct device_driver *ddp, char *buf) { -- 2.43.0