diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-07-28 03:07:03 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2011-08-22 15:26:21 -0400 |
commit | 706d5860969b3b24d65d9a57bd3bb5e4a1419c08 (patch) | |
tree | a6293f322a5327d3c317c09197b33d66e22d010e /drivers/target/target_core_transport.c | |
parent | 16ab8e60a0ebc22cfbe61d84e620457a15f3a0bc (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.c | 102 |
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 | ||
2864 | static 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, §or_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: |