scsi_lib_test.c 9.1 KB

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