Commit fe83558a33f509277aa07566d484096cc7149807

Authored by Linus Torvalds

Merge branch '3.3-urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending

Pull target fixes from Nicholas Bellinger:
 "This series addresses two recently reported regression bugs related to
  legacy SCSI reservation usage in target core, and iscsi-target
  reservation conflict handling.

  The second patch in particular addresses possible data-corruption with
  SCSI reservations that is specific to iscsi-target fabric LUNs with
  multiple client writers.  Both patches need to go into v3.2 stable
  ASAP, and the branch based on the last target-pending/3.3-rc-fixes
  HEAD.

  Again, thanks to Martin Svec for his help to identify and address this
  regression bug with iscsi-target."

* '3.3-urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
  iscsi-target: Fix reservation conflict -EBUSY response handling bug
  target: Fix compatible reservation handling (CRH=1) with legacy RESERVE/RELEASE

Showing 3 changed files Side-by-side Diff

drivers/target/iscsi/iscsi_target.c
... ... @@ -1028,7 +1028,7 @@
1028 1028 return iscsit_add_reject_from_cmd(
1029 1029 ISCSI_REASON_BOOKMARK_NO_RESOURCES,
1030 1030 1, 1, buf, cmd);
1031   - } else if (transport_ret == -EINVAL) {
  1031 + } else if (transport_ret < 0) {
1032 1032 /*
1033 1033 * Unsupported SAM Opcode. CHECK_CONDITION will be sent
1034 1034 * in iscsit_execute_cmd() during the CmdSN OOO Execution
drivers/target/target_core_pr.c
... ... @@ -117,7 +117,7 @@
117 117 struct se_node_acl *, struct se_session *);
118 118 static void core_scsi3_put_pr_reg(struct t10_pr_registration *);
119 119  
120   -static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd, int *ret)
  120 +static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd)
121 121 {
122 122 struct se_session *se_sess = cmd->se_sess;
123 123 struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
... ... @@ -127,7 +127,7 @@
127 127 int conflict = 0;
128 128  
129 129 if (!crh)
130   - return false;
  130 + return -EINVAL;
131 131  
132 132 pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl,
133 133 se_sess);
134 134  
... ... @@ -155,16 +155,14 @@
155 155 */
156 156 if (pr_reg->pr_res_holder) {
157 157 core_scsi3_put_pr_reg(pr_reg);
158   - *ret = 0;
159   - return false;
  158 + return 1;
160 159 }
161 160 if ((pr_reg->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY) ||
162 161 (pr_reg->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY) ||
163 162 (pr_reg->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG) ||
164 163 (pr_reg->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)) {
165 164 core_scsi3_put_pr_reg(pr_reg);
166   - *ret = 0;
167   - return true;
  165 + return 1;
168 166 }
169 167 core_scsi3_put_pr_reg(pr_reg);
170 168 conflict = 1;
171 169  
... ... @@ -189,10 +187,10 @@
189 187 " while active SPC-3 registrations exist,"
190 188 " returning RESERVATION_CONFLICT\n");
191 189 cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
192   - return true;
  190 + return -EBUSY;
193 191 }
194 192  
195   - return false;
  193 + return 0;
196 194 }
197 195  
198 196 int target_scsi2_reservation_release(struct se_task *task)
199 197  
200 198  
... ... @@ -201,12 +199,18 @@
201 199 struct se_device *dev = cmd->se_dev;
202 200 struct se_session *sess = cmd->se_sess;
203 201 struct se_portal_group *tpg = sess->se_tpg;
204   - int ret = 0;
  202 + int ret = 0, rc;
205 203  
206 204 if (!sess || !tpg)
207 205 goto out;
208   - if (target_check_scsi2_reservation_conflict(cmd, &ret))
  206 + rc = target_check_scsi2_reservation_conflict(cmd);
  207 + if (rc == 1)
209 208 goto out;
  209 + else if (rc < 0) {
  210 + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
  211 + ret = -EINVAL;
  212 + goto out;
  213 + }
210 214  
211 215 ret = 0;
212 216 spin_lock(&dev->dev_reservation_lock);
... ... @@ -243,7 +247,7 @@
243 247 struct se_device *dev = cmd->se_dev;
244 248 struct se_session *sess = cmd->se_sess;
245 249 struct se_portal_group *tpg = sess->se_tpg;
246   - int ret = 0;
  250 + int ret = 0, rc;
247 251  
248 252 if ((cmd->t_task_cdb[1] & 0x01) &&
249 253 (cmd->t_task_cdb[1] & 0x02)) {
250 254  
... ... @@ -259,8 +263,14 @@
259 263 */
260 264 if (!sess || !tpg)
261 265 goto out;
262   - if (target_check_scsi2_reservation_conflict(cmd, &ret))
  266 + rc = target_check_scsi2_reservation_conflict(cmd);
  267 + if (rc == 1)
263 268 goto out;
  269 + else if (rc < 0) {
  270 + cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
  271 + ret = -EINVAL;
  272 + goto out;
  273 + }
264 274  
265 275 ret = 0;
266 276 spin_lock(&dev->dev_reservation_lock);
drivers/target/target_core_transport.c
... ... @@ -2539,6 +2539,7 @@
2539 2539 cmd, cdb, pr_reg_type) != 0) {
2540 2540 cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
2541 2541 cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT;
  2542 + cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
2542 2543 cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
2543 2544 return -EBUSY;
2544 2545 }