| 1 | |
| 2 | |
| 3 | * KUnit tests for scsi_lib.c.
|
| 4 | *
|
| 5 | * Copyright (C) 2023, Oracle Corporation
|
| 6 |
|
| 7 | #include <kunit/test.h>
|
| 8 |
|
| 9 | #include <scsi/scsi_proto.h>
|
| 10 | #include <scsi/scsi_cmnd.h>
|
| 11 | #include <scsi/scsi_device.h>
|
| 12 |
|
| 13 | #define SCSI_LIB_TEST_MAX_ALLOWED 3
|
| 14 | #define SCSI_LIB_TEST_TOTAL_MAX_ALLOWED 5
|
| 15 |
|
| 16 | static void scsi_lib_test_multiple_sense(struct kunit *test)
|
| 17 | {
|
| 18 | struct scsi_failure multiple_sense_failure_defs[] = {
|
| 19 | {
|
| 20 | .sense = DATA_PROTECT,
|
| 21 | .asc = 0x1,
|
| 22 | .ascq = 0x1,
|
| 23 | .result = SAM_STAT_CHECK_CONDITION,
|
| 24 | },
|
| 25 | {
|
| 26 | .sense = UNIT_ATTENTION,
|
| 27 | .asc = 0x11,
|
| 28 | .ascq = 0x0,
|
| 29 | .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
|
| 30 | .result = SAM_STAT_CHECK_CONDITION,
|
| 31 | },
|
| 32 | {
|
| 33 | .sense = NOT_READY,
|
| 34 | .asc = 0x11,
|
| 35 | .ascq = 0x22,
|
| 36 | .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
|
| 37 | .result = SAM_STAT_CHECK_CONDITION,
|
| 38 | },
|
| 39 | {
|
| 40 | .sense = ABORTED_COMMAND,
|
| 41 | .asc = 0x11,
|
| 42 | .ascq = SCMD_FAILURE_ASCQ_ANY,
|
| 43 | .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
|
| 44 | .result = SAM_STAT_CHECK_CONDITION,
|
| 45 | },
|
| 46 | {
|
| 47 | .sense = HARDWARE_ERROR,
|
| 48 | .asc = SCMD_FAILURE_ASC_ANY,
|
| 49 | .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
|
| 50 | .result = SAM_STAT_CHECK_CONDITION,
|
| 51 | },
|
| 52 | {
|
| 53 | .sense = ILLEGAL_REQUEST,
|
| 54 | .asc = 0x91,
|
| 55 | .ascq = 0x36,
|
| 56 | .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
|
| 57 | .result = SAM_STAT_CHECK_CONDITION,
|
| 58 | },
|
| 59 | {}
|
| 60 | };
|
| 61 | struct scsi_failures failures = {
|
| 62 | .failure_definitions = multiple_sense_failure_defs,
|
| 63 | };
|
| 64 | u8 sense[SCSI_SENSE_BUFFERSIZE] = {};
|
| 65 | struct scsi_cmnd sc = {
|
| 66 | .sense_buffer = sense,
|
| 67 | };
|
| 68 | int i;
|
| 69 |
|
| 70 |
|
| 71 | sc.result = 0;
|
| 72 | KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
|
| 73 | KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, NULL));
|
| 74 |
|
| 75 | scsi_build_sense(&sc, 0, ILLEGAL_REQUEST, 0x91, 0x36);
|
| 76 | KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, NULL));
|
| 77 |
|
| 78 | scsi_build_sense(&sc, 0, ILLEGAL_REQUEST, 0x91, 0x36);
|
| 79 | KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
|
| 80 |
|
| 81 | scsi_build_sense(&sc, 0, UNIT_ATTENTION, 0x11, 0x0);
|
| 82 | KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
|
| 83 |
|
| 84 | scsi_build_sense(&sc, 0, MISCOMPARE, 0x11, 0x11);
|
| 85 | KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
|
| 86 |
|
| 87 | scsi_build_sense(&sc, 0, ABORTED_COMMAND, 0x11, 0x22);
|
| 88 | KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
|
| 89 |
|
| 90 | scsi_build_sense(&sc, 0, ABORTED_COMMAND, 0x22, 0x22);
|
| 91 | KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
|
| 92 |
|
| 93 | scsi_build_sense(&sc, 0, HARDWARE_ERROR, 0x11, 0x22);
|
| 94 | KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
|
| 95 |
|
| 96 | sc.result = SAM_STAT_RESERVATION_CONFLICT;
|
| 97 | KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
|
| 98 |
|
| 99 |
|
| 100 | scsi_build_sense(&sc, 0, NOT_READY, 0x11, 0x22);
|
| 101 | for (i = 0; i < SCSI_LIB_TEST_MAX_ALLOWED; i++)
|
| 102 | KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc,
|
| 103 | &failures));
|
| 104 | KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
|
| 105 |
|
| 106 |
|
| 107 | failures.failure_definitions = multiple_sense_failure_defs;
|
| 108 | scsi_failures_reset_retries(&failures);
|
| 109 |
|
| 110 |
|
| 111 | scsi_build_sense(&sc, 0, DATA_PROTECT, 0x1, 0x1);
|
| 112 | KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
|
| 113 | }
|
| 114 |
|
| 115 | static void scsi_lib_test_any_sense(struct kunit *test)
|
| 116 | {
|
| 117 | struct scsi_failure any_sense_failure_defs[] = {
|
| 118 | {
|
| 119 | .result = SCMD_FAILURE_SENSE_ANY,
|
| 120 | .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
|
| 121 | },
|
| 122 | {}
|
| 123 | };
|
| 124 | struct scsi_failures failures = {
|
| 125 | .failure_definitions = any_sense_failure_defs,
|
| 126 | };
|
| 127 | u8 sense[SCSI_SENSE_BUFFERSIZE] = {};
|
| 128 | struct scsi_cmnd sc = {
|
| 129 | .sense_buffer = sense,
|
| 130 | };
|
| 131 |
|
| 132 |
|
| 133 | failures.failure_definitions = any_sense_failure_defs;
|
| 134 | scsi_build_sense(&sc, 0, MEDIUM_ERROR, 0x11, 0x22);
|
| 135 | KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
|
| 136 | }
|
| 137 |
|
| 138 | static void scsi_lib_test_host(struct kunit *test)
|
| 139 | {
|
| 140 | struct scsi_failure retryable_host_failure_defs[] = {
|
| 141 | {
|
| 142 | .result = DID_TRANSPORT_DISRUPTED << 16,
|
| 143 | .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
|
| 144 | },
|
| 145 | {
|
| 146 | .result = DID_TIME_OUT << 16,
|
| 147 | .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
|
| 148 | },
|
| 149 | {}
|
| 150 | };
|
| 151 | struct scsi_failures failures = {
|
| 152 | .failure_definitions = retryable_host_failure_defs,
|
| 153 | };
|
| 154 | u8 sense[SCSI_SENSE_BUFFERSIZE] = {};
|
| 155 | struct scsi_cmnd sc = {
|
| 156 | .sense_buffer = sense,
|
| 157 | };
|
| 158 |
|
| 159 |
|
| 160 | failures.failure_definitions = retryable_host_failure_defs;
|
| 161 | sc.result = DID_NO_CONNECT << 16;
|
| 162 | KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
|
| 163 |
|
| 164 | sc.result = DID_TIME_OUT << 16;
|
| 165 | KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
|
| 166 | }
|
| 167 |
|
| 168 | static void scsi_lib_test_any_failure(struct kunit *test)
|
| 169 | {
|
| 170 | struct scsi_failure any_failure_defs[] = {
|
| 171 | {
|
| 172 | .result = SCMD_FAILURE_RESULT_ANY,
|
| 173 | .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
|
| 174 | },
|
| 175 | {}
|
| 176 | };
|
| 177 | struct scsi_failures failures = {
|
| 178 | .failure_definitions = any_failure_defs,
|
| 179 | };
|
| 180 | u8 sense[SCSI_SENSE_BUFFERSIZE] = {};
|
| 181 | struct scsi_cmnd sc = {
|
| 182 | .sense_buffer = sense,
|
| 183 | };
|
| 184 |
|
| 185 |
|
| 186 | failures.failure_definitions = any_failure_defs;
|
| 187 | sc.result = DID_TRANSPORT_FAILFAST << 16;
|
| 188 | KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
|
| 189 | }
|
| 190 |
|
| 191 | static void scsi_lib_test_any_status(struct kunit *test)
|
| 192 | {
|
| 193 | struct scsi_failure any_status_failure_defs[] = {
|
| 194 | {
|
| 195 | .result = SCMD_FAILURE_STAT_ANY,
|
| 196 | .allowed = SCSI_LIB_TEST_MAX_ALLOWED,
|
| 197 | },
|
| 198 | {}
|
| 199 | };
|
| 200 | struct scsi_failures failures = {
|
| 201 | .failure_definitions = any_status_failure_defs,
|
| 202 | };
|
| 203 | u8 sense[SCSI_SENSE_BUFFERSIZE] = {};
|
| 204 | struct scsi_cmnd sc = {
|
| 205 | .sense_buffer = sense,
|
| 206 | };
|
| 207 |
|
| 208 |
|
| 209 | failures.failure_definitions = any_status_failure_defs;
|
| 210 | sc.result = SAM_STAT_RESERVATION_CONFLICT;
|
| 211 | KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
|
| 212 | }
|
| 213 |
|
| 214 | static void scsi_lib_test_total_allowed(struct kunit *test)
|
| 215 | {
|
| 216 | struct scsi_failure total_allowed_defs[] = {
|
| 217 | {
|
| 218 | .sense = UNIT_ATTENTION,
|
| 219 | .asc = SCMD_FAILURE_ASC_ANY,
|
| 220 | .ascq = SCMD_FAILURE_ASCQ_ANY,
|
| 221 | .result = SAM_STAT_CHECK_CONDITION,
|
| 222 | },
|
| 223 |
|
| 224 | {
|
| 225 | .sense = SCMD_FAILURE_SENSE_ANY,
|
| 226 | .result = SAM_STAT_CHECK_CONDITION,
|
| 227 | },
|
| 228 |
|
| 229 | {
|
| 230 | .result = SCMD_FAILURE_RESULT_ANY,
|
| 231 | },
|
| 232 | {}
|
| 233 | };
|
| 234 | struct scsi_failures failures = {
|
| 235 | .failure_definitions = total_allowed_defs,
|
| 236 | };
|
| 237 | u8 sense[SCSI_SENSE_BUFFERSIZE] = {};
|
| 238 | struct scsi_cmnd sc = {
|
| 239 | .sense_buffer = sense,
|
| 240 | };
|
| 241 | int i;
|
| 242 |
|
| 243 |
|
| 244 | failures.failure_definitions = total_allowed_defs;
|
| 245 | scsi_failures_reset_retries(&failures);
|
| 246 | failures.total_allowed = SCSI_LIB_TEST_TOTAL_MAX_ALLOWED;
|
| 247 |
|
| 248 | scsi_build_sense(&sc, 0, UNIT_ATTENTION, 0x28, 0x0);
|
| 249 | for (i = 0; i < SCSI_LIB_TEST_TOTAL_MAX_ALLOWED; i++)
|
| 250 |
|
| 251 | KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc,
|
| 252 | &failures));
|
| 253 | sc.result = DID_TIME_OUT << 16;
|
| 254 |
|
| 255 | KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
|
| 256 | }
|
| 257 |
|
| 258 | static void scsi_lib_test_mixed_total(struct kunit *test)
|
| 259 | {
|
| 260 | struct scsi_failure mixed_total_defs[] = {
|
| 261 | {
|
| 262 | .sense = UNIT_ATTENTION,
|
| 263 | .asc = 0x28,
|
| 264 | .result = SAM_STAT_CHECK_CONDITION,
|
| 265 | },
|
| 266 | {
|
| 267 | .sense = UNIT_ATTENTION,
|
| 268 | .asc = 0x29,
|
| 269 | .result = SAM_STAT_CHECK_CONDITION,
|
| 270 | },
|
| 271 | {
|
| 272 | .allowed = 1,
|
| 273 | .result = DID_TIME_OUT << 16,
|
| 274 | },
|
| 275 | {}
|
| 276 | };
|
| 277 | u8 sense[SCSI_SENSE_BUFFERSIZE] = {};
|
| 278 | struct scsi_failures failures = {
|
| 279 | .failure_definitions = mixed_total_defs,
|
| 280 | };
|
| 281 | struct scsi_cmnd sc = {
|
| 282 | .sense_buffer = sense,
|
| 283 | };
|
| 284 | int i;
|
| 285 |
|
| 286 | |
| 287 | * Test total_allowed when there is a mix of per failure allowed
|
| 288 | * and total_allowed limits.
|
| 289 |
|
| 290 | failures.failure_definitions = mixed_total_defs;
|
| 291 | scsi_failures_reset_retries(&failures);
|
| 292 | failures.total_allowed = SCSI_LIB_TEST_TOTAL_MAX_ALLOWED;
|
| 293 |
|
| 294 | scsi_build_sense(&sc, 0, UNIT_ATTENTION, 0x28, 0x0);
|
| 295 | for (i = 0; i < SCSI_LIB_TEST_TOTAL_MAX_ALLOWED; i++)
|
| 296 |
|
| 297 | KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc,
|
| 298 | &failures));
|
| 299 |
|
| 300 | KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
|
| 301 |
|
| 302 | scsi_failures_reset_retries(&failures);
|
| 303 | scsi_build_sense(&sc, 0, UNIT_ATTENTION, 0x28, 0x0);
|
| 304 | for (i = 0; i < SCSI_LIB_TEST_TOTAL_MAX_ALLOWED; i++)
|
| 305 |
|
| 306 | KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc,
|
| 307 | &failures));
|
| 308 | sc.result = DID_TIME_OUT << 16;
|
| 309 |
|
| 310 | KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));
|
| 311 | scsi_build_sense(&sc, 0, UNIT_ATTENTION, 0x29, 0x0);
|
| 312 |
|
| 313 | KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));
|
| 314 | }
|
| 315 |
|
| 316 | static void scsi_lib_test_check_passthough(struct kunit *test)
|
| 317 | {
|
| 318 | scsi_lib_test_multiple_sense(test);
|
| 319 | scsi_lib_test_any_sense(test);
|
| 320 | scsi_lib_test_host(test);
|
| 321 | scsi_lib_test_any_failure(test);
|
| 322 | scsi_lib_test_any_status(test);
|
| 323 | scsi_lib_test_total_allowed(test);
|
| 324 | scsi_lib_test_mixed_total(test);
|
| 325 | }
|
| 326 |
|
| 327 | static struct kunit_case scsi_lib_test_cases[] = {
|
| 328 | KUNIT_CASE(scsi_lib_test_check_passthough),
|
| 329 | {}
|
| 330 | };
|
| 331 |
|
| 332 | static struct kunit_suite scsi_lib_test_suite = {
|
| 333 | .name = "scsi_lib",
|
| 334 | .test_cases = scsi_lib_test_cases,
|
| 335 | };
|
| 336 |
|
| 337 | kunit_test_suite(scsi_lib_test_suite);
|