aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@daterainc.com>2013-08-19 17:34:17 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2013-09-09 17:29:26 -0400
commita6b0133c19af1ab268ed1f4414efa2782896a870 (patch)
treead55c8b08d283a8cf1fa2b3ae6d9a8b0b02b8677
parent1c68cc1626341665a8bd1d2c7dfffd7fc852a79c (diff)
target: Add return for se_cmd->transport_complete_callback
This patch adds a sense_reason_t return to ->transport_complete_callback(), and updates target_complete_ok_work() to invoke the call if necessary to transport_send_check_condition_and_sense() during the failure case. Also update xdreadwrite_callback() to use this return value. Cc: Christoph Hellwig <hch@lst.de> Cc: Hannes Reinecke <hare@suse.de> Cc: Martin Petersen <martin.petersen@oracle.com> Cc: Chris Mason <chris.mason@fusionio.com> Cc: James Bottomley <JBottomley@Parallels.com> Cc: Nicholas Bellinger <nab@linux-iscsi.org> Signed-off-by: Nicholas Bellinger <nab@daterainc.com>
-rw-r--r--drivers/target/target_core_sbc.c13
-rw-r--r--drivers/target/target_core_transport.c20
-rw-r--r--include/target/target_core_base.h2
3 files changed, 26 insertions, 9 deletions
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index 8a462773d0c8..be5234abb76c 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -280,13 +280,13 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
280 return 0; 280 return 0;
281} 281}
282 282
283static void xdreadwrite_callback(struct se_cmd *cmd) 283static sense_reason_t xdreadwrite_callback(struct se_cmd *cmd)
284{ 284{
285 unsigned char *buf, *addr; 285 unsigned char *buf, *addr;
286 struct scatterlist *sg; 286 struct scatterlist *sg;
287 unsigned int offset; 287 unsigned int offset;
288 int i; 288 sense_reason_t ret = TCM_NO_SENSE;
289 int count; 289 int i, count;
290 /* 290 /*
291 * From sbc3r22.pdf section 5.48 XDWRITEREAD (10) command 291 * From sbc3r22.pdf section 5.48 XDWRITEREAD (10) command
292 * 292 *
@@ -301,7 +301,7 @@ static void xdreadwrite_callback(struct se_cmd *cmd)
301 buf = kmalloc(cmd->data_length, GFP_KERNEL); 301 buf = kmalloc(cmd->data_length, GFP_KERNEL);
302 if (!buf) { 302 if (!buf) {
303 pr_err("Unable to allocate xor_callback buf\n"); 303 pr_err("Unable to allocate xor_callback buf\n");
304 return; 304 return TCM_OUT_OF_RESOURCES;
305 } 305 }
306 /* 306 /*
307 * Copy the scatterlist WRITE buffer located at cmd->t_data_sg 307 * Copy the scatterlist WRITE buffer located at cmd->t_data_sg
@@ -320,8 +320,10 @@ static void xdreadwrite_callback(struct se_cmd *cmd)
320 offset = 0; 320 offset = 0;
321 for_each_sg(cmd->t_bidi_data_sg, sg, cmd->t_bidi_data_nents, count) { 321 for_each_sg(cmd->t_bidi_data_sg, sg, cmd->t_bidi_data_nents, count) {
322 addr = kmap_atomic(sg_page(sg)); 322 addr = kmap_atomic(sg_page(sg));
323 if (!addr) 323 if (!addr) {
324 ret = TCM_OUT_OF_RESOURCES;
324 goto out; 325 goto out;
326 }
325 327
326 for (i = 0; i < sg->length; i++) 328 for (i = 0; i < sg->length; i++)
327 *(addr + sg->offset + i) ^= *(buf + offset + i); 329 *(addr + sg->offset + i) ^= *(buf + offset + i);
@@ -332,6 +334,7 @@ static void xdreadwrite_callback(struct se_cmd *cmd)
332 334
333out: 335out:
334 kfree(buf); 336 kfree(buf);
337 return ret;
335} 338}
336 339
337sense_reason_t 340sense_reason_t
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 98ec7110873b..53d1d756f7f5 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1904,10 +1904,24 @@ static void target_complete_ok_work(struct work_struct *work)
1904 } 1904 }
1905 /* 1905 /*
1906 * Check for a callback, used by amongst other things 1906 * Check for a callback, used by amongst other things
1907 * XDWRITE_READ_10 emulation. 1907 * XDWRITE_READ_10 and COMPARE_AND_WRITE emulation.
1908 */ 1908 */
1909 if (cmd->transport_complete_callback) 1909 if (cmd->transport_complete_callback) {
1910 cmd->transport_complete_callback(cmd); 1910 sense_reason_t rc;
1911
1912 rc = cmd->transport_complete_callback(cmd);
1913 if (!rc)
1914 return;
1915
1916 ret = transport_send_check_condition_and_sense(cmd,
1917 rc, 0);
1918 if (ret == -EAGAIN || ret == -ENOMEM)
1919 goto queue_full;
1920
1921 transport_lun_remove_cmd(cmd);
1922 transport_cmd_check_stop_to_fabric(cmd);
1923 return;
1924 }
1911 1925
1912 switch (cmd->data_direction) { 1926 switch (cmd->data_direction) {
1913 case DMA_FROM_DEVICE: 1927 case DMA_FROM_DEVICE:
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index bd55acd43005..6892b3332ebb 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -447,7 +447,7 @@ struct se_cmd {
447 struct kref cmd_kref; 447 struct kref cmd_kref;
448 struct target_core_fabric_ops *se_tfo; 448 struct target_core_fabric_ops *se_tfo;
449 sense_reason_t (*execute_cmd)(struct se_cmd *); 449 sense_reason_t (*execute_cmd)(struct se_cmd *);
450 void (*transport_complete_callback)(struct se_cmd *); 450 sense_reason_t (*transport_complete_callback)(struct se_cmd *);
451 451
452 unsigned char *t_task_cdb; 452 unsigned char *t_task_cdb;
453 unsigned char __t_task_cdb[TCM_MAX_COMMAND_SIZE]; 453 unsigned char __t_task_cdb[TCM_MAX_COMMAND_SIZE];