Commit 16b7fc66 authored by Douglas Gilbert's avatar Douglas Gilbert Committed by James Bottomley

[PATCH] scsi_debug in 2.5.64

Here is a second attempt to patch scsi_debug in
2.5.64 . My reference version was out of sync in
my previous posting.

Changelog:
   - add recovered error injection (this is a bit
     different to the patch proposed by Kurt Garloff)
   - fix flakiness in scsi_cmnd::result when errors
     are being injected
   - fix medium error injection
   - make "every_nth" writeable in sysfs
   - small re-arrangement of error flags in "opts"
   - clean up some of the naming

Updated http://www.torque.net/sg/sdebug25.html

This patch does not include Mike Anderson's sysfs
probe() cleanup.

In 2.5.64 scsi error handling is flaky and sysfs is
especially flaky in 2.5.64-bk3. I'll send some finding
to the list when things stabilize a bit. [For anyone
who is bored, try following the tortured sequence
of scsi commands generated by the block/sd/mid-level
layers in response to a persistent medium error.]
parent ca636121
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
#include "scsi_debug.h" #include "scsi_debug.h"
static const char * scsi_debug_version_str = "Version: 1.67 (20021221)"; static const char * scsi_debug_version_str = "Version: 1.68 (20030309)";
#ifndef SCSI_CMD_READ_16 #ifndef SCSI_CMD_READ_16
#define SCSI_CMD_READ_16 0x88 #define SCSI_CMD_READ_16 0x88
...@@ -68,7 +68,7 @@ static const char * scsi_debug_version_str = "Version: 1.67 (20021221)"; ...@@ -68,7 +68,7 @@ static const char * scsi_debug_version_str = "Version: 1.67 (20021221)";
/* Default values for driver parameters */ /* Default values for driver parameters */
#define DEF_NUM_DEVS 1 #define DEF_NUM_DEVS 1
#define DEF_DEV_SIZE_MB 8 #define DEF_DEV_SIZE_MB 8
#define DEF_EVERY_NTH 100 #define DEF_EVERY_NTH 0
#define DEF_DELAY 1 #define DEF_DELAY 1
#define DEF_MAX_LUNS 2 #define DEF_MAX_LUNS 2
#define DEF_SCSI_LEVEL 3 #define DEF_SCSI_LEVEL 3
...@@ -80,9 +80,17 @@ static const char * scsi_debug_version_str = "Version: 1.67 (20021221)"; ...@@ -80,9 +80,17 @@ static const char * scsi_debug_version_str = "Version: 1.67 (20021221)";
/* bit mask values for scsi_debug_opts */ /* bit mask values for scsi_debug_opts */
#define SCSI_DEBUG_OPT_NOISE 1 #define SCSI_DEBUG_OPT_NOISE 1
#define SCSI_DEBUG_OPT_MEDIUM_ERR 2 #define SCSI_DEBUG_OPT_MEDIUM_ERR 2
#define SCSI_DEBUG_OPT_EVERY_NTH 4 #define SCSI_DEBUG_OPT_TIMEOUT 4
#define SCSI_DEBUG_OPT_RECOVERED_ERR 8
/* When "every_nth" > 0 then modulo "every_nth" commands:
* - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
* - a RECOVERED_ERROR is simulated on successful read and write
* commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
*/
#define OPT_MEDIUM_ERR_ADDR 0x1234 /* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
* sector on read commands: */
#define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */
static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB; static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;
static int scsi_debug_num_devs = DEF_NUM_DEVS; static int scsi_debug_num_devs = DEF_NUM_DEVS;
...@@ -161,6 +169,9 @@ static struct device_driver sdebug_driverfs_driver = { ...@@ -161,6 +169,9 @@ static struct device_driver sdebug_driverfs_driver = {
.devclass = &shost_devclass, .devclass = &shost_devclass,
}; };
static const int check_condition_result =
(DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
/* function declarations */ /* function declarations */
static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff, static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
int bufflen, struct sdebug_dev_info * devip); int bufflen, struct sdebug_dev_info * devip);
...@@ -222,6 +233,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) ...@@ -222,6 +233,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
unsigned long capac; unsigned long capac;
struct sdebug_dev_info * devip = NULL; struct sdebug_dev_info * devip = NULL;
unsigned char * sbuff; unsigned char * sbuff;
int inj_recovered = 0;
if (done == NULL) if (done == NULL)
return 0; /* assume mid level reprocessing command */ return 0; /* assume mid level reprocessing command */
...@@ -255,11 +267,13 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) ...@@ -255,11 +267,13 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
return schedule_resp(SCpnt, NULL, done, return schedule_resp(SCpnt, NULL, done,
DID_NO_CONNECT << 16, 0); DID_NO_CONNECT << 16, 0);
if ((SCSI_DEBUG_OPT_EVERY_NTH & scsi_debug_opts) && if ((scsi_debug_every_nth > 0) &&
(scsi_debug_every_nth > 0) &&
(++scsi_debug_cmnd_count >= scsi_debug_every_nth)) { (++scsi_debug_cmnd_count >= scsi_debug_every_nth)) {
scsi_debug_cmnd_count =0; scsi_debug_cmnd_count =0;
if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
return 0; /* ignore command causing timeout */ return 0; /* ignore command causing timeout */
else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts)
inj_recovered = 1; /* to reads and writes below */
} }
switch (*cmd) { switch (*cmd) {
...@@ -269,8 +283,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) ...@@ -269,8 +283,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
case REQUEST_SENSE: /* mandatory */ case REQUEST_SENSE: /* mandatory */
/* Since this driver indicates autosense by placing the /* Since this driver indicates autosense by placing the
* sense buffer in the scsi_cmnd structure in the response * sense buffer in the scsi_cmnd structure in the response
* (when CHECK_CONDITION is set), the mid level shouldn't * (when SAM_STAT_CHECK_CONDITION is set), the mid level
* need to call REQUEST_SENSE */ * shouldn't need to call REQUEST_SENSE */
if (devip) { if (devip) {
sbuff = devip->sense_buff; sbuff = devip->sense_buff;
memcpy(buff, sbuff, (bufflen < SDEBUG_SENSE_LEN) ? memcpy(buff, sbuff, (bufflen < SDEBUG_SENSE_LEN) ?
...@@ -355,6 +369,10 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) ...@@ -355,6 +369,10 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
num = cmd[4]; num = cmd[4];
} }
errsts = resp_read(SCpnt, upper_blk, block, num, devip); errsts = resp_read(SCpnt, upper_blk, block, num, devip);
if (inj_recovered && (0 == errsts)) {
mk_sense_buffer(devip, RECOVERED_ERROR, 0x5d, 0, 14);
errsts = check_condition_result;
}
break; break;
case REPORT_LUNS: case REPORT_LUNS:
errsts = resp_report_luns(cmd, buff, bufflen, devip); errsts = resp_report_luns(cmd, buff, bufflen, devip);
...@@ -388,6 +406,10 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) ...@@ -388,6 +406,10 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
num = cmd[4]; num = cmd[4];
} }
errsts = resp_write(SCpnt, upper_blk, block, num, devip); errsts = resp_write(SCpnt, upper_blk, block, num, devip);
if (inj_recovered && (0 == errsts)) {
mk_sense_buffer(devip, RECOVERED_ERROR, 0x5d, 0, 14);
errsts = check_condition_result;
}
break; break;
case MODE_SENSE: case MODE_SENSE:
case MODE_SENSE_10: case MODE_SENSE_10:
...@@ -400,7 +422,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) ...@@ -400,7 +422,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
if ((errsts = check_reset(SCpnt, devip))) if ((errsts = check_reset(SCpnt, devip)))
break; break;
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x20, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x20, 0, 14);
errsts = (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); errsts = check_condition_result;
break; break;
} }
return schedule_resp(SCpnt, devip, done, errsts, scsi_debug_delay); return schedule_resp(SCpnt, devip, done, errsts, scsi_debug_delay);
...@@ -420,7 +442,7 @@ static int check_reset(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip) ...@@ -420,7 +442,7 @@ static int check_reset(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip)
if (devip->reset) { if (devip->reset) {
devip->reset = 0; devip->reset = 0;
mk_sense_buffer(devip, UNIT_ATTENTION, 0x29, 0, 14); mk_sense_buffer(devip, UNIT_ATTENTION, 0x29, 0, 14);
return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); return check_condition_result;
} }
return 0; return 0;
} }
...@@ -481,7 +503,7 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff, ...@@ -481,7 +503,7 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
arr[0] = pq_pdt; arr[0] = pq_pdt;
if (0x2 & cmd[1]) { /* CMDDT bit set */ if (0x2 & cmd[1]) { /* CMDDT bit set */
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); return check_condition_result;
} else if (0x1 & cmd[1]) { /* EVPD bit set */ } else if (0x1 & cmd[1]) { /* EVPD bit set */
int dev_id_num, len; int dev_id_num, len;
char dev_id_str[6]; char dev_id_str[6];
...@@ -506,7 +528,7 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff, ...@@ -506,7 +528,7 @@ static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
} else { } else {
/* Illegal request, invalid field in cdb */ /* Illegal request, invalid field in cdb */
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); return check_condition_result;
} }
memcpy(buff, arr, min_len); memcpy(buff, arr, min_len);
return 0; return 0;
...@@ -619,7 +641,7 @@ static int resp_mode_sense(unsigned char * cmd, int target, ...@@ -619,7 +641,7 @@ static int resp_mode_sense(unsigned char * cmd, int target,
memset(arr, 0, SDEBUG_MAX_MSENSE_SZ); memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
if (0x3 == pcontrol) { /* Saving values not supported */ if (0x3 == pcontrol) { /* Saving values not supported */
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x39, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x39, 0, 14);
return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); return check_condition_result;
} }
dev_spec = DEV_READONLY(target) ? 0x80 : 0x0; dev_spec = DEV_READONLY(target) ? 0x80 : 0x0;
if (msense_6) { if (msense_6) {
...@@ -662,7 +684,7 @@ static int resp_mode_sense(unsigned char * cmd, int target, ...@@ -662,7 +684,7 @@ static int resp_mode_sense(unsigned char * cmd, int target,
break; break;
default: default:
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); return check_condition_result;
} }
if (msense_6) if (msense_6)
arr[0] = offset - 1; arr[0] = offset - 1;
...@@ -686,14 +708,14 @@ static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block, ...@@ -686,14 +708,14 @@ static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block,
if (upper_blk || (block + num > sdebug_capacity)) { if (upper_blk || (block + num > sdebug_capacity)) {
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14);
return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); return check_condition_result;
} }
if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) && if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
(block >= OPT_MEDIUM_ERR_ADDR) && (block <= OPT_MEDIUM_ERR_ADDR) &&
(block < (OPT_MEDIUM_ERR_ADDR + num))) { ((block + num) > OPT_MEDIUM_ERR_ADDR)) {
mk_sense_buffer(devip, MEDIUM_ERROR, 0x11, 0, 14); mk_sense_buffer(devip, MEDIUM_ERROR, 0x11, 0, 14);
/* claim unrecoverable read error */ /* claim unrecoverable read error */
return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); return check_condition_result;
} }
read_lock_irqsave(&atomic_rw, iflags); read_lock_irqsave(&atomic_rw, iflags);
sgcount = 0; sgcount = 0;
...@@ -735,7 +757,7 @@ static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block, ...@@ -735,7 +757,7 @@ static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block,
if (upper_blk || (block + num > sdebug_capacity)) { if (upper_blk || (block + num > sdebug_capacity)) {
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x21, 0, 14);
return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); return check_condition_result;
} }
write_lock_irqsave(&atomic_rw, iflags); write_lock_irqsave(&atomic_rw, iflags);
...@@ -776,7 +798,7 @@ static int resp_report_luns(unsigned char * cmd, unsigned char * buff, ...@@ -776,7 +798,7 @@ static int resp_report_luns(unsigned char * cmd, unsigned char * buff,
alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
if ((alloc_len < 16) || (select_report > 2)) { if ((alloc_len < 16) || (select_report > 2)) {
mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14); mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x24, 0, 14);
return (DRIVER_SENSE << 24) | (CHECK_CONDITION << 1); return check_condition_result;
} }
if (bufflen > 3) { if (bufflen > 3) {
lun_cnt = min((int)(bufflen / sizeof(ScsiLun)), lun_cnt = min((int)(bufflen / sizeof(ScsiLun)),
...@@ -810,8 +832,10 @@ static void timer_intr_handler(unsigned long indx) ...@@ -810,8 +832,10 @@ static void timer_intr_handler(unsigned long indx)
return; return;
} }
sqcp->in_use = 0; sqcp->in_use = 0;
if (sqcp->done_funct) if (sqcp->done_funct) {
sqcp->a_cmnd->result = sqcp->scsi_result;
sqcp->done_funct(sqcp->a_cmnd); /* callback to mid level */ sqcp->done_funct(sqcp->a_cmnd); /* callback to mid level */
}
sqcp->done_funct = NULL; sqcp->done_funct = NULL;
spin_unlock_irqrestore(&queued_arr_lock, iflags); spin_unlock_irqrestore(&queued_arr_lock, iflags);
} }
...@@ -1063,7 +1087,7 @@ static int schedule_resp(struct scsi_cmnd * cmnd, ...@@ -1063,7 +1087,7 @@ static int schedule_resp(struct scsi_cmnd * cmnd,
} }
if (cmnd && devip) { if (cmnd && devip) {
/* simulate autosense by this driver */ /* simulate autosense by this driver */
if (CHECK_CONDITION == status_byte(scsi_result)) if (SAM_STAT_CHECK_CONDITION == (scsi_result & 0xff))
memcpy(cmnd->sense_buffer, devip->sense_buff, memcpy(cmnd->sense_buffer, devip->sense_buff,
(SCSI_SENSE_BUFFERSIZE > SDEBUG_SENSE_LEN) ? (SCSI_SENSE_BUFFERSIZE > SDEBUG_SENSE_LEN) ?
SDEBUG_SENSE_LEN : SCSI_SENSE_BUFFERSIZE); SDEBUG_SENSE_LEN : SCSI_SENSE_BUFFERSIZE);
...@@ -1099,6 +1123,8 @@ static int schedule_resp(struct scsi_cmnd * cmnd, ...@@ -1099,6 +1123,8 @@ static int schedule_resp(struct scsi_cmnd * cmnd,
sqcp->cmnd_timer.expires = jiffies + delta_jiff; sqcp->cmnd_timer.expires = jiffies + delta_jiff;
add_timer(&sqcp->cmnd_timer); add_timer(&sqcp->cmnd_timer);
spin_unlock_irqrestore(&queued_arr_lock, iflags); spin_unlock_irqrestore(&queued_arr_lock, iflags);
if (cmnd)
cmnd->result = 0;
return 0; return 0;
} }
} }
...@@ -1163,7 +1189,7 @@ static int scsi_debug_proc_info(char *buffer, char **start, off_t offset, ...@@ -1163,7 +1189,7 @@ static int scsi_debug_proc_info(char *buffer, char **start, off_t offset,
if (1 != sscanf(arr, "%d", &pos)) if (1 != sscanf(arr, "%d", &pos))
return -EINVAL; return -EINVAL;
scsi_debug_opts = pos; scsi_debug_opts = pos;
if (SCSI_DEBUG_OPT_EVERY_NTH & scsi_debug_opts) if (scsi_debug_every_nth > 0)
scsi_debug_cmnd_count = 0; scsi_debug_cmnd_count = 0;
return length; return length;
} }
...@@ -1192,12 +1218,12 @@ static int scsi_debug_proc_info(char *buffer, char **start, off_t offset, ...@@ -1192,12 +1218,12 @@ static int scsi_debug_proc_info(char *buffer, char **start, off_t offset,
return len; return len;
} }
static ssize_t sdebug_delay_read(struct device_driver * ddp, char * buf) static ssize_t sdebug_delay_show(struct device_driver * ddp, char * buf)
{ {
return sprintf(buf, "%d\n", scsi_debug_delay); return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay);
} }
static ssize_t sdebug_delay_write(struct device_driver * ddp, static ssize_t sdebug_delay_store(struct device_driver * ddp,
const char * buf, size_t count) const char * buf, size_t count)
{ {
int delay; int delay;
...@@ -1211,15 +1237,15 @@ static ssize_t sdebug_delay_write(struct device_driver * ddp, ...@@ -1211,15 +1237,15 @@ static ssize_t sdebug_delay_write(struct device_driver * ddp,
} }
return -EINVAL; return -EINVAL;
} }
DRIVER_ATTR(delay, S_IRUGO | S_IWUSR, sdebug_delay_read, DRIVER_ATTR(delay, S_IRUGO | S_IWUSR, sdebug_delay_show,
sdebug_delay_write) sdebug_delay_store)
static ssize_t sdebug_opts_read(struct device_driver * ddp, char * buf) static ssize_t sdebug_opts_show(struct device_driver * ddp, char * buf)
{ {
return sprintf(buf, "0x%x\n", scsi_debug_opts); return snprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts);
} }
static ssize_t sdebug_opts_write(struct device_driver * ddp, static ssize_t sdebug_opts_store(struct device_driver * ddp,
const char * buf, size_t count) const char * buf, size_t count)
{ {
int opts; int opts;
...@@ -1237,47 +1263,61 @@ static ssize_t sdebug_opts_write(struct device_driver * ddp, ...@@ -1237,47 +1263,61 @@ static ssize_t sdebug_opts_write(struct device_driver * ddp,
return -EINVAL; return -EINVAL;
opts_done: opts_done:
scsi_debug_opts = opts; scsi_debug_opts = opts;
scsi_debug_cmnd_count = 0;
return count; return count;
} }
DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_read, DRIVER_ATTR(opts, S_IRUGO | S_IWUSR, sdebug_opts_show,
sdebug_opts_write) sdebug_opts_store)
static ssize_t sdebug_num_devs_read(struct device_driver * ddp, char * buf) static ssize_t sdebug_num_devs_show(struct device_driver * ddp, char * buf)
{ {
return sprintf(buf, "%d\n", scsi_debug_num_devs); return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_num_devs);
} }
DRIVER_ATTR(num_devs, S_IRUGO, sdebug_num_devs_read, NULL) DRIVER_ATTR(num_devs, S_IRUGO, sdebug_num_devs_show, NULL)
static ssize_t sdebug_dev_size_mb_read(struct device_driver * ddp, char * buf) static ssize_t sdebug_dev_size_mb_show(struct device_driver * ddp, char * buf)
{ {
return sprintf(buf, "%d\n", scsi_debug_dev_size_mb); return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dev_size_mb);
} }
DRIVER_ATTR(dev_size_mb, S_IRUGO, sdebug_dev_size_mb_read, NULL) DRIVER_ATTR(dev_size_mb, S_IRUGO, sdebug_dev_size_mb_show, NULL)
static ssize_t sdebug_every_nth_read(struct device_driver * ddp, char * buf) static ssize_t sdebug_every_nth_show(struct device_driver * ddp, char * buf)
{ {
return sprintf(buf, "%d\n", scsi_debug_every_nth); return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_every_nth);
}
static ssize_t sdebug_every_nth_store(struct device_driver * ddp,
const char * buf, size_t count)
{
int nth;
if ((count > 0) && (1 == sscanf(buf, "%d", &nth)) && (nth >= 0)) {
scsi_debug_every_nth = nth;
scsi_debug_cmnd_count = 0;
return count;
}
return -EINVAL;
} }
DRIVER_ATTR(every_nth, S_IRUGO, sdebug_every_nth_read, NULL) DRIVER_ATTR(every_nth, S_IRUGO | S_IWUSR, sdebug_every_nth_show,
sdebug_every_nth_store)
static ssize_t sdebug_max_luns_read(struct device_driver * ddp, char * buf) static ssize_t sdebug_max_luns_show(struct device_driver * ddp, char * buf)
{ {
return sprintf(buf, "%d\n", scsi_debug_max_luns); return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_luns);
} }
DRIVER_ATTR(max_luns, S_IRUGO, sdebug_max_luns_read, NULL) DRIVER_ATTR(max_luns, S_IRUGO, sdebug_max_luns_show, NULL)
static ssize_t sdebug_scsi_level_read(struct device_driver * ddp, char * buf) static ssize_t sdebug_scsi_level_show(struct device_driver * ddp, char * buf)
{ {
return sprintf(buf, "%d\n", scsi_debug_scsi_level); return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_scsi_level);
} }
DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_read, NULL) DRIVER_ATTR(scsi_level, S_IRUGO, sdebug_scsi_level_show, NULL)
static ssize_t sdebug_add_host_read(struct device_driver * ddp, char * buf) static ssize_t sdebug_add_host_show(struct device_driver * ddp, char * buf)
{ {
return sprintf(buf, "%d\n", scsi_debug_add_host); return snprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_add_host);
} }
static ssize_t sdebug_add_host_write(struct device_driver * ddp, static ssize_t sdebug_add_host_store(struct device_driver * ddp,
const char * buf, size_t count) const char * buf, size_t count)
{ {
int delta_hosts, k; int delta_hosts, k;
...@@ -1322,8 +1362,8 @@ static ssize_t sdebug_add_host_write(struct device_driver * ddp, ...@@ -1322,8 +1362,8 @@ static ssize_t sdebug_add_host_write(struct device_driver * ddp,
} }
return count; return count;
} }
DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_read, DRIVER_ATTR(add_host, S_IRUGO | S_IWUSR, sdebug_add_host_show,
sdebug_add_host_write) sdebug_add_host_store)
static void do_create_driverfs_files() static void do_create_driverfs_files()
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment