aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2011-11-03 17:50:40 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2011-11-04 04:00:08 -0400
commiteacac00ce5bfde8086cd0615fb53c986f7f970fe (patch)
treee58c10a9f55b3704f1eed16eb3e5cfc5038336eb /drivers/target
parenta17f091d1a7c570804cfc2c77701634da88f8ecf (diff)
target: split core_scsi2_emulate_crh
Split core_scsi2_emulate_crh into one routine each for the reserve and release side. The common code now is in a helper called by both routines. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/target_core_pr.c189
-rw-r--r--drivers/target/target_core_pr.h3
-rw-r--r--drivers/target/target_core_transport.c16
3 files changed, 102 insertions, 106 deletions
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index 0c4f783f924c..830953a743d6 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -116,14 +116,99 @@ static int core_scsi2_reservation_check(struct se_cmd *cmd, u32 *pr_reg_type)
116 return ret; 116 return ret;
117} 117}
118 118
119static int core_scsi2_reservation_release(struct se_cmd *cmd) 119static struct t10_pr_registration *core_scsi3_locate_pr_reg(struct se_device *,
120 struct se_node_acl *, struct se_session *);
121static void core_scsi3_put_pr_reg(struct t10_pr_registration *);
122
123static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd, int *ret)
124{
125 struct se_session *se_sess = cmd->se_sess;
126 struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
127 struct t10_pr_registration *pr_reg;
128 struct t10_reservation *pr_tmpl = &su_dev->t10_pr;
129 int crh = (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS);
130 int conflict = 0;
131
132 if (!crh)
133 return false;
134
135 pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl,
136 se_sess);
137 if (pr_reg) {
138 /*
139 * From spc4r17 5.7.3 Exceptions to SPC-2 RESERVE and RELEASE
140 * behavior
141 *
142 * A RESERVE(6) or RESERVE(10) command shall complete with GOOD
143 * status, but no reservation shall be established and the
144 * persistent reservation shall not be changed, if the command
145 * is received from a) and b) below.
146 *
147 * A RELEASE(6) or RELEASE(10) command shall complete with GOOD
148 * status, but the persistent reservation shall not be released,
149 * if the command is received from a) and b)
150 *
151 * a) An I_T nexus that is a persistent reservation holder; or
152 * b) An I_T nexus that is registered if a registrants only or
153 * all registrants type persistent reservation is present.
154 *
155 * In all other cases, a RESERVE(6) command, RESERVE(10) command,
156 * RELEASE(6) command, or RELEASE(10) command shall be processed
157 * as defined in SPC-2.
158 */
159 if (pr_reg->pr_res_holder) {
160 core_scsi3_put_pr_reg(pr_reg);
161 *ret = 0;
162 return false;
163 }
164 if ((pr_reg->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY) ||
165 (pr_reg->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY) ||
166 (pr_reg->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) ||
167 (pr_reg->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)) {
168 core_scsi3_put_pr_reg(pr_reg);
169 *ret = 0;
170 return true;
171 }
172 core_scsi3_put_pr_reg(pr_reg);
173 conflict = 1;
174 } else {
175 /*
176 * Following spc2r20 5.5.1 Reservations overview:
177 *
178 * If a logical unit has executed a PERSISTENT RESERVE OUT
179 * command with the REGISTER or the REGISTER AND IGNORE
180 * EXISTING KEY service action and is still registered by any
181 * initiator, all RESERVE commands and all RELEASE commands
182 * regardless of initiator shall conflict and shall terminate
183 * with a RESERVATION CONFLICT status.
184 */
185 spin_lock(&pr_tmpl->registration_lock);
186 conflict = (list_empty(&pr_tmpl->registration_list)) ? 0 : 1;
187 spin_unlock(&pr_tmpl->registration_lock);
188 }
189
190 if (conflict) {
191 pr_err("Received legacy SPC-2 RESERVE/RELEASE"
192 " while active SPC-3 registrations exist,"
193 " returning RESERVATION_CONFLICT\n");
194 *ret = PYX_TRANSPORT_RESERVATION_CONFLICT;
195 return true;
196 }
197
198 return false;
199}
200
201int target_scsi2_reservation_release(struct se_cmd *cmd)
120{ 202{
121 struct se_device *dev = cmd->se_dev; 203 struct se_device *dev = cmd->se_dev;
122 struct se_session *sess = cmd->se_sess; 204 struct se_session *sess = cmd->se_sess;
123 struct se_portal_group *tpg = sess->se_tpg; 205 struct se_portal_group *tpg = sess->se_tpg;
206 int ret;
124 207
125 if (!sess || !tpg) 208 if (!sess || !tpg)
126 return 0; 209 return 0;
210 if (target_check_scsi2_reservation_conflict(cmd, &ret))
211 return ret;
127 212
128 spin_lock(&dev->dev_reservation_lock); 213 spin_lock(&dev->dev_reservation_lock);
129 if (!dev->dev_reserved_node_acl || !sess) { 214 if (!dev->dev_reserved_node_acl || !sess) {
@@ -150,11 +235,12 @@ static int core_scsi2_reservation_release(struct se_cmd *cmd)
150 return 0; 235 return 0;
151} 236}
152 237
153static int core_scsi2_reservation_reserve(struct se_cmd *cmd) 238int target_scsi2_reservation_reserve(struct se_cmd *cmd)
154{ 239{
155 struct se_device *dev = cmd->se_dev; 240 struct se_device *dev = cmd->se_dev;
156 struct se_session *sess = cmd->se_sess; 241 struct se_session *sess = cmd->se_sess;
157 struct se_portal_group *tpg = sess->se_tpg; 242 struct se_portal_group *tpg = sess->se_tpg;
243 int ret;
158 244
159 if ((cmd->t_task_cdb[1] & 0x01) && 245 if ((cmd->t_task_cdb[1] & 0x01) &&
160 (cmd->t_task_cdb[1] & 0x02)) { 246 (cmd->t_task_cdb[1] & 0x02)) {
@@ -168,6 +254,8 @@ static int core_scsi2_reservation_reserve(struct se_cmd *cmd)
168 */ 254 */
169 if (!sess || !tpg) 255 if (!sess || !tpg)
170 return 0; 256 return 0;
257 if (target_check_scsi2_reservation_conflict(cmd, &ret))
258 return ret;
171 259
172 spin_lock(&dev->dev_reservation_lock); 260 spin_lock(&dev->dev_reservation_lock);
173 if (dev->dev_reserved_node_acl && 261 if (dev->dev_reserved_node_acl &&
@@ -200,99 +288,6 @@ static int core_scsi2_reservation_reserve(struct se_cmd *cmd)
200 return 0; 288 return 0;
201} 289}
202 290
203static struct t10_pr_registration *core_scsi3_locate_pr_reg(struct se_device *,
204 struct se_node_acl *, struct se_session *);
205static void core_scsi3_put_pr_reg(struct t10_pr_registration *);
206
207/*
208 * Setup in target_core_transport.c:transport_generic_cmd_sequencer()
209 * and called via struct se_cmd->transport_emulate_cdb() in TCM processing
210 * thread context.
211 */
212int core_scsi2_emulate_crh(struct se_cmd *cmd)
213{
214 struct se_session *se_sess = cmd->se_sess;
215 struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
216 struct t10_pr_registration *pr_reg;
217 struct t10_reservation *pr_tmpl = &su_dev->t10_pr;
218 unsigned char *cdb = &cmd->t_task_cdb[0];
219 int crh = (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS);
220 int conflict = 0;
221
222 if (!se_sess)
223 return 0;
224
225 if (!crh)
226 goto after_crh;
227
228 pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl,
229 se_sess);
230 if (pr_reg) {
231 /*
232 * From spc4r17 5.7.3 Exceptions to SPC-2 RESERVE and RELEASE
233 * behavior
234 *
235 * A RESERVE(6) or RESERVE(10) command shall complete with GOOD
236 * status, but no reservation shall be established and the
237 * persistent reservation shall not be changed, if the command
238 * is received from a) and b) below.
239 *
240 * A RELEASE(6) or RELEASE(10) command shall complete with GOOD
241 * status, but the persistent reservation shall not be released,
242 * if the command is received from a) and b)
243 *
244 * a) An I_T nexus that is a persistent reservation holder; or
245 * b) An I_T nexus that is registered if a registrants only or
246 * all registrants type persistent reservation is present.
247 *
248 * In all other cases, a RESERVE(6) command, RESERVE(10) command,
249 * RELEASE(6) command, or RELEASE(10) command shall be processed
250 * as defined in SPC-2.
251 */
252 if (pr_reg->pr_res_holder) {
253 core_scsi3_put_pr_reg(pr_reg);
254 return 0;
255 }
256 if ((pr_reg->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY) ||
257 (pr_reg->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY) ||
258 (pr_reg->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) ||
259 (pr_reg->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)) {
260 core_scsi3_put_pr_reg(pr_reg);
261 return 0;
262 }
263 core_scsi3_put_pr_reg(pr_reg);
264 conflict = 1;
265 } else {
266 /*
267 * Following spc2r20 5.5.1 Reservations overview:
268 *
269 * If a logical unit has executed a PERSISTENT RESERVE OUT
270 * command with the REGISTER or the REGISTER AND IGNORE
271 * EXISTING KEY service action and is still registered by any
272 * initiator, all RESERVE commands and all RELEASE commands
273 * regardless of initiator shall conflict and shall terminate
274 * with a RESERVATION CONFLICT status.
275 */
276 spin_lock(&pr_tmpl->registration_lock);
277 conflict = (list_empty(&pr_tmpl->registration_list)) ? 0 : 1;
278 spin_unlock(&pr_tmpl->registration_lock);
279 }
280
281 if (conflict) {
282 pr_err("Received legacy SPC-2 RESERVE/RELEASE"
283 " while active SPC-3 registrations exist,"
284 " returning RESERVATION_CONFLICT\n");
285 return PYX_TRANSPORT_RESERVATION_CONFLICT;
286 }
287
288after_crh:
289 if ((cdb[0] == RESERVE) || (cdb[0] == RESERVE_10))
290 return core_scsi2_reservation_reserve(cmd);
291 else if ((cdb[0] == RELEASE) || (cdb[0] == RELEASE_10))
292 return core_scsi2_reservation_release(cmd);
293 else
294 return PYX_TRANSPORT_INVALID_CDB_FIELD;
295}
296 291
297/* 292/*
298 * Begin SPC-3/SPC-4 Persistent Reservations emulation support 293 * Begin SPC-3/SPC-4 Persistent Reservations emulation support
@@ -418,12 +413,12 @@ static int core_scsi3_pr_seq_non_holder(
418 break; 413 break;
419 case RELEASE: 414 case RELEASE:
420 case RELEASE_10: 415 case RELEASE_10:
421 /* Handled by CRH=1 in core_scsi2_emulate_crh() */ 416 /* Handled by CRH=1 in target_scsi2_reservation_release() */
422 ret = 0; 417 ret = 0;
423 break; 418 break;
424 case RESERVE: 419 case RESERVE:
425 case RESERVE_10: 420 case RESERVE_10:
426 /* Handled by CRH=1 in core_scsi2_emulate_crh() */ 421 /* Handled by CRH=1 in target_scsi2_reservation_reserve() */
427 ret = 0; 422 ret = 0;
428 break; 423 break;
429 case TEST_UNIT_READY: 424 case TEST_UNIT_READY:
diff --git a/drivers/target/target_core_pr.h b/drivers/target/target_core_pr.h
index c8f47d064584..4e94a427e314 100644
--- a/drivers/target/target_core_pr.h
+++ b/drivers/target/target_core_pr.h
@@ -47,7 +47,8 @@ extern struct kmem_cache *t10_pr_reg_cache;
47 47
48extern int core_pr_dump_initiator_port(struct t10_pr_registration *, 48extern int core_pr_dump_initiator_port(struct t10_pr_registration *,
49 char *, u32); 49 char *, u32);
50extern int core_scsi2_emulate_crh(struct se_cmd *); 50extern int target_scsi2_reservation_release(struct se_cmd *cmd);
51extern int target_scsi2_reservation_reserve(struct se_cmd *cmd);
51extern int core_scsi3_alloc_aptpl_registration( 52extern int core_scsi3_alloc_aptpl_registration(
52 struct t10_reservation *, u64, 53 struct t10_reservation *, u64,
53 unsigned char *, unsigned char *, u32, 54 unsigned char *, unsigned char *, u32,
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index e84b26ffb17b..f4232934bac5 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -2963,10 +2963,10 @@ static int transport_generic_cmd_sequencer(
2963 * is running in SPC_PASSTHROUGH, and wants reservations 2963 * is running in SPC_PASSTHROUGH, and wants reservations
2964 * emulation disabled. 2964 * emulation disabled.
2965 */ 2965 */
2966 cmd->transport_emulate_cdb = 2966 if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH) {
2967 (su_dev->t10_pr.res_type != 2967 cmd->transport_emulate_cdb =
2968 SPC_PASSTHROUGH) ? 2968 target_scsi2_reservation_reserve;
2969 core_scsi2_emulate_crh : NULL; 2969 }
2970 cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; 2970 cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
2971 break; 2971 break;
2972 case RELEASE: 2972 case RELEASE:
@@ -2980,10 +2980,10 @@ static int transport_generic_cmd_sequencer(
2980 else 2980 else
2981 size = cmd->data_length; 2981 size = cmd->data_length;
2982 2982
2983 cmd->transport_emulate_cdb = 2983 if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH) {
2984 (su_dev->t10_pr.res_type != 2984 cmd->transport_emulate_cdb =
2985 SPC_PASSTHROUGH) ? 2985 target_scsi2_reservation_release;
2986 core_scsi2_emulate_crh : NULL; 2986 }
2987 cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; 2987 cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
2988 break; 2988 break;
2989 case SYNCHRONIZE_CACHE: 2989 case SYNCHRONIZE_CACHE: