Patch "target: Fix COMPARE_AND_WRITE with SG_TO_MEM_NOALLOC handling" has been added to the 3.14-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
target: Fix COMPARE_AND_WRITE with SG_TO_MEM_NOALLOC handling
to the 3.14-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
target-fix-compare_and_write-with-sg_to_mem_noalloc-handling.patch
and it can be found in the queue-3.14 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
c8e639852ad720499912acedfd6b072325fd2807Mon Sep 17 00:00:00 2001
From: Nicholas Bellinger <[email protected]>
Date: Tue, 7 Apr 2015 21:53:27 +0000
Subject: target: Fix COMPARE_AND_WRITE with SG_TO_MEM_NOALLOC handling
From: Nicholas Bellinger <[email protected]>
commit c8e639852ad720499912acedfd6b072325fd2807 upstream.
This patch fixes a bug for COMPARE_AND_WRITE handling with fabrics using SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC.
It adds the missing allocation for cmd->t_bidi_data_sg within transport_generic_new_cmd() that is used by COMPARE_AND_WRITE for the initial READ payload, even if the fabric is already providing a pre-allocated buffer for cmd->t_data_sg.
Also, fix zero-length COMPARE_AND_WRITE handling within the compare_and_write_callback() and target_complete_ok_work() to queue the response, skipping the initial READ.
This fixes COMPARE_AND_WRITE emulation with loopback, vhost, and xen-backend fabric drivers using SG_TO_MEM_NOALLOC.
--- drivers/target/target_core_sbc.c | 15 ++++++++----- drivers/target/target_core_transport.c | 37 +++++++++++++++++++++++++++++---- include/target/target_core_base.h | 2 - 3 files changed, 44 insertions(+), 10 deletions(-)
drivers/target/target_core_sbc.c +10 -5
@@ -314,7 +314,7 @@ sbc_setup_write_same(struct se_cmd *cmd,return 0 ; } -static sense_reason_t xdreadwrite_callback (struct se_cmd *cmd) +static sense_reason_t xdreadwrite_callback (struct se_cmd *cmd,bool success) {unsigned char *buf, *addr;struct scatterlist *sg;
@@ -378,7 +378,7 @@ sbc_execute_rw(struct se_cmd *cmd) cmd->data_direction); } -static sense_reason_t compare_and_write_post (struct se_cmd *cmd) +static sense_reason_t compare_and_write_post (struct se_cmd *cmd,bool success) {struct se_device *dev = cmd->se_dev;
@@ -401,7 +401,7 @@ static sense_reason_t compare_and_write_return TCM_NO_SENSE ; } -static sense_reason_t compare_and_write_callback (struct se_cmd *cmd) +static sense_reason_t compare_and_write_callback (struct se_cmd *cmd,bool success) {struct se_device *dev = cmd->se_dev;struct scatterlist *write_sg =NULL , *sg;
@@ -416,11 +416,16 @@ static sense_reason_t compare_and_write_/* * Handle early failure in transport_generic_request_failure(), -* which will not have taken ->caw_mutex yet.. +* which will not have taken ->caw_sem yet.. */ -if (!cmd->t_data_sg || !cmd->t_bidi_data_sg) +if (!success && (!cmd->t_data_sg || !cmd->t_bidi_data_sg))return TCM_NO_SENSE ;/* +* Handle special case for zero-length COMPARE_AND_WRITE +*/ +if (!cmd->data_length) + goto out; +/* * Immediately exit + release dev->caw_sem if command has already * been failed with a non-zero SCSI status. */
drivers/target/target_core_transport.c +33 -4
@@ -1600,11 +1600,11 @@ void transport_generic_request_failure(stransport_complete_task_attr (cmd);/* * Handle special case for COMPARE_AND_WRITE failure, where the -* callback is expected to drop the per device ->caw_mutex. +* callback is expected to drop the per device ->caw_sem. */ if ((cmd->se_cmd_flags &SCF_COMPARE_AND_WRITE ) && cmd->transport_complete_callback) - cmd->transport_complete_callback (cmd); + cmd->transport_complete_callback (cmd, false);switch (sense_reason) {case TCM_NON_EXISTENT_LUN :
@@ -1941,8 +1941,12 @@ static void target_complete_ok_work(struif (cmd->transport_complete_callback) {sense_reason_t rc; - rc = cmd->transport_complete_callback (cmd); + rc = cmd->transport_complete_callback (cmd, true);if (!rc && !(cmd->se_cmd_flags &SCF_COMPARE_AND_WRITE_POST )) { +if ((cmd->se_cmd_flags &SCF_COMPARE_AND_WRITE ) && + !cmd->data_length) + goto queue_rsp; +return ; }else if (rc) { ret = transport_send_check_condition_and_sense(cmd,
@@ -1956,6 +1960,7 @@ static void target_complete_ok_work(stru } } +queue_rsp:switch (cmd->data_direction) {case DMA_FROM_DEVICE :spin_lock (&cmd->se_lun->lun_sep_lock);
@@ -2044,6 +2049,16 @@ static inline void transport_reset_sgl_ostatic inline void transport_free_pages (struct se_cmd *cmd) {if (cmd->se_cmd_flags &SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC ) { +/* +* Release special case READ buffer payload required for +* SG_TO_MEM_NOALLOC to function with COMPARE_AND_WRITE +*/ +if (cmd->se_cmd_flags &SCF_COMPARE_AND_WRITE ) { +transport_free_sgl (cmd->t_bidi_data_sg, + cmd->t_bidi_data_nents); + cmd->t_bidi_data_sg =NULL ; + cmd->t_bidi_data_nents =0 ; + }transport_reset_sgl_orig (cmd);return ; }
@@ -2192,6 +2207,7 @@ sense_reason_t transport_generic_new_cmd(struct se_cmd *cmd) {int ret =0 ; +bool zero_flag = !(cmd->se_cmd_flags &SCF_SCSI_DATA_CDB );/* * Determine is the TCM fabric module has already allocated physical
@@ -2200,7 +2216,6 @@ transport_generic_new_cmd(struct se_cmd*/ if (!(cmd->se_cmd_flags &SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC ) && cmd->data_length) { -bool zero_flag = !(cmd->se_cmd_flags &SCF_SCSI_DATA_CDB );if ((cmd->se_cmd_flags &SCF_BIDI ) || (cmd->se_cmd_flags &SCF_COMPARE_AND_WRITE )) {
@@ -2223,6 +2238,20 @@ transport_generic_new_cmd(struct se_cmd cmd->data_length, zero_flag);if (ret <0 )return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE ; + }else if ((cmd->se_cmd_flags &SCF_COMPARE_AND_WRITE ) && + cmd->data_length) { +/* +* Special case for COMPARE_AND_WRITE with fabrics +* using SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC. +*/ +u32 caw_length = cmd->t_task_nolb * + cmd->se_dev->dev_attrib.block_size; + + ret =target_alloc_sgl (&cmd->t_bidi_data_sg, + &cmd->t_bidi_data_nents, + caw_length, zero_flag); +if (ret <0 ) +return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE ; }/* * If this command is not a write we can execute it right here,
include/target/target_core_base.h +1 -1
@@ -513,7 +513,7 @@ struct se_cmd {sense_reason_t (*execute_cmd)(struct se_cmd *);sense_reason_t (*execute_rw)(struct se_cmd *,struct scatterlist *,u32 ,enum dma_data_direction ); -sense_reason_t (*transport_complete_callback)(struct se_cmd *); +sense_reason_t (*transport_complete_callback)(struct se_cmd *,bool );unsigned char *t_task_cdb;unsigned char __t_task_cdb[TCM_MAX_COMMAND_SIZE ];
Patches currently in stable-queue which might be from [email protected] are
queue-3.14/target-file-fix-bug-when-config_debug_sg-y-and-dif-protection-enabled.patch queue-3.14/target-fix-compare_and_write-with-sg_to_mem_noalloc-handling.patch queue-3.14/target-file-fix-sg-table-for-prot_buf-initialization.patch