1 /*
2 Copyright (C) 2013 Ronnie Sahlberg <ronniesahlberg@gmail.com>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <stdio.h>
19
20 #include <CUnit/CUnit.h>
21
22 #include "iscsi.h"
23 #include "scsi-lowlevel.h"
24 #include "iscsi-support.h"
25 #include "iscsi-test-cu.h"
26
27
28 void
test_writesame16_unmap(void)29 test_writesame16_unmap(void)
30 {
31 unsigned int i;
32
33 CHECK_FOR_DATALOSS;
34 CHECK_FOR_THIN_PROVISIONING;
35 CHECK_FOR_LBPWS;
36 CHECK_FOR_SBC;
37
38 logging(LOG_VERBOSE, LOG_BLANK_LINE);
39 logging(LOG_VERBOSE, "Test WRITESAME16 of 1-256 blocks at the start of the LUN");
40 for (i = 1; i <= 256; i++) {
41 logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i);
42 memset(scratch, 0xff, i * block_size);
43 WRITE16(sd, 0, i * block_size, block_size,
44 0, 0, 0, 0, 0, scratch,
45 EXPECT_STATUS_GOOD);
46
47 logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME16", i);
48 memset(scratch, 0, block_size);
49 WRITESAME16(sd, 0, block_size, i, 0, 1, 0, 0, scratch,
50 EXPECT_STATUS_GOOD);
51
52 if (rc16->lbprz) {
53 logging(LOG_VERBOSE, "LBPRZ is set. Read the unmapped "
54 "blocks back and verify they are all zero");
55 logging(LOG_VERBOSE, "Read %d blocks and verify they "
56 "are now zero", i);
57 READ16(sd, NULL, 0, i * block_size, block_size,
58 0, 0, 0, 0, 0, scratch,
59 EXPECT_STATUS_GOOD);
60 ALL_ZERO(scratch, i * block_size);
61 } else {
62 logging(LOG_VERBOSE, "LBPRZ is clear. Skip the read "
63 "and verify zero test");
64 }
65 }
66
67
68 logging(LOG_VERBOSE, "Test WRITESAME16 of 1-256 blocks at the end of the LUN");
69 for (i = 1; i <= 256; i++) {
70 logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i);
71 memset(scratch, 0xff, i * block_size);
72 WRITE16(sd, num_blocks - i,
73 i * block_size, block_size, 0, 0, 0, 0, 0, scratch,
74 EXPECT_STATUS_GOOD);
75
76 logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME16", i);
77 memset(scratch, 0, block_size);
78 WRITESAME16(sd, num_blocks - i,
79 block_size, i, 0, 1, 0, 0, scratch,
80 EXPECT_STATUS_GOOD);
81
82 if (rc16->lbprz) {
83 logging(LOG_VERBOSE, "LBPRZ is set. Read the unmapped "
84 "blocks back and verify they are all zero");
85 logging(LOG_VERBOSE, "Read %d blocks and verify they "
86 "are now zero", i);
87 READ16(sd, NULL, num_blocks - i,
88 i * block_size, block_size,
89 0, 0, 0, 0, 0, scratch,
90 EXPECT_STATUS_GOOD);
91 ALL_ZERO(scratch, i * block_size);
92 } else {
93 logging(LOG_VERBOSE, "LBPRZ is clear. Skip the read "
94 "and verify zero test");
95 }
96 }
97
98 logging(LOG_VERBOSE, "Verify that WRITESAME16 ANCHOR==1 + UNMAP==0 is invalid");
99 WRITESAME16(sd, 0, block_size, 1, 1, 0, 0, 0, scratch,
100 EXPECT_INVALID_FIELD_IN_CDB);
101
102 if (inq_lbp->anc_sup) {
103 logging(LOG_VERBOSE, "Test WRITESAME16 ANCHOR==1 + UNMAP==0");
104 memset(scratch, 0, block_size);
105 WRITESAME16(sd, 0, block_size, 1, 1, 1, 0, 0, scratch,
106 EXPECT_STATUS_GOOD);
107 } else {
108 logging(LOG_VERBOSE, "Test WRITESAME16 ANCHOR==1 + UNMAP==0 no ANC_SUP so expecting to fail");
109 WRITESAME16(sd, 0, block_size, 1, 1, 1, 0, 0, scratch,
110 EXPECT_INVALID_FIELD_IN_CDB);
111 }
112
113 if (inq_bl == NULL) {
114 logging(LOG_VERBOSE, "[FAILED] WRITESAME16 works but "
115 "BlockLimits VPD is missing.");
116 CU_FAIL("[FAILED] WRITESAME16 works but "
117 "BlockLimits VPD is missing.");
118 return;
119 }
120
121 i = 256;
122 if (i <= num_blocks
123 && (inq_bl->max_ws_len == 0 || inq_bl->max_ws_len >= i)) {
124 logging(LOG_VERBOSE, "Block Limits VPD page reports MAX_WS_LEN "
125 "as either 0 (==no limit) or >= %d. Test Unmapping "
126 "%d blocks to verify that it can handle 2-byte "
127 "lengths", i, i);
128
129 logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i);
130 memset(scratch, 0xff, i * block_size);
131 WRITE16(sd, 0,
132 i * block_size, block_size, 0, 0, 0, 0, 0, scratch,
133 EXPECT_STATUS_GOOD);
134
135 logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME16", i);
136 memset(scratch, 0, block_size);
137 WRITESAME16(sd, 0, block_size, i, 0, 1, 0, 0, scratch,
138 EXPECT_STATUS_GOOD);
139
140 if (rc16->lbprz) {
141 logging(LOG_VERBOSE, "LBPRZ is set. Read the unmapped "
142 "blocks back and verify they are all zero");
143
144 logging(LOG_VERBOSE, "Read %d blocks and verify they "
145 "are now zero", i);
146 READ16(sd, NULL, 0, i * block_size, block_size,
147 0, 0, 0, 0, 0, scratch,
148 EXPECT_STATUS_GOOD);
149 ALL_ZERO(scratch, i * block_size);
150 } else {
151 logging(LOG_VERBOSE, "LBPRZ is clear. Skip the read "
152 "and verify zero test");
153 }
154 } else if (i <= num_blocks) {
155 logging(LOG_VERBOSE, "Block Limits VPD page reports MAX_WS_LEN "
156 "as <256. Verify that a 256 block unmap fails with "
157 "INVALID_FIELD_IN_CDB.");
158
159 logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME16", i);
160 WRITESAME16(sd, 0, block_size, i, 0, 1, 0, 0, scratch,
161 EXPECT_INVALID_FIELD_IN_CDB);
162 }
163
164
165 i = 65536;
166 if (i <= num_blocks
167 && (inq_bl->max_ws_len == 0 || inq_bl->max_ws_len >= i)) {
168 logging(LOG_VERBOSE, "Block Limits VPD page reports MAX_WS_LEN "
169 "as either 0 (==no limit) or >= %d. Test Unmapping "
170 "%d blocks to verify that it can handle 4-byte "
171 "lengths", i, i);
172
173 logging(LOG_VERBOSE, "Write %d blocks of 0xFF", i);
174 memset(scratch, 0xff, i * block_size);
175 WRITE16(sd, 0,
176 i * block_size, block_size, 0, 0, 0, 0, 0, scratch,
177 EXPECT_STATUS_GOOD);
178
179 logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME16", i);
180 memset(scratch, 0, block_size);
181 WRITESAME16(sd, 0, block_size, i, 0, 1, 0, 0, scratch,
182 EXPECT_STATUS_GOOD);
183
184 if (rc16->lbprz) {
185 logging(LOG_VERBOSE, "LBPRZ is set. Read the unmapped "
186 "blocks back and verify they are all zero");
187
188 logging(LOG_VERBOSE, "Read %d blocks and verify they "
189 "are now zero", i);
190 READ16(sd, NULL, 0, i * block_size, block_size,
191 0, 0, 0, 0, 0, scratch,
192 EXPECT_STATUS_GOOD);
193 ALL_ZERO(scratch, i * block_size);
194 } else {
195 logging(LOG_VERBOSE, "LBPRZ is clear. Skip the read "
196 "and verify zero test");
197 }
198 } else if (i <= num_blocks) {
199 logging(LOG_VERBOSE, "Block Limits VPD page reports MAX_WS_LEN "
200 "as <256. Verify that a 256 block unmap fails with "
201 "INVALID_FIELD_IN_CDB.");
202
203 logging(LOG_VERBOSE, "Unmap %d blocks using WRITESAME16", i);
204 WRITESAME16(sd, 0, block_size, i, 0, 1, 0, 0, scratch,
205 EXPECT_INVALID_FIELD_IN_CDB);
206 }
207 }
208