Skip to content

Commit 4f2c8bf

Browse files
doug-gilbertmartinkpetersen
authored andcommitted
scsi: scsi_debug: IMMED related delay adjustments
A patch titled: "[PATCH v2] scsi_debug: implement IMMED bit" introduced long delays to the Start stop unit (SSU) and Synchronize cache (SC) commands when the IMMED bit is clear. This patch makes those delays more realistic. It causes SSU to only delay when the start stop state is changed; SC only delays when there's been a write since the previous SC. It also reduced the SC delay from 1 second to 50 milliseconds. Signed-off-by: Douglas Gilbert <dgilbert@interlog.com> Tested-by: Ming Lei <ming.lei@redhat.com> Reported-by: Ming Lei <ming.lei@redhat.com> Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent af17092 commit 4f2c8bf

File tree

1 file changed

+24
-9
lines changed

1 file changed

+24
-9
lines changed

drivers/scsi/scsi_debug.c

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -234,11 +234,13 @@ static const char *sdebug_version_date = "20180128";
234234
#define F_INV_OP 0x200
235235
#define F_FAKE_RW 0x400
236236
#define F_M_ACCESS 0x800 /* media access */
237-
#define F_LONG_DELAY 0x1000
237+
#define F_SSU_DELAY 0x1000
238+
#define F_SYNC_DELAY 0x2000
238239

239240
#define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR)
240241
#define FF_MEDIA_IO (F_M_ACCESS | F_FAKE_RW)
241242
#define FF_SA (F_SA_HIGH | F_SA_LOW)
243+
#define F_LONG_DELAY (F_SSU_DELAY | F_SYNC_DELAY)
242244

243245
#define SDEBUG_MAX_PARTS 4
244246

@@ -510,7 +512,7 @@ static const struct opcode_info_t release_iarr[] = {
510512
};
511513

512514
static const struct opcode_info_t sync_cache_iarr[] = {
513-
{0, 0x91, 0, F_LONG_DELAY | F_M_ACCESS, resp_sync_cache, NULL,
515+
{0, 0x91, 0, F_SYNC_DELAY | F_M_ACCESS, resp_sync_cache, NULL,
514516
{16, 0x6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
515517
0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7} }, /* SYNC_CACHE (16) */
516518
};
@@ -553,7 +555,7 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = {
553555
resp_write_dt0, write_iarr, /* WRITE(16) */
554556
{16, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
555557
0xff, 0xff, 0xff, 0xff, 0xff, 0xc7} },
556-
{0, 0x1b, 0, F_LONG_DELAY, resp_start_stop, NULL,/* START STOP UNIT */
558+
{0, 0x1b, 0, F_SSU_DELAY, resp_start_stop, NULL,/* START STOP UNIT */
557559
{6, 0x1, 0, 0xf, 0xf7, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
558560
{ARRAY_SIZE(sa_in_16_iarr), 0x9e, 0x10, F_SA_LOW | F_D_IN,
559561
resp_readcap16, sa_in_16_iarr, /* SA_IN(16), READ CAPACITY(16) */
@@ -606,7 +608,7 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEMENT + 1] = {
606608
resp_write_same_10, write_same_iarr, /* WRITE SAME(10) */
607609
{10, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xc7, 0,
608610
0, 0, 0, 0, 0} },
609-
{ARRAY_SIZE(sync_cache_iarr), 0x35, 0, F_LONG_DELAY | F_M_ACCESS,
611+
{ARRAY_SIZE(sync_cache_iarr), 0x35, 0, F_SYNC_DELAY | F_M_ACCESS,
610612
resp_sync_cache, sync_cache_iarr,
611613
{10, 0x7, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xc7, 0, 0,
612614
0, 0, 0, 0} }, /* SYNC_CACHE (10) */
@@ -667,6 +669,7 @@ static bool sdebug_strict = DEF_STRICT;
667669
static bool sdebug_any_injecting_opt;
668670
static bool sdebug_verbose;
669671
static bool have_dif_prot;
672+
static bool write_since_sync;
670673
static bool sdebug_statistics = DEF_STATISTICS;
671674

672675
static unsigned int sdebug_store_sectors;
@@ -1607,15 +1610,20 @@ static int resp_start_stop(struct scsi_cmnd *scp,
16071610
{
16081611
unsigned char *cmd = scp->cmnd;
16091612
int power_cond, stop;
1613+
bool changing;
16101614

16111615
power_cond = (cmd[4] & 0xf0) >> 4;
16121616
if (power_cond) {
16131617
mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, 7);
16141618
return check_condition_result;
16151619
}
16161620
stop = !(cmd[4] & 1);
1621+
changing = atomic_read(&devip->stopped) == !stop;
16171622
atomic_xchg(&devip->stopped, stop);
1618-
return (cmd[1] & 0x1) ? SDEG_RES_IMMED_MASK : 0; /* check IMMED bit */
1623+
if (!changing || cmd[1] & 0x1) /* state unchanged or IMMED set */
1624+
return SDEG_RES_IMMED_MASK;
1625+
else
1626+
return 0;
16191627
}
16201628

16211629
static sector_t get_sdebug_capacity(void)
@@ -2473,6 +2481,7 @@ static int do_device_access(struct scsi_cmnd *scmd, u32 sg_skip, u64 lba,
24732481
if (do_write) {
24742482
sdb = scsi_out(scmd);
24752483
dir = DMA_TO_DEVICE;
2484+
write_since_sync = true;
24762485
} else {
24772486
sdb = scsi_in(scmd);
24782487
dir = DMA_FROM_DEVICE;
@@ -3583,6 +3592,7 @@ static int resp_get_lba_status(struct scsi_cmnd *scp,
35833592
static int resp_sync_cache(struct scsi_cmnd *scp,
35843593
struct sdebug_dev_info *devip)
35853594
{
3595+
int res = 0;
35863596
u64 lba;
35873597
u32 num_blocks;
35883598
u8 *cmd = scp->cmnd;
@@ -3598,7 +3608,11 @@ static int resp_sync_cache(struct scsi_cmnd *scp,
35983608
mk_sense_buffer(scp, ILLEGAL_REQUEST, LBA_OUT_OF_RANGE, 0);
35993609
return check_condition_result;
36003610
}
3601-
return (cmd[1] & 0x2) ? SDEG_RES_IMMED_MASK : 0; /* check IMMED bit */
3611+
if (!write_since_sync || cmd[1] & 0x2)
3612+
res = SDEG_RES_IMMED_MASK;
3613+
else /* delay if write_since_sync and IMMED clear */
3614+
write_since_sync = false;
3615+
return res;
36023616
}
36033617

36043618
#define RL_BUCKET_ELEMS 8
@@ -5777,13 +5791,14 @@ static int scsi_debug_queuecommand(struct Scsi_Host *shost,
57775791
return schedule_resp(scp, devip, errsts, pfp, 0, 0);
57785792
else if ((sdebug_jdelay || sdebug_ndelay) && (flags & F_LONG_DELAY)) {
57795793
/*
5780-
* If any delay is active, want F_LONG_DELAY to be at least 1
5794+
* If any delay is active, for F_SSU_DELAY want at least 1
57815795
* second and if sdebug_jdelay>0 want a long delay of that
5782-
* many seconds.
5796+
* many seconds; for F_SYNC_DELAY want 1/20 of that.
57835797
*/
57845798
int jdelay = (sdebug_jdelay < 2) ? 1 : sdebug_jdelay;
5799+
int denom = (flags & F_SYNC_DELAY) ? 20 : 1;
57855800

5786-
jdelay = mult_frac(USER_HZ * jdelay, HZ, USER_HZ);
5801+
jdelay = mult_frac(USER_HZ * jdelay, HZ, denom * USER_HZ);
57875802
return schedule_resp(scp, devip, errsts, pfp, jdelay, 0);
57885803
} else
57895804
return schedule_resp(scp, devip, errsts, pfp, sdebug_jdelay,

0 commit comments

Comments
 (0)