aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/target/target_core_pr.c87
1 files changed, 65 insertions, 22 deletions
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index c4a8da5415c5..703890c12071 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -76,7 +76,7 @@ enum preempt_type {
76}; 76};
77 77
78static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *, 78static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *,
79 struct t10_pr_registration *, int); 79 struct t10_pr_registration *, int, int);
80 80
81static sense_reason_t 81static sense_reason_t
82target_scsi2_reservation_check(struct se_cmd *cmd) 82target_scsi2_reservation_check(struct se_cmd *cmd)
@@ -1177,7 +1177,7 @@ static int core_scsi3_check_implicit_release(
1177 * service action with the SERVICE ACTION RESERVATION KEY 1177 * service action with the SERVICE ACTION RESERVATION KEY
1178 * field set to zero (see 5.7.11.3). 1178 * field set to zero (see 5.7.11.3).
1179 */ 1179 */
1180 __core_scsi3_complete_pro_release(dev, nacl, pr_reg, 0); 1180 __core_scsi3_complete_pro_release(dev, nacl, pr_reg, 0, 1);
1181 ret = 1; 1181 ret = 1;
1182 /* 1182 /*
1183 * For 'All Registrants' reservation types, all existing 1183 * For 'All Registrants' reservation types, all existing
@@ -1219,7 +1219,8 @@ static void __core_scsi3_free_registration(
1219 1219
1220 pr_reg->pr_reg_deve->def_pr_registered = 0; 1220 pr_reg->pr_reg_deve->def_pr_registered = 0;
1221 pr_reg->pr_reg_deve->pr_res_key = 0; 1221 pr_reg->pr_reg_deve->pr_res_key = 0;
1222 list_del(&pr_reg->pr_reg_list); 1222 if (!list_empty(&pr_reg->pr_reg_list))
1223 list_del(&pr_reg->pr_reg_list);
1223 /* 1224 /*
1224 * Caller accessing *pr_reg using core_scsi3_locate_pr_reg(), 1225 * Caller accessing *pr_reg using core_scsi3_locate_pr_reg(),
1225 * so call core_scsi3_put_pr_reg() to decrement our reference. 1226 * so call core_scsi3_put_pr_reg() to decrement our reference.
@@ -1271,6 +1272,7 @@ void core_scsi3_free_pr_reg_from_nacl(
1271{ 1272{
1272 struct t10_reservation *pr_tmpl = &dev->t10_pr; 1273 struct t10_reservation *pr_tmpl = &dev->t10_pr;
1273 struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder; 1274 struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_res_holder;
1275 bool free_reg = false;
1274 /* 1276 /*
1275 * If the passed se_node_acl matches the reservation holder, 1277 * If the passed se_node_acl matches the reservation holder,
1276 * release the reservation. 1278 * release the reservation.
@@ -1278,13 +1280,18 @@ void core_scsi3_free_pr_reg_from_nacl(
1278 spin_lock(&dev->dev_reservation_lock); 1280 spin_lock(&dev->dev_reservation_lock);
1279 pr_res_holder = dev->dev_pr_res_holder; 1281 pr_res_holder = dev->dev_pr_res_holder;
1280 if ((pr_res_holder != NULL) && 1282 if ((pr_res_holder != NULL) &&
1281 (pr_res_holder->pr_reg_nacl == nacl)) 1283 (pr_res_holder->pr_reg_nacl == nacl)) {
1282 __core_scsi3_complete_pro_release(dev, nacl, pr_res_holder, 0); 1284 __core_scsi3_complete_pro_release(dev, nacl, pr_res_holder, 0, 1);
1285 free_reg = true;
1286 }
1283 spin_unlock(&dev->dev_reservation_lock); 1287 spin_unlock(&dev->dev_reservation_lock);
1284 /* 1288 /*
1285 * Release any registration associated with the struct se_node_acl. 1289 * Release any registration associated with the struct se_node_acl.
1286 */ 1290 */
1287 spin_lock(&pr_tmpl->registration_lock); 1291 spin_lock(&pr_tmpl->registration_lock);
1292 if (pr_res_holder && free_reg)
1293 __core_scsi3_free_registration(dev, pr_res_holder, NULL, 0);
1294
1288 list_for_each_entry_safe(pr_reg, pr_reg_tmp, 1295 list_for_each_entry_safe(pr_reg, pr_reg_tmp,
1289 &pr_tmpl->registration_list, pr_reg_list) { 1296 &pr_tmpl->registration_list, pr_reg_list) {
1290 1297
@@ -1307,7 +1314,7 @@ void core_scsi3_free_all_registrations(
1307 if (pr_res_holder != NULL) { 1314 if (pr_res_holder != NULL) {
1308 struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl; 1315 struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl;
1309 __core_scsi3_complete_pro_release(dev, pr_res_nacl, 1316 __core_scsi3_complete_pro_release(dev, pr_res_nacl,
1310 pr_res_holder, 0); 1317 pr_res_holder, 0, 0);
1311 } 1318 }
1312 spin_unlock(&dev->dev_reservation_lock); 1319 spin_unlock(&dev->dev_reservation_lock);
1313 1320
@@ -2103,13 +2110,13 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
2103 /* 2110 /*
2104 * sa_res_key=0 Unregister Reservation Key for registered I_T Nexus. 2111 * sa_res_key=0 Unregister Reservation Key for registered I_T Nexus.
2105 */ 2112 */
2106 pr_holder = core_scsi3_check_implicit_release( 2113 type = pr_reg->pr_res_type;
2107 cmd->se_dev, pr_reg); 2114 pr_holder = core_scsi3_check_implicit_release(cmd->se_dev,
2115 pr_reg);
2108 if (pr_holder < 0) { 2116 if (pr_holder < 0) {
2109 ret = TCM_RESERVATION_CONFLICT; 2117 ret = TCM_RESERVATION_CONFLICT;
2110 goto out; 2118 goto out;
2111 } 2119 }
2112 type = pr_reg->pr_res_type;
2113 2120
2114 spin_lock(&pr_tmpl->registration_lock); 2121 spin_lock(&pr_tmpl->registration_lock);
2115 /* 2122 /*
@@ -2383,23 +2390,59 @@ static void __core_scsi3_complete_pro_release(
2383 struct se_device *dev, 2390 struct se_device *dev,
2384 struct se_node_acl *se_nacl, 2391 struct se_node_acl *se_nacl,
2385 struct t10_pr_registration *pr_reg, 2392 struct t10_pr_registration *pr_reg,
2386 int explicit) 2393 int explicit,
2394 int unreg)
2387{ 2395{
2388 struct target_core_fabric_ops *tfo = se_nacl->se_tpg->se_tpg_tfo; 2396 struct target_core_fabric_ops *tfo = se_nacl->se_tpg->se_tpg_tfo;
2389 char i_buf[PR_REG_ISID_ID_LEN]; 2397 char i_buf[PR_REG_ISID_ID_LEN];
2398 int pr_res_type = 0, pr_res_scope = 0;
2390 2399
2391 memset(i_buf, 0, PR_REG_ISID_ID_LEN); 2400 memset(i_buf, 0, PR_REG_ISID_ID_LEN);
2392 core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN); 2401 core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
2393 /* 2402 /*
2394 * Go ahead and release the current PR reservation holder. 2403 * Go ahead and release the current PR reservation holder.
2404 * If an All Registrants reservation is currently active and
2405 * a unregister operation is requested, replace the current
2406 * dev_pr_res_holder with another active registration.
2395 */ 2407 */
2396 dev->dev_pr_res_holder = NULL; 2408 if (dev->dev_pr_res_holder) {
2409 pr_res_type = dev->dev_pr_res_holder->pr_res_type;
2410 pr_res_scope = dev->dev_pr_res_holder->pr_res_scope;
2411 dev->dev_pr_res_holder->pr_res_type = 0;
2412 dev->dev_pr_res_holder->pr_res_scope = 0;
2413 dev->dev_pr_res_holder->pr_res_holder = 0;
2414 dev->dev_pr_res_holder = NULL;
2415 }
2416 if (!unreg)
2417 goto out;
2397 2418
2398 pr_debug("SPC-3 PR [%s] Service Action: %s RELEASE cleared" 2419 spin_lock(&dev->t10_pr.registration_lock);
2399 " reservation holder TYPE: %s ALL_TG_PT: %d\n", 2420 list_del_init(&pr_reg->pr_reg_list);
2400 tfo->get_fabric_name(), (explicit) ? "explicit" : "implicit", 2421 /*
2401 core_scsi3_pr_dump_type(pr_reg->pr_res_type), 2422 * If the I_T nexus is a reservation holder, the persistent reservation
2402 (pr_reg->pr_reg_all_tg_pt) ? 1 : 0); 2423 * is of an all registrants type, and the I_T nexus is the last remaining
2424 * registered I_T nexus, then the device server shall also release the
2425 * persistent reservation.
2426 */
2427 if (!list_empty(&dev->t10_pr.registration_list) &&
2428 ((pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) ||
2429 (pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG))) {
2430 dev->dev_pr_res_holder =
2431 list_entry(dev->t10_pr.registration_list.next,
2432 struct t10_pr_registration, pr_reg_list);
2433 dev->dev_pr_res_holder->pr_res_type = pr_res_type;
2434 dev->dev_pr_res_holder->pr_res_scope = pr_res_scope;
2435 dev->dev_pr_res_holder->pr_res_holder = 1;
2436 }
2437 spin_unlock(&dev->t10_pr.registration_lock);
2438out:
2439 if (!dev->dev_pr_res_holder) {
2440 pr_debug("SPC-3 PR [%s] Service Action: %s RELEASE cleared"
2441 " reservation holder TYPE: %s ALL_TG_PT: %d\n",
2442 tfo->get_fabric_name(), (explicit) ? "explicit" :
2443 "implicit", core_scsi3_pr_dump_type(pr_res_type),
2444 (pr_reg->pr_reg_all_tg_pt) ? 1 : 0);
2445 }
2403 pr_debug("SPC-3 PR [%s] RELEASE Node: %s%s\n", 2446 pr_debug("SPC-3 PR [%s] RELEASE Node: %s%s\n",
2404 tfo->get_fabric_name(), se_nacl->initiatorname, 2447 tfo->get_fabric_name(), se_nacl->initiatorname,
2405 i_buf); 2448 i_buf);
@@ -2530,7 +2573,7 @@ core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope,
2530 * server shall not establish a unit attention condition. 2573 * server shall not establish a unit attention condition.
2531 */ 2574 */
2532 __core_scsi3_complete_pro_release(dev, se_sess->se_node_acl, 2575 __core_scsi3_complete_pro_release(dev, se_sess->se_node_acl,
2533 pr_reg, 1); 2576 pr_reg, 1, 0);
2534 2577
2535 spin_unlock(&dev->dev_reservation_lock); 2578 spin_unlock(&dev->dev_reservation_lock);
2536 2579
@@ -2618,7 +2661,7 @@ core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key)
2618 if (pr_res_holder) { 2661 if (pr_res_holder) {
2619 struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl; 2662 struct se_node_acl *pr_res_nacl = pr_res_holder->pr_reg_nacl;
2620 __core_scsi3_complete_pro_release(dev, pr_res_nacl, 2663 __core_scsi3_complete_pro_release(dev, pr_res_nacl,
2621 pr_res_holder, 0); 2664 pr_res_holder, 0, 0);
2622 } 2665 }
2623 spin_unlock(&dev->dev_reservation_lock); 2666 spin_unlock(&dev->dev_reservation_lock);
2624 /* 2667 /*
@@ -2677,7 +2720,7 @@ static void __core_scsi3_complete_pro_preempt(
2677 */ 2720 */
2678 if (dev->dev_pr_res_holder) 2721 if (dev->dev_pr_res_holder)
2679 __core_scsi3_complete_pro_release(dev, nacl, 2722 __core_scsi3_complete_pro_release(dev, nacl,
2680 dev->dev_pr_res_holder, 0); 2723 dev->dev_pr_res_holder, 0, 0);
2681 2724
2682 dev->dev_pr_res_holder = pr_reg; 2725 dev->dev_pr_res_holder = pr_reg;
2683 pr_reg->pr_res_holder = 1; 2726 pr_reg->pr_res_holder = 1;
@@ -2922,8 +2965,8 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
2922 */ 2965 */
2923 if (pr_reg_n != pr_res_holder) 2966 if (pr_reg_n != pr_res_holder)
2924 __core_scsi3_complete_pro_release(dev, 2967 __core_scsi3_complete_pro_release(dev,
2925 pr_res_holder->pr_reg_nacl, 2968 pr_res_holder->pr_reg_nacl,
2926 dev->dev_pr_res_holder, 0); 2969 dev->dev_pr_res_holder, 0, 0);
2927 /* 2970 /*
2928 * b) Remove the registrations for all I_T nexuses identified 2971 * b) Remove the registrations for all I_T nexuses identified
2929 * by the SERVICE ACTION RESERVATION KEY field, except the 2972 * by the SERVICE ACTION RESERVATION KEY field, except the
@@ -3386,7 +3429,7 @@ after_iport_check:
3386 * holder (i.e., the I_T nexus on which the 3429 * holder (i.e., the I_T nexus on which the
3387 */ 3430 */
3388 __core_scsi3_complete_pro_release(dev, pr_res_nacl, 3431 __core_scsi3_complete_pro_release(dev, pr_res_nacl,
3389 dev->dev_pr_res_holder, 0); 3432 dev->dev_pr_res_holder, 0, 0);
3390 /* 3433 /*
3391 * g) Move the persistent reservation to the specified I_T nexus using 3434 * g) Move the persistent reservation to the specified I_T nexus using
3392 * the same scope and type as the persistent reservation released in 3435 * the same scope and type as the persistent reservation released in