scsi_debug: randomize command duration option + %p
PATCH 1/1 scsi_debug: randomize command duration option + %p
Add an option to use the given command delay (in nanoseconds) as the upper limit for command durations. A pseudo random number generator chooses a duration in the range:
[0..delay_in_ns)
Main benefit: allows testing with out-of-order responses.
Change the only %p (print a kernel pointer) in the driver to %pK as the former seems to have no usefulness in recent kernels.
---
The new %p would be more useful if it didn't randomize NULL pointers and gave an indicative output for ERR_PTR(-ENOENT) type pointers. Hard to imagine how that will help the black hats. Probably all printk()s in the SCSI subsystem should be changed to %pK or some variant of that.
--- drivers/scsi/scsi_debug.c | 43 +++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-)
drivers/scsi/scsi_debug.c +39 -4
@@ -38,6 +38,7 @@#include <linux/hrtimer.h> #include <linux/uuid.h> #include <linux/t10-pi.h> +#include <linux/random.h> #include <net/checksum.h>
@@ -125,6 +126,7 @@ static const char *sdebug_version_date = "20190125";#define DEF_PHYSBLK_EXP 0#define DEF_OPT_XFERLEN_EXP 0#define DEF_PTYPE TYPE_DISK +#define DEF_RANDOM false#define DEF_REMOVABLE false#define DEF_SCSI_LEVEL 7/* INQUIRY, byte2 [6->SPC-4; 7->SPC-5] */ #define DEF_SECTOR_SIZE 512
@@ -655,6 +657,7 @@ static unsigned int sdebug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;static unsigned int sdebug_unmap_max_desc =DEF_UNMAP_MAX_DESC ;static unsigned int sdebug_write_same_length =DEF_WRITESAME_LENGTH ;static int sdebug_uuid_ctl =DEF_UUID_CTL ; +static bool sdebug_random =DEF_RANDOM ;static bool sdebug_removable =DEF_REMOVABLE ;static bool sdebug_clustering;static bool sdebug_host_lock =DEF_HOST_LOCK ;
@@ -4354,9 +4357,21 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,ktime_t kt;if (delta_jiff >0 ) { - kt =ns_to_ktime ((u64 )delta_jiff * (NSEC_PER_SEC /HZ )); - }else - kt = ndelay; +u64 ns = (u64 )delta_jiff * (NSEC_PER_SEC /HZ ); + +if (sdebug_random && ns <U32_MAX ) { + ns =prandom_u32_max ((u32 )ns); + }else if (sdebug_random) { + ns /=1000 ; +if (ns <U32_MAX )/* an hour and a bit */ + ns =prandom_u32_max ((u32 )ns); + ns *=1000 ; + } + kt =ns_to_ktime (ns); + }else { + kt = sdebug_random ?prandom_u32_max ((u32 )ndelay) : + (u32 )ndelay; + }if (!sd_dp->init_hrt) { sd_dp->init_hrt = true; sqcp->sd_dp = sd_dp;
@@ -4451,6 +4466,7 @@ module_param_named(opts, sdebug_opts, int, S_IRUGO | S_IWUSR);module_param_named (physblk_exp, sdebug_physblk_exp, int,S_IRUGO );module_param_named (opt_xferlen_exp, sdebug_opt_xferlen_exp, int,S_IRUGO );module_param_named (ptype, sdebug_ptype, int,S_IRUGO |S_IWUSR ); +module_param_named (random, sdebug_random, bool,S_IRUGO |S_IWUSR );module_param_named (removable, sdebug_removable, bool,S_IRUGO |S_IWUSR );module_param_named (scsi_level, sdebug_scsi_level, int,S_IRUGO );module_param_named (sector_size, sdebug_sector_size, int,S_IRUGO );
@@ -4511,6 +4527,7 @@ MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err...MODULE_PARM_DESC (physblk_exp,"physical block exponent (def=0)" );MODULE_PARM_DESC (opt_xferlen_exp,"optimal transfer length granularity exponent (def=physblk_exp)" );MODULE_PARM_DESC (ptype,"SCSI peripheral type(def=0[disk])" ); +MODULE_PARM_DESC (random,"1-> command duration chosen from [0..delay_in_ns) (def=0)" );MODULE_PARM_DESC (removable,"claim to have removable media (def=0)" );MODULE_PARM_DESC (scsi_level,"SCSI level to simulate(def=7[SPC-5])" );MODULE_PARM_DESC (sector_size,"logical block size in bytes (def=512)" );
@@ -5101,6 +5118,23 @@ static ssize_t map_show(struct device_driver *ddp, char *buf) }static DRIVER_ATTR_RO (map); +static ssize_t random_show (struct device_driver *ddp,char *buf) +{ +return scnprintf (buf,PAGE_SIZE ,"%d\n" , sdebug_random ?1 :0 ); +} +static ssize_t random_store (struct device_driver *ddp,const char *buf, +size_t count) +{ +int n; + +if (count >0 &&1 ==sscanf (buf,"%d" , &n) && n >=0 ) { + sdebug_random = (n >0 ); +return count; + } +return -EINVAL ; +} +static DRIVER_ATTR_RW (random); +static ssize_t removable_show (struct device_driver *ddp,char *buf) {return scnprintf (buf,PAGE_SIZE ,"%d\n" , sdebug_removable ?1 :0 );
@@ -5211,6 +5245,7 @@ static struct attribute *sdebug_drv_attrs[] = { &driver_attr_guard.attr, &driver_attr_ato.attr, &driver_attr_map.attr, + &driver_attr_random.attr, &driver_attr_removable.attr, &driver_attr_host_lock.attr, &driver_attr_ndelay.attr,
@@ -5338,7 +5373,7 @@ static int __init scsi_debug_init(void) dif_size = sdebug_store_sectors *sizeof (struct t10_pi_tuple ); dif_storep =vmalloc (dif_size); -pr_err ("dif_storep %u bytes @ %p\n" , dif_size, dif_storep); +pr_err ("dif_storep %u bytes @ %pK\n" , dif_size, dif_storep);if (dif_storep ==NULL ) {pr_err ("out of mem. (DIX)\n" );
Signature · 1 line
2.23.0
kbuild test robot
build botThank you for the patch! Yet something to improve:
Hi Douglas,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on scsi/for-next]
[cannot apply to v5.3 next-20190925]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Douglas-Gilbert/scsi_debug-randomize-command-duration-option-p/20190927-094954 base: https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next config: i386-randconfig-e003-201938 (attached as .config) compiler: gcc-7 (Debian 7.4.0-13) 7.4.0 reproduce: # save the attached .config to linux build tree make ARCH=i386
If you fix the issue, kindly add following tag
All errors (new ones prefixed by >>):
>> ERROR: "__divdi3" [drivers/scsi/scsi_debug.ko] undefined! >> ERROR: "__udivdi3" [drivers/scsi/scsi_debug.ko] undefined!
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
kbuild test robot
build botThank you for the patch! Yet something to improve:
Hi Douglas,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on scsi/for-next]
[cannot apply to v5.3 next-20190925]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system. BTW, we also suggest to use '--base' option to specify the base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Douglas-Gilbert/scsi_debug-randomize-command-duration-option-p/20190927-094954 base: https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next config: i386-randconfig-f004-201938 (attached as .config) compiler: gcc-7 (Debian 7.4.0-13) 7.4.0 reproduce: # save the attached .config to linux build tree make ARCH=i386
If you fix the issue, kindly add following tag
All errors (new ones prefixed by >>):
ld: drivers/scsi/scsi_debug.o: in function `schedule_resp':
>> drivers/scsi/scsi_debug.c:4365: undefined reference to `__udivdi3'
vim +4365 drivers/scsi/scsi_debug.c
4251
4252 /* Complete the processing of the thread that queued a SCSI command to this
4253 * driver. It either completes the command by calling cmnd_done() or
4254 * schedules a hr timer or work queue then returns 0. Returns
4255 * SCSI_MLQUEUE_HOST_BUSY if temporarily out of resources.
4256 */
4257 static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
4258 int scsi_result,
4259 int (*pfp)(struct scsi_cmnd *,
4260 struct sdebug_dev_info *),
4261 int delta_jiff, int ndelay)
4262 {
4263 unsigned long iflags;
4264 int k, num_in_q, qdepth, inject;
4265 struct sdebug_queue *sqp;
4266 struct sdebug_queued_cmd *sqcp;
4267 struct scsi_device *sdp;
4268 struct sdebug_defer *sd_dp;
4269
4270 if (unlikely(devip == NULL)) {
4271 if (scsi_result == 0)
4272 scsi_result = DID_NO_CONNECT << 16;
4273 goto respond_in_thread;
4274 }
4275 sdp = cmnd->device;
4276
4277 if (delta_jiff == 0)
4278 goto respond_in_thread;
4279
4280 /* schedule the response at a later time if resources permit */
4281 sqp = get_queue(cmnd);
4282 spin_lock_irqsave(&sqp->qc_lock, iflags);
4283 if (unlikely(atomic_read(&sqp->blocked))) {
4284 spin_unlock_irqrestore(&sqp->qc_lock, iflags);
4285 return SCSI_MLQUEUE_HOST_BUSY;
4286 }
4287 num_in_q = atomic_read(&devip->num_in_q);
4288 qdepth = cmnd->device->queue_depth;
4289 inject = 0;
4290 if (unlikely((qdepth > 0) && (num_in_q >= qdepth))) {
4291 if (scsi_result) {
4292 spin_unlock_irqrestore(&sqp->qc_lock, iflags);
4293 goto respond_in_thread;
4294 } else
4295 scsi_result = device_qfull_result;
4296 } else if (unlikely(sdebug_every_nth &&
4297 (SDEBUG_OPT_RARE_TSF & sdebug_opts) &&
4298 (scsi_result == 0))) {
4299 if ((num_in_q == (qdepth - 1)) &&
4300 (atomic_inc_return(&sdebug_a_tsf) >=
4301 abs(sdebug_every_nth))) {
4302 atomic_set(&sdebug_a_tsf, 0);
4303 inject = 1;
4304 scsi_result = device_qfull_result;
4305 }
4306 }
4307
4308 k = find_first_zero_bit(sqp->in_use_bm, sdebug_max_queue);
4309 if (unlikely(k >= sdebug_max_queue)) {
4310 spin_unlock_irqrestore(&sqp->qc_lock, iflags);
4311 if (scsi_result)
4312 goto respond_in_thread;
4313 else if (SDEBUG_OPT_ALL_TSF & sdebug_opts)
4314 scsi_result = device_qfull_result;
4315 if (SDEBUG_OPT_Q_NOISE & sdebug_opts)
4316 sdev_printk(KERN_INFO, sdp,
4317 "%s: max_queue=%d exceeded, %s\n",
4318 __func__, sdebug_max_queue,
4319 (scsi_result ? "status: TASK SET FULL" :
4320 "report: host busy"));
4321 if (scsi_result)
4322 goto respond_in_thread;
4323 else
4324 return SCSI_MLQUEUE_HOST_BUSY;
4325 }
4326 __set_bit(k, sqp->in_use_bm);
4327 atomic_inc(&devip->num_in_q);
4328 sqcp = &sqp->qc_arr[k];
4329 sqcp->a_cmnd = cmnd;
4330 cmnd->host_scribble = (unsigned char *)sqcp;
4331 sd_dp = sqcp->sd_dp;
4332 spin_unlock_irqrestore(&sqp->qc_lock, iflags);
4333 if (unlikely(sdebug_every_nth && sdebug_any_injecting_opt))
4334 setup_inject(sqp, sqcp);
4335 if (sd_dp == NULL) {
4336 sd_dp = kzalloc(sizeof(*sd_dp), GFP_ATOMIC);
4337 if (sd_dp == NULL)
4338 return SCSI_MLQUEUE_HOST_BUSY;
4339 }
4340
4341 cmnd->result = pfp != NULL ? pfp(cmnd, devip) : 0;
4342 if (cmnd->result & SDEG_RES_IMMED_MASK) {
4343 /*
4344 * This is the F_DELAY_OVERR case. No delay.
4345 */
4346 cmnd->result &= ~SDEG_RES_IMMED_MASK;
4347 delta_jiff = ndelay = 0;
4348 }
4349 if (cmnd->result == 0 && scsi_result != 0)
4350 cmnd->result = scsi_result;
4351
4352 if (unlikely(sdebug_verbose && cmnd->result))
4353 sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n",
4354 __func__, cmnd->result);
4355
4356 if (delta_jiff > 0 || ndelay > 0) {
4357 ktime_t kt;
4358
4359 if (delta_jiff > 0) {
4360 u64 ns = (u64)delta_jiff * (NSEC_PER_SEC / HZ);
4361
4362 if (sdebug_random && ns < U32_MAX) {
4363 ns = prandom_u32_max((u32)ns);
4364 } else if (sdebug_random) {
> 4365 ns /= 1000;
4366 if (ns < U32_MAX) /* an hour and a bit */
4367 ns = prandom_u32_max((u32)ns);
4368 ns *= 1000;
4369 }
4370 kt = ns_to_ktime(ns);
4371 } else {
4372 kt = sdebug_random ? prandom_u32_max((u32)ndelay) :
4373 (u32)ndelay;
4374 }
4375 if (!sd_dp->init_hrt) {
4376 sd_dp->init_hrt = true;
4377 sqcp->sd_dp = sd_dp;
4378 hrtimer_init(&sd_dp->hrt, CLOCK_MONOTONIC,
4379 HRTIMER_MODE_REL_PINNED);
4380 sd_dp->hrt.function = sdebug_q_cmd_hrt_complete;
4381 sd_dp->sqa_idx = sqp - sdebug_q_arr;
4382 sd_dp->qc_idx = k;
4383 }
4384 if (sdebug_statistics)
4385 sd_dp->issuing_cpu = raw_smp_processor_id();
4386 sd_dp->defer_t = SDEB_DEFER_HRT;
4387 hrtimer_start(&sd_dp->hrt, kt, HRTIMER_MODE_REL_PINNED);
4388 } else { /* jdelay < 0, use work queue */
4389 if (!sd_dp->init_wq) {
4390 sd_dp->init_wq = true;
4391 sqcp->sd_dp = sd_dp;
4392 sd_dp->sqa_idx = sqp - sdebug_q_arr;
4393 sd_dp->qc_idx = k;
4394 INIT_WORK(&sd_dp->ew.work, sdebug_q_cmd_wq_complete);
4395 }
4396 if (sdebug_statistics)
4397 sd_dp->issuing_cpu = raw_smp_processor_id();
4398 sd_dp->defer_t = SDEB_DEFER_WQ;
4399 if (unlikely(sqcp->inj_cmd_abort))
4400 sd_dp->aborted = true;
4401 schedule_work(&sd_dp->ew.work);
4402 if (unlikely(sqcp->inj_cmd_abort)) {
4403 sdev_printk(KERN_INFO, sdp, "abort request tag %d\n",
4404 cmnd->request->tag);
4405 blk_abort_request(cmnd->request);
4406 }
4407 }
4408 if (unlikely((SDEBUG_OPT_Q_NOISE & sdebug_opts) &&
4409 (scsi_result == device_qfull_result)))
4410 sdev_printk(KERN_INFO, sdp,
4411 "%s: num_in_q=%d +1, %s%s\n", __func__,
4412 num_in_q, (inject ? "<inject> " : ""),
4413 "status: TASK SET FULL"); 4414 return 0;
4415
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation