aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target/target_core_transport.c
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2011-07-28 03:07:03 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2011-08-22 15:26:21 -0400
commit706d5860969b3b24d65d9a57bd3bb5e4a1419c08 (patch)
treea6293f322a5327d3c317c09197b33d66e22d010e /drivers/target/target_core_transport.c
parent16ab8e60a0ebc22cfbe61d84e620457a15f3a0bc (diff)
target: Add WRITE_SAME (10) parsing and refactor passthrough checks
This patch adds initial WRITE_SAME (10) w/ UNMAP=1 support following updates in sbcr26 to allow UNMAP=1 for the non 16 + 32 byte CDB case. It also refactors current pSCSI passthrough passthrough checks into target_check_write_same_discard() ahead of UNMAP=0 w/ write payload support into target_core_iblock.c. This includes the support for handling WRITE_SAME in transport_emulate_control_cdb(), and converts target_emulate_write_same to accept num_blocks directly for WRITE_SAME, WRITE_SAME_16 and WRITE_SAME_32. Reported-by: Eric Seppanen <eric@purestorage.com> Cc: Roland Dreier <roland@purestorage.com> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: Nicholas Bellinger <nab@risingtidesystems.com>
Diffstat (limited to 'drivers/target/target_core_transport.c')
-rw-r--r--drivers/target/target_core_transport.c102
1 files changed, 57 insertions, 45 deletions
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index fd7d4518b8e..eb8055aa6e6 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -2861,6 +2861,38 @@ static int transport_cmd_get_valid_sectors(struct se_cmd *cmd)
2861 return sectors; 2861 return sectors;
2862} 2862}
2863 2863
2864static int target_check_write_same_discard(unsigned char *flags, struct se_device *dev)
2865{
2866 /*
2867 * Determine if the received WRITE_SAME is used to for direct
2868 * passthrough into Linux/SCSI with struct request via TCM/pSCSI
2869 * or we are signaling the use of internal WRITE_SAME + UNMAP=1
2870 * emulation for -> Linux/BLOCK disbard with TCM/IBLOCK code.
2871 */
2872 int passthrough = (dev->transport->transport_type ==
2873 TRANSPORT_PLUGIN_PHBA_PDEV);
2874
2875 if (!passthrough) {
2876 if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
2877 pr_err("WRITE_SAME PBDATA and LBDATA"
2878 " bits not supported for Block Discard"
2879 " Emulation\n");
2880 return -ENOSYS;
2881 }
2882 /*
2883 * Currently for the emulated case we only accept
2884 * tpws with the UNMAP=1 bit set.
2885 */
2886 if (!(flags[0] & 0x08)) {
2887 pr_err("WRITE_SAME w/o UNMAP bit not"
2888 " supported for Block Discard Emulation\n");
2889 return -ENOSYS;
2890 }
2891 }
2892
2893 return 0;
2894}
2895
2864/* transport_generic_cmd_sequencer(): 2896/* transport_generic_cmd_sequencer():
2865 * 2897 *
2866 * Generic Command Sequencer that should work for most DAS transport 2898 * Generic Command Sequencer that should work for most DAS transport
@@ -3081,27 +3113,9 @@ static int transport_generic_cmd_sequencer(
3081 cmd->t_task_lba = get_unaligned_be64(&cdb[12]); 3113 cmd->t_task_lba = get_unaligned_be64(&cdb[12]);
3082 cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; 3114 cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
3083 3115
3084 /* 3116 if (target_check_write_same_discard(&cdb[10], dev) < 0)
3085 * Skip the remaining assignments for TCM/PSCSI passthrough
3086 */
3087 if (passthrough)
3088 break;
3089
3090 if ((cdb[10] & 0x04) || (cdb[10] & 0x02)) {
3091 pr_err("WRITE_SAME PBDATA and LBDATA"
3092 " bits not supported for Block Discard"
3093 " Emulation\n");
3094 goto out_invalid_cdb_field; 3117 goto out_invalid_cdb_field;
3095 } 3118
3096 /*
3097 * Currently for the emulated case we only accept
3098 * tpws with the UNMAP=1 bit set.
3099 */
3100 if (!(cdb[10] & 0x08)) {
3101 pr_err("WRITE_SAME w/o UNMAP bit not"
3102 " supported for Block Discard Emulation\n");
3103 goto out_invalid_cdb_field;
3104 }
3105 break; 3119 break;
3106 default: 3120 default:
3107 pr_err("VARIABLE_LENGTH_CMD service action" 3121 pr_err("VARIABLE_LENGTH_CMD service action"
@@ -3358,33 +3372,31 @@ static int transport_generic_cmd_sequencer(
3358 } 3372 }
3359 3373
3360 cmd->t_task_lba = get_unaligned_be64(&cdb[2]); 3374 cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
3361 passthrough = (dev->transport->transport_type == 3375 cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
3362 TRANSPORT_PLUGIN_PHBA_PDEV); 3376
3363 /* 3377 if (target_check_write_same_discard(&cdb[1], dev) < 0)
3364 * Determine if the received WRITE_SAME_16 is used to for direct 3378 goto out_invalid_cdb_field;
3365 * passthrough into Linux/SCSI with struct request via TCM/pSCSI 3379 break;
3366 * or we are signaling the use of internal WRITE_SAME + UNMAP=1 3380 case WRITE_SAME:
3367 * emulation for -> Linux/BLOCK disbard with TCM/IBLOCK and 3381 sectors = transport_get_sectors_10(cdb, cmd, &sector_ret);
3368 * TCM/FILEIO subsystem plugin backstores. 3382 if (sector_ret)
3369 */ 3383 goto out_unsupported_cdb;
3370 if (!passthrough) { 3384
3371 if ((cdb[1] & 0x04) || (cdb[1] & 0x02)) { 3385 if (sectors)
3372 pr_err("WRITE_SAME PBDATA and LBDATA" 3386 size = transport_get_size(sectors, cdb, cmd);
3373 " bits not supported for Block Discard" 3387 else {
3374 " Emulation\n"); 3388 pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
3375 goto out_invalid_cdb_field; 3389 goto out_invalid_cdb_field;
3376 }
3377 /*
3378 * Currently for the emulated case we only accept
3379 * tpws with the UNMAP=1 bit set.
3380 */
3381 if (!(cdb[1] & 0x08)) {
3382 pr_err("WRITE_SAME w/o UNMAP bit not "
3383 " supported for Block Discard Emulation\n");
3384 goto out_invalid_cdb_field;
3385 }
3386 } 3390 }
3391
3392 cmd->t_task_lba = get_unaligned_be32(&cdb[2]);
3387 cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; 3393 cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
3394 /*
3395 * Follow sbcr26 with WRITE_SAME (10) and check for the existence
3396 * of byte 1 bit 3 UNMAP instead of original reserved field
3397 */
3398 if (target_check_write_same_discard(&cdb[1], dev) < 0)
3399 goto out_invalid_cdb_field;
3388 break; 3400 break;
3389 case ALLOW_MEDIUM_REMOVAL: 3401 case ALLOW_MEDIUM_REMOVAL:
3390 case GPCMD_CLOSE_TRACK: 3402 case GPCMD_CLOSE_TRACK: