aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2012-11-07 23:01:10 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2012-11-15 15:04:52 -0500
commitcd063bef414c51d79b9c6ea7a8ef8f9d319529bc (patch)
tree7c003f3c6e865cc0eaf4df43683a37802ce4cb5d /drivers/target
parent1920ed61fbbbb38919edfb2427b0b1fd4e4ad8d9 (diff)
target/sbc: Seperate WRITE_SAME based on UNMAP flag in sbc_ops
This patch adds a new sbc_ops->execute_write_same_unmap() caller for use with WRITE_SAME w/ UNMAP=1, and performs the ->execute_cmd() setup based this bit within sbc_setup_write_same() code. Also, makes the changes in sbc_parse_cdb() to handle a sense_reason_t return from sbc_setup_write_same() on error. Reported-by: Christoph Hellwig <hch@lst.de> Cc: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/target_core_sbc.c51
1 files changed, 23 insertions, 28 deletions
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index b8024219cd4f..a5a8f463004b 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -235,26 +235,30 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb)
235 return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32; 235 return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32;
236} 236}
237 237
238static int sbc_write_same_supported(struct se_device *dev, 238static sense_reason_t
239 unsigned char *flags) 239sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops)
240{ 240{
241 if ((flags[0] & 0x04) || (flags[0] & 0x02)) { 241 if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
242 pr_err("WRITE_SAME PBDATA and LBDATA" 242 pr_err("WRITE_SAME PBDATA and LBDATA"
243 " bits not supported for Block Discard" 243 " bits not supported for Block Discard"
244 " Emulation\n"); 244 " Emulation\n");
245 return -ENOSYS; 245 return TCM_UNSUPPORTED_SCSI_OPCODE;
246 } 246 }
247
248 /* 247 /*
249 * Currently for the emulated case we only accept 248 * Special case for WRITE_SAME w/ UNMAP=1 that ends up getting
250 * tpws with the UNMAP=1 bit set. 249 * translated into block discard requests within backend code.
251 */ 250 */
252 if (!(flags[0] & 0x08)) { 251 if (flags[0] & 0x08) {
253 pr_err("WRITE_SAME w/o UNMAP bit not" 252 if (!ops->execute_write_same_unmap)
254 " supported for Block Discard Emulation\n"); 253 return TCM_UNSUPPORTED_SCSI_OPCODE;
255 return -ENOSYS; 254
255 cmd->execute_cmd = ops->execute_write_same_unmap;
256 return 0;
256 } 257 }
258 if (!ops->execute_write_same)
259 return TCM_UNSUPPORTED_SCSI_OPCODE;
257 260
261 cmd->execute_cmd = ops->execute_write_same;
258 return 0; 262 return 0;
259} 263}
260 264
@@ -418,9 +422,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
418 cmd->se_cmd_flags |= SCF_FUA; 422 cmd->se_cmd_flags |= SCF_FUA;
419 break; 423 break;
420 case WRITE_SAME_32: 424 case WRITE_SAME_32:
421 if (!ops->execute_write_same)
422 return TCM_UNSUPPORTED_SCSI_OPCODE;
423
424 sectors = transport_get_sectors_32(cdb); 425 sectors = transport_get_sectors_32(cdb);
425 if (!sectors) { 426 if (!sectors) {
426 pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not" 427 pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not"
@@ -431,9 +432,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
431 size = sbc_get_size(cmd, 1); 432 size = sbc_get_size(cmd, 1);
432 cmd->t_task_lba = get_unaligned_be64(&cdb[12]); 433 cmd->t_task_lba = get_unaligned_be64(&cdb[12]);
433 434
434 if (sbc_write_same_supported(dev, &cdb[10]) < 0) 435 ret = sbc_setup_write_same(cmd, &cdb[10], ops);
435 return TCM_UNSUPPORTED_SCSI_OPCODE; 436 if (ret < 0)
436 cmd->execute_cmd = ops->execute_write_same; 437 return ret;
437 break; 438 break;
438 default: 439 default:
439 pr_err("VARIABLE_LENGTH_CMD service action" 440 pr_err("VARIABLE_LENGTH_CMD service action"
@@ -495,9 +496,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
495 cmd->execute_cmd = ops->execute_unmap; 496 cmd->execute_cmd = ops->execute_unmap;
496 break; 497 break;
497 case WRITE_SAME_16: 498 case WRITE_SAME_16:
498 if (!ops->execute_write_same)
499 return TCM_UNSUPPORTED_SCSI_OPCODE;
500
501 sectors = transport_get_sectors_16(cdb); 499 sectors = transport_get_sectors_16(cdb);
502 if (!sectors) { 500 if (!sectors) {
503 pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); 501 pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
@@ -507,14 +505,11 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
507 size = sbc_get_size(cmd, 1); 505 size = sbc_get_size(cmd, 1);
508 cmd->t_task_lba = get_unaligned_be64(&cdb[2]); 506 cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
509 507
510 if (sbc_write_same_supported(dev, &cdb[1]) < 0) 508 ret = sbc_setup_write_same(cmd, &cdb[1], ops);
511 return TCM_UNSUPPORTED_SCSI_OPCODE; 509 if (ret < 0)
512 cmd->execute_cmd = ops->execute_write_same; 510 return ret;
513 break; 511 break;
514 case WRITE_SAME: 512 case WRITE_SAME:
515 if (!ops->execute_write_same)
516 return TCM_UNSUPPORTED_SCSI_OPCODE;
517
518 sectors = transport_get_sectors_10(cdb); 513 sectors = transport_get_sectors_10(cdb);
519 if (!sectors) { 514 if (!sectors) {
520 pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n"); 515 pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
@@ -528,9 +523,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
528 * Follow sbcr26 with WRITE_SAME (10) and check for the existence 523 * Follow sbcr26 with WRITE_SAME (10) and check for the existence
529 * of byte 1 bit 3 UNMAP instead of original reserved field 524 * of byte 1 bit 3 UNMAP instead of original reserved field
530 */ 525 */
531 if (sbc_write_same_supported(dev, &cdb[1]) < 0) 526 ret = sbc_setup_write_same(cmd, &cdb[1], ops);
532 return TCM_UNSUPPORTED_SCSI_OPCODE; 527 if (ret < 0)
533 cmd->execute_cmd = ops->execute_write_same; 528 return ret;
534 break; 529 break;
535 case VERIFY: 530 case VERIFY:
536 size = 0; 531 size = 0;