brintos

brintos / linux-shallow public Read only

0
0
Text · 9.1 KiB · 9983442 Raw
331 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * KUnit tests for scsi_lib.c.4 *5 * Copyright (C) 2023, Oracle Corporation6 */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 314#define SCSI_LIB_TEST_TOTAL_MAX_ALLOWED 515 16static 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	/* Match end of array */71	scsi_build_sense(&sc, 0, ILLEGAL_REQUEST, 0x91, 0x36);72	KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));73	/* Basic match in array */74	scsi_build_sense(&sc, 0, UNIT_ATTENTION, 0x11, 0x0);75	KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));76	/* No matching sense entry */77	scsi_build_sense(&sc, 0, MISCOMPARE, 0x11, 0x11);78	KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));79	/* Match using SCMD_FAILURE_ASCQ_ANY */80	scsi_build_sense(&sc, 0, ABORTED_COMMAND, 0x11, 0x22);81	KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));82	/* Fail to match */83	scsi_build_sense(&sc, 0, ABORTED_COMMAND, 0x22, 0x22);84	KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));85	/* Match using SCMD_FAILURE_ASC_ANY */86	scsi_build_sense(&sc, 0, HARDWARE_ERROR, 0x11, 0x22);87	KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));88	/* No matching status entry */89	sc.result = SAM_STAT_RESERVATION_CONFLICT;90	KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));91 92	/* Test hitting allowed limit */93	scsi_build_sense(&sc, 0, NOT_READY, 0x11, 0x22);94	for (i = 0; i < SCSI_LIB_TEST_MAX_ALLOWED; i++)95		KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc,96				&failures));97	KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));98 99	/* reset retries so we can retest */100	failures.failure_definitions = multiple_sense_failure_defs;101	scsi_failures_reset_retries(&failures);102 103	/* Test no retries allowed */104	scsi_build_sense(&sc, 0, DATA_PROTECT, 0x1, 0x1);105	KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));106}107 108static void scsi_lib_test_any_sense(struct kunit *test)109{110	struct scsi_failure any_sense_failure_defs[] = {111		{112			.result = SCMD_FAILURE_SENSE_ANY,113			.allowed = SCSI_LIB_TEST_MAX_ALLOWED,114		},115		{}116	};117	struct scsi_failures failures = {118		.failure_definitions = any_sense_failure_defs,119	};120	u8 sense[SCSI_SENSE_BUFFERSIZE] = {};121	struct scsi_cmnd sc = {122		.sense_buffer = sense,123	};124 125	/* Match using SCMD_FAILURE_SENSE_ANY */126	failures.failure_definitions = any_sense_failure_defs;127	scsi_build_sense(&sc, 0, MEDIUM_ERROR, 0x11, 0x22);128	KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));129}130 131static void scsi_lib_test_host(struct kunit *test)132{133	struct scsi_failure retryable_host_failure_defs[] = {134		{135			.result = DID_TRANSPORT_DISRUPTED << 16,136			.allowed = SCSI_LIB_TEST_MAX_ALLOWED,137		},138		{139			.result = DID_TIME_OUT << 16,140			.allowed = SCSI_LIB_TEST_MAX_ALLOWED,141		},142		{}143	};144	struct scsi_failures failures = {145		.failure_definitions = retryable_host_failure_defs,146	};147	u8 sense[SCSI_SENSE_BUFFERSIZE] = {};148	struct scsi_cmnd sc = {149		.sense_buffer = sense,150	};151 152	/* No matching host byte entry */153	failures.failure_definitions = retryable_host_failure_defs;154	sc.result = DID_NO_CONNECT << 16;155	KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));156	/* Matching host byte entry */157	sc.result = DID_TIME_OUT << 16;158	KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));159}160 161static void scsi_lib_test_any_failure(struct kunit *test)162{163	struct scsi_failure any_failure_defs[] = {164		{165			.result = SCMD_FAILURE_RESULT_ANY,166			.allowed = SCSI_LIB_TEST_MAX_ALLOWED,167		},168		{}169	};170	struct scsi_failures failures = {171		.failure_definitions = any_failure_defs,172	};173	u8 sense[SCSI_SENSE_BUFFERSIZE] = {};174	struct scsi_cmnd sc = {175		.sense_buffer = sense,176	};177 178	/* Match SCMD_FAILURE_RESULT_ANY */179	failures.failure_definitions = any_failure_defs;180	sc.result = DID_TRANSPORT_FAILFAST << 16;181	KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));182}183 184static void scsi_lib_test_any_status(struct kunit *test)185{186	struct scsi_failure any_status_failure_defs[] = {187		{188			.result = SCMD_FAILURE_STAT_ANY,189			.allowed = SCSI_LIB_TEST_MAX_ALLOWED,190		},191		{}192	};193	struct scsi_failures failures = {194		.failure_definitions = any_status_failure_defs,195	};196	u8 sense[SCSI_SENSE_BUFFERSIZE] = {};197	struct scsi_cmnd sc = {198		.sense_buffer = sense,199	};200 201	/* Test any status handling */202	failures.failure_definitions = any_status_failure_defs;203	sc.result = SAM_STAT_RESERVATION_CONFLICT;204	KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));205}206 207static void scsi_lib_test_total_allowed(struct kunit *test)208{209	struct scsi_failure total_allowed_defs[] = {210		{211			.sense = UNIT_ATTENTION,212			.asc = SCMD_FAILURE_ASC_ANY,213			.ascq = SCMD_FAILURE_ASCQ_ANY,214			.result = SAM_STAT_CHECK_CONDITION,215		},216		/* Fail all CCs except the UA above */217		{218			.sense = SCMD_FAILURE_SENSE_ANY,219			.result = SAM_STAT_CHECK_CONDITION,220		},221		/* Retry any other errors not listed above */222		{223			.result = SCMD_FAILURE_RESULT_ANY,224		},225		{}226	};227	struct scsi_failures failures = {228		.failure_definitions = total_allowed_defs,229	};230	u8 sense[SCSI_SENSE_BUFFERSIZE] = {};231	struct scsi_cmnd sc = {232		.sense_buffer = sense,233	};234	int i;235 236	/* Test total_allowed */237	failures.failure_definitions = total_allowed_defs;238	scsi_failures_reset_retries(&failures);239	failures.total_allowed = SCSI_LIB_TEST_TOTAL_MAX_ALLOWED;240 241	scsi_build_sense(&sc, 0, UNIT_ATTENTION, 0x28, 0x0);242	for (i = 0; i < SCSI_LIB_TEST_TOTAL_MAX_ALLOWED; i++)243		/* Retry since we under the total_allowed limit */244		KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc,245				&failures));246	sc.result = DID_TIME_OUT << 16;247	/* We have now hit the total_allowed limit so no more retries */248	KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));249}250 251static void scsi_lib_test_mixed_total(struct kunit *test)252{253	struct scsi_failure mixed_total_defs[] = {254		{255			.sense = UNIT_ATTENTION,256			.asc = 0x28,257			.result = SAM_STAT_CHECK_CONDITION,258		},259		{260			.sense = UNIT_ATTENTION,261			.asc = 0x29,262			.result = SAM_STAT_CHECK_CONDITION,263		},264		{265			.allowed = 1,266			.result = DID_TIME_OUT << 16,267		},268		{}269	};270	u8 sense[SCSI_SENSE_BUFFERSIZE] = {};271	struct scsi_failures failures = {272		.failure_definitions = mixed_total_defs,273	};274	struct scsi_cmnd sc = {275		.sense_buffer = sense,276	};277	int i;278 279	/*280	 * Test total_allowed when there is a mix of per failure allowed281	 * and total_allowed limits.282	 */283	failures.failure_definitions = mixed_total_defs;284	scsi_failures_reset_retries(&failures);285	failures.total_allowed = SCSI_LIB_TEST_TOTAL_MAX_ALLOWED;286 287	scsi_build_sense(&sc, 0, UNIT_ATTENTION, 0x28, 0x0);288	for (i = 0; i < SCSI_LIB_TEST_TOTAL_MAX_ALLOWED; i++)289		/* Retry since we under the total_allowed limit */290		KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc,291				&failures));292	/* Do not retry since we are now over total_allowed limit */293	KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));294 295	scsi_failures_reset_retries(&failures);296	scsi_build_sense(&sc, 0, UNIT_ATTENTION, 0x28, 0x0);297	for (i = 0; i < SCSI_LIB_TEST_TOTAL_MAX_ALLOWED; i++)298		/* Retry since we under the total_allowed limit */299		KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc,300				&failures));301	sc.result = DID_TIME_OUT << 16;302	/* Retry because this failure has a per failure limit */303	KUNIT_EXPECT_EQ(test, -EAGAIN, scsi_check_passthrough(&sc, &failures));304	scsi_build_sense(&sc, 0, UNIT_ATTENTION, 0x29, 0x0);305	/* total_allowed is now hit so no more retries */306	KUNIT_EXPECT_EQ(test, 0, scsi_check_passthrough(&sc, &failures));307}308 309static void scsi_lib_test_check_passthough(struct kunit *test)310{311	scsi_lib_test_multiple_sense(test);312	scsi_lib_test_any_sense(test);313	scsi_lib_test_host(test);314	scsi_lib_test_any_failure(test);315	scsi_lib_test_any_status(test);316	scsi_lib_test_total_allowed(test);317	scsi_lib_test_mixed_total(test);318}319 320static struct kunit_case scsi_lib_test_cases[] = {321	KUNIT_CASE(scsi_lib_test_check_passthough),322	{}323};324 325static struct kunit_suite scsi_lib_test_suite = {326	.name = "scsi_lib",327	.test_cases = scsi_lib_test_cases,328};329 330kunit_test_suite(scsi_lib_test_suite);331