diff options
author | Douglas Gilbert <dougg@torque.net> | 2007-01-05 00:05:25 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-01-13 14:52:37 -0500 |
commit | 6f3cbf552e0557a463ad421f07b2e873a608406f (patch) | |
tree | 150e99a4d625ede99cb8356932f85ae726510304 /drivers/scsi/scsi_debug.c | |
parent | d780c3bf2150264947870bb68c057c26c2aff7cc (diff) |
[SCSI] scsi_debug: error processing
After discussions in the thread titled:
[PATCH] scsi_debug: illegal blocking memory allocation
here is a patch containing the discussed fix and some other
fixes and additions. The patch is against lk 2.6.20-rc3 .
The version is bumped to 1.81 .
ChangeLog:
- Change several GFP_KERNEL allocations to GFP_ATOMIC
as they can be called from queuecommand() context
- check above allocation returns and if out of memory
report DID_REQUEUE in two cases, DID_NO_CONNECT in
another, and fail slave configure() in another
- add support for WRITE BUFFER command
- add aborted_command error injection support
(opts mask 0x10), similar mechanism to
recovered_error injection.
Signed-off-by: Douglas Gilbert <dougg@torque.net>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/scsi_debug.c')
-rw-r--r-- | drivers/scsi/scsi_debug.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 30ee3d72c021..5adbbeedec38 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
@@ -51,10 +51,10 @@ | |||
51 | #include "scsi_logging.h" | 51 | #include "scsi_logging.h" |
52 | #include "scsi_debug.h" | 52 | #include "scsi_debug.h" |
53 | 53 | ||
54 | #define SCSI_DEBUG_VERSION "1.80" | 54 | #define SCSI_DEBUG_VERSION "1.81" |
55 | static const char * scsi_debug_version_date = "20061018"; | 55 | static const char * scsi_debug_version_date = "20070104"; |
56 | 56 | ||
57 | /* Additional Sense Code (ASC) used */ | 57 | /* Additional Sense Code (ASC) */ |
58 | #define NO_ADDITIONAL_SENSE 0x0 | 58 | #define NO_ADDITIONAL_SENSE 0x0 |
59 | #define LOGICAL_UNIT_NOT_READY 0x4 | 59 | #define LOGICAL_UNIT_NOT_READY 0x4 |
60 | #define UNRECOVERED_READ_ERR 0x11 | 60 | #define UNRECOVERED_READ_ERR 0x11 |
@@ -65,9 +65,13 @@ static const char * scsi_debug_version_date = "20061018"; | |||
65 | #define INVALID_FIELD_IN_PARAM_LIST 0x26 | 65 | #define INVALID_FIELD_IN_PARAM_LIST 0x26 |
66 | #define POWERON_RESET 0x29 | 66 | #define POWERON_RESET 0x29 |
67 | #define SAVING_PARAMS_UNSUP 0x39 | 67 | #define SAVING_PARAMS_UNSUP 0x39 |
68 | #define TRANSPORT_PROBLEM 0x4b | ||
68 | #define THRESHOLD_EXCEEDED 0x5d | 69 | #define THRESHOLD_EXCEEDED 0x5d |
69 | #define LOW_POWER_COND_ON 0x5e | 70 | #define LOW_POWER_COND_ON 0x5e |
70 | 71 | ||
72 | /* Additional Sense Code Qualifier (ASCQ) */ | ||
73 | #define ACK_NAK_TO 0x3 | ||
74 | |||
71 | #define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */ | 75 | #define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */ |
72 | 76 | ||
73 | /* Default values for driver parameters */ | 77 | /* Default values for driver parameters */ |
@@ -95,15 +99,20 @@ static const char * scsi_debug_version_date = "20061018"; | |||
95 | #define SCSI_DEBUG_OPT_MEDIUM_ERR 2 | 99 | #define SCSI_DEBUG_OPT_MEDIUM_ERR 2 |
96 | #define SCSI_DEBUG_OPT_TIMEOUT 4 | 100 | #define SCSI_DEBUG_OPT_TIMEOUT 4 |
97 | #define SCSI_DEBUG_OPT_RECOVERED_ERR 8 | 101 | #define SCSI_DEBUG_OPT_RECOVERED_ERR 8 |
102 | #define SCSI_DEBUG_OPT_TRANSPORT_ERR 16 | ||
98 | /* When "every_nth" > 0 then modulo "every_nth" commands: | 103 | /* When "every_nth" > 0 then modulo "every_nth" commands: |
99 | * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set | 104 | * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set |
100 | * - a RECOVERED_ERROR is simulated on successful read and write | 105 | * - a RECOVERED_ERROR is simulated on successful read and write |
101 | * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set. | 106 | * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set. |
107 | * - a TRANSPORT_ERROR is simulated on successful read and write | ||
108 | * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set. | ||
102 | * | 109 | * |
103 | * When "every_nth" < 0 then after "- every_nth" commands: | 110 | * When "every_nth" < 0 then after "- every_nth" commands: |
104 | * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set | 111 | * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set |
105 | * - a RECOVERED_ERROR is simulated on successful read and write | 112 | * - a RECOVERED_ERROR is simulated on successful read and write |
106 | * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set. | 113 | * commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set. |
114 | * - a TRANSPORT_ERROR is simulated on successful read and write | ||
115 | * commands if SCSI_DEBUG_OPT_TRANSPORT_ERR is set. | ||
107 | * This will continue until some other action occurs (e.g. the user | 116 | * This will continue until some other action occurs (e.g. the user |
108 | * writing a new value (other than -1 or 1) to every_nth via sysfs). | 117 | * writing a new value (other than -1 or 1) to every_nth via sysfs). |
109 | */ | 118 | */ |
@@ -315,6 +324,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) | |||
315 | int target = SCpnt->device->id; | 324 | int target = SCpnt->device->id; |
316 | struct sdebug_dev_info * devip = NULL; | 325 | struct sdebug_dev_info * devip = NULL; |
317 | int inj_recovered = 0; | 326 | int inj_recovered = 0; |
327 | int inj_transport = 0; | ||
318 | int delay_override = 0; | 328 | int delay_override = 0; |
319 | 329 | ||
320 | if (done == NULL) | 330 | if (done == NULL) |
@@ -352,6 +362,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) | |||
352 | return 0; /* ignore command causing timeout */ | 362 | return 0; /* ignore command causing timeout */ |
353 | else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts) | 363 | else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts) |
354 | inj_recovered = 1; /* to reads and writes below */ | 364 | inj_recovered = 1; /* to reads and writes below */ |
365 | else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts) | ||
366 | inj_transport = 1; /* to reads and writes below */ | ||
355 | } | 367 | } |
356 | 368 | ||
357 | if (devip->wlun) { | 369 | if (devip->wlun) { |
@@ -468,7 +480,11 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) | |||
468 | mk_sense_buffer(devip, RECOVERED_ERROR, | 480 | mk_sense_buffer(devip, RECOVERED_ERROR, |
469 | THRESHOLD_EXCEEDED, 0); | 481 | THRESHOLD_EXCEEDED, 0); |
470 | errsts = check_condition_result; | 482 | errsts = check_condition_result; |
471 | } | 483 | } else if (inj_transport && (0 == errsts)) { |
484 | mk_sense_buffer(devip, ABORTED_COMMAND, | ||
485 | TRANSPORT_PROBLEM, ACK_NAK_TO); | ||
486 | errsts = check_condition_result; | ||
487 | } | ||
472 | break; | 488 | break; |
473 | case REPORT_LUNS: /* mandatory, ignore unit attention */ | 489 | case REPORT_LUNS: /* mandatory, ignore unit attention */ |
474 | delay_override = 1; | 490 | delay_override = 1; |
@@ -531,6 +547,9 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) | |||
531 | delay_override = 1; | 547 | delay_override = 1; |
532 | errsts = check_readiness(SCpnt, 0, devip); | 548 | errsts = check_readiness(SCpnt, 0, devip); |
533 | break; | 549 | break; |
550 | case WRITE_BUFFER: | ||
551 | errsts = check_readiness(SCpnt, 1, devip); | ||
552 | break; | ||
534 | default: | 553 | default: |
535 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | 554 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) |
536 | printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " | 555 | printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " |
@@ -954,7 +973,9 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, | |||
954 | int alloc_len, n, ret; | 973 | int alloc_len, n, ret; |
955 | 974 | ||
956 | alloc_len = (cmd[3] << 8) + cmd[4]; | 975 | alloc_len = (cmd[3] << 8) + cmd[4]; |
957 | arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_KERNEL); | 976 | arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_ATOMIC); |
977 | if (! arr) | ||
978 | return DID_REQUEUE << 16; | ||
958 | if (devip->wlun) | 979 | if (devip->wlun) |
959 | pq_pdt = 0x1e; /* present, wlun */ | 980 | pq_pdt = 0x1e; /* present, wlun */ |
960 | else if (scsi_debug_no_lun_0 && (0 == devip->lun)) | 981 | else if (scsi_debug_no_lun_0 && (0 == devip->lun)) |
@@ -1217,7 +1238,9 @@ static int resp_report_tgtpgs(struct scsi_cmnd * scp, | |||
1217 | alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8) | 1238 | alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8) |
1218 | + cmd[9]); | 1239 | + cmd[9]); |
1219 | 1240 | ||
1220 | arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_KERNEL); | 1241 | arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_ATOMIC); |
1242 | if (! arr) | ||
1243 | return DID_REQUEUE << 16; | ||
1221 | /* | 1244 | /* |
1222 | * EVPD page 0x88 states we have two ports, one | 1245 | * EVPD page 0x88 states we have two ports, one |
1223 | * real and a fake port with no device connected. | 1246 | * real and a fake port with no device connected. |
@@ -1996,6 +2019,8 @@ static int scsi_debug_slave_configure(struct scsi_device * sdp) | |||
1996 | if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN) | 2019 | if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN) |
1997 | sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN; | 2020 | sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN; |
1998 | devip = devInfoReg(sdp); | 2021 | devip = devInfoReg(sdp); |
2022 | if (NULL == devip) | ||
2023 | return 1; /* no resources, will be marked offline */ | ||
1999 | sdp->hostdata = devip; | 2024 | sdp->hostdata = devip; |
2000 | if (sdp->host->cmd_per_lun) | 2025 | if (sdp->host->cmd_per_lun) |
2001 | scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING, | 2026 | scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING, |
@@ -2044,7 +2069,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) | |||
2044 | } | 2069 | } |
2045 | } | 2070 | } |
2046 | if (NULL == open_devip) { /* try and make a new one */ | 2071 | if (NULL == open_devip) { /* try and make a new one */ |
2047 | open_devip = kzalloc(sizeof(*open_devip),GFP_KERNEL); | 2072 | open_devip = kzalloc(sizeof(*open_devip),GFP_ATOMIC); |
2048 | if (NULL == open_devip) { | 2073 | if (NULL == open_devip) { |
2049 | printk(KERN_ERR "%s: out of memory at line %d\n", | 2074 | printk(KERN_ERR "%s: out of memory at line %d\n", |
2050 | __FUNCTION__, __LINE__); | 2075 | __FUNCTION__, __LINE__); |
@@ -2388,7 +2413,7 @@ MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)"); | |||
2388 | MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)"); | 2413 | MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)"); |
2389 | MODULE_PARM_DESC(num_parts, "number of partitions(def=0)"); | 2414 | MODULE_PARM_DESC(num_parts, "number of partitions(def=0)"); |
2390 | MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)"); | 2415 | MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)"); |
2391 | MODULE_PARM_DESC(opts, "1->noise, 2->medium_error, 4->... (def=0)"); | 2416 | MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)"); |
2392 | MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])"); | 2417 | MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])"); |
2393 | MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])"); | 2418 | MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])"); |
2394 | MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)"); | 2419 | MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)"); |
@@ -2943,7 +2968,6 @@ static int sdebug_add_adapter(void) | |||
2943 | struct list_head *lh, *lh_sf; | 2968 | struct list_head *lh, *lh_sf; |
2944 | 2969 | ||
2945 | sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL); | 2970 | sdbg_host = kzalloc(sizeof(*sdbg_host),GFP_KERNEL); |
2946 | |||
2947 | if (NULL == sdbg_host) { | 2971 | if (NULL == sdbg_host) { |
2948 | printk(KERN_ERR "%s: out of memory at line %d\n", | 2972 | printk(KERN_ERR "%s: out of memory at line %d\n", |
2949 | __FUNCTION__, __LINE__); | 2973 | __FUNCTION__, __LINE__); |