Przeglądaj źródła

Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending

* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (62 commits)
  target: Fix compile warning w/ missing module.h include
  target: Remove legacy se_task->task_timer and associated logic
  target: Fix incorrect transport_sent usage
  target: re-use the command S/G list for single-task commands
  target: Fix BIDI t_task_cdb handling in transport_generic_new_cmd
  target: remove transport_allocate_tasks
  target: merge transport_new_cmd_obj into transport_generic_new_cmd
  target: remove the task_sg_bidi field se_task and pSCSI BIDI support
  target: transport_subsystem_check_init cleanups
  target: use a workqueue for I/O completions
  target: remove unused TRANSPORT_ states
  target: remove TRANSPORT_DEFERRED_CMD state
  target: remove the TRANSPORT_REMOVE state
  target: move depth_left manipulation out of transport_generic_request_failure
  target: stop task timers earlier
  target: remove TF_TIMER_STOP
  target: factor some duplicate code for stopping a task
  target: fix list walking in transport_free_dev_tasks
  target: use transport_cmd_check_stop_to_fabric consistently
  target: do not pass the queue object to transport_remove_cmd_from_queue
  ...
Linus Torvalds 13 lat temu
rodzic
commit
7c1953ddb6
36 zmienionych plików z 684 dodań i 1485 usunięć
  1. 0 1
      drivers/target/Makefile
  2. 4 35
      drivers/target/iscsi/iscsi_target.c
  3. 3 31
      drivers/target/iscsi/iscsi_target_auth.c
  4. 3 1
      drivers/target/iscsi/iscsi_target_core.h
  5. 7 42
      drivers/target/iscsi/iscsi_target_erl2.c
  6. 3 3
      drivers/target/iscsi/iscsi_target_tmr.c
  7. 19 1
      drivers/target/iscsi/iscsi_target_util.c
  8. 1 0
      drivers/target/iscsi/iscsi_target_util.h
  9. 15 3
      drivers/target/loopback/tcm_loop.c
  10. 20 1
      drivers/target/target_core_alua.c
  11. 64 15
      drivers/target/target_core_cdb.c
  12. 1 15
      drivers/target/target_core_configfs.c
  13. 15 55
      drivers/target/target_core_device.c
  14. 0 1
      drivers/target/target_core_fabric_configfs.c
  15. 8 48
      drivers/target/target_core_file.c
  16. 1 3
      drivers/target/target_core_file.h
  17. 83 191
      drivers/target/target_core_iblock.c
  18. 0 2
      drivers/target/target_core_iblock.h
  19. 0 1
      drivers/target/target_core_pr.c
  20. 68 193
      drivers/target/target_core_pscsi.c
  21. 0 1
      drivers/target/target_core_pscsi.h
  22. 3 16
      drivers/target/target_core_rd.c
  23. 0 2
      drivers/target/target_core_rd.h
  24. 0 105
      drivers/target/target_core_scdb.c
  25. 0 10
      drivers/target/target_core_scdb.h
  26. 0 1
      drivers/target/target_core_stat.c
  27. 152 99
      drivers/target/target_core_tmr.c
  28. 165 476
      drivers/target/target_core_transport.c
  29. 0 1
      drivers/target/target_core_ua.c
  30. 8 10
      drivers/target/tcm_fc/tfc_cmd.c
  31. 5 8
      drivers/target/tcm_fc/tfc_conf.c
  32. 0 1
      drivers/target/tcm_fc/tfc_io.c
  33. 0 1
      drivers/target/tcm_fc/tfc_sess.c
  34. 21 50
      include/target/target_core_base.h
  35. 1 1
      include/target/target_core_tmr.h
  36. 14 61
      include/target/target_core_transport.h

+ 0 - 1
drivers/target/Makefile

@@ -6,7 +6,6 @@ target_core_mod-y		:= target_core_configfs.o \
 				   target_core_hba.o \
 				   target_core_pr.o \
 				   target_core_alua.o \
-				   target_core_scdb.o \
 				   target_core_tmr.o \
 				   target_core_tpg.o \
 				   target_core_transport.o \

+ 4 - 35
drivers/target/iscsi/iscsi_target.c

@@ -765,7 +765,7 @@ static int iscsit_allocate_iovecs(struct iscsi_cmd *cmd)
 	u32 iov_count = (cmd->se_cmd.t_data_nents == 0) ? 1 :
 				cmd->se_cmd.t_data_nents;
 
-	iov_count += TRANSPORT_IOV_DATA_BUFFER;
+	iov_count += ISCSI_IOV_DATA_BUFFER;
 
 	cmd->iov_data = kzalloc(iov_count * sizeof(struct kvec), GFP_KERNEL);
 	if (!cmd->iov_data) {
@@ -3538,16 +3538,8 @@ get_immediate:
 				spin_lock_bh(&conn->cmd_lock);
 				list_del(&cmd->i_list);
 				spin_unlock_bh(&conn->cmd_lock);
-				/*
-				 * Determine if a struct se_cmd is assoicated with
-				 * this struct iscsi_cmd.
-				 */
-				if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) &&
-				    !(cmd->tmr_req))
-					iscsit_release_cmd(cmd);
-				else
-					transport_generic_free_cmd(&cmd->se_cmd,
-								1, 0);
+
+				iscsit_free_cmd(cmd);
 				goto get_immediate;
 			case ISTATE_SEND_NOPIN_WANT_RESPONSE:
 				spin_unlock_bh(&cmd->istate_lock);
@@ -3940,7 +3932,6 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
 {
 	struct iscsi_cmd *cmd = NULL, *cmd_tmp = NULL;
 	struct iscsi_session *sess = conn->sess;
-	struct se_cmd *se_cmd;
 	/*
 	 * We expect this function to only ever be called from either RX or TX
 	 * thread context via iscsit_close_connection() once the other context
@@ -3948,35 +3939,13 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
 	 */
 	spin_lock_bh(&conn->cmd_lock);
 	list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_list) {
-		if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD)) {
 
-			list_del(&cmd->i_list);
-			spin_unlock_bh(&conn->cmd_lock);
-			iscsit_increment_maxcmdsn(cmd, sess);
-			se_cmd = &cmd->se_cmd;
-			/*
-			 * Special cases for active iSCSI TMR, and
-			 * transport_lookup_cmd_lun() failing from
-			 * iscsit_get_lun_for_cmd() in iscsit_handle_scsi_cmd().
-			 */
-			if (cmd->tmr_req && se_cmd->transport_wait_for_tasks)
-				se_cmd->transport_wait_for_tasks(se_cmd, 1, 1);
-			else if (cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD)
-				transport_release_cmd(se_cmd);
-			else
-				iscsit_release_cmd(cmd);
-
-			spin_lock_bh(&conn->cmd_lock);
-			continue;
-		}
 		list_del(&cmd->i_list);
 		spin_unlock_bh(&conn->cmd_lock);
 
 		iscsit_increment_maxcmdsn(cmd, sess);
-		se_cmd = &cmd->se_cmd;
 
-		if (se_cmd->transport_wait_for_tasks)
-			se_cmd->transport_wait_for_tasks(se_cmd, 1, 1);
+		iscsit_free_cmd(cmd);
 
 		spin_lock_bh(&conn->cmd_lock);
 	}

+ 3 - 31
drivers/target/iscsi/iscsi_target_auth.c

@@ -18,6 +18,7 @@
  * GNU General Public License for more details.
  ******************************************************************************/
 
+#include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/crypto.h>
 #include <linux/err.h>
@@ -27,40 +28,11 @@
 #include "iscsi_target_nego.h"
 #include "iscsi_target_auth.h"
 
-static unsigned char chap_asciihex_to_binaryhex(unsigned char val[2])
-{
-	unsigned char result = 0;
-	/*
-	 * MSB
-	 */
-	if ((val[0] >= 'a') && (val[0] <= 'f'))
-		result = ((val[0] - 'a' + 10) & 0xf) << 4;
-	else
-		if ((val[0] >= 'A') && (val[0] <= 'F'))
-			result = ((val[0] - 'A' + 10) & 0xf) << 4;
-		else /* digit */
-			result = ((val[0] - '0') & 0xf) << 4;
-	/*
-	 * LSB
-	 */
-	if ((val[1] >= 'a') && (val[1] <= 'f'))
-		result |= ((val[1] - 'a' + 10) & 0xf);
-	else
-		if ((val[1] >= 'A') && (val[1] <= 'F'))
-			result |= ((val[1] - 'A' + 10) & 0xf);
-		else /* digit */
-			result |= ((val[1] - '0') & 0xf);
-
-	return result;
-}
-
 static int chap_string_to_hex(unsigned char *dst, unsigned char *src, int len)
 {
-	int i, j = 0;
+	int j = DIV_ROUND_UP(len, 2);
 
-	for (i = 0; i < len; i += 2) {
-		dst[j++] = (unsigned char) chap_asciihex_to_binaryhex(&src[i]);
-	}
+	hex2bin(dst, src, j);
 
 	dst[j] = '\0';
 	return j;

+ 3 - 1
drivers/target/iscsi/iscsi_target_core.h

@@ -57,6 +57,9 @@
 #define TA_PROD_MODE_WRITE_PROTECT	0
 #define TA_CACHE_CORE_NPS		0
 
+
+#define ISCSI_IOV_DATA_BUFFER		5
+
 enum tpg_np_network_transport_table {
 	ISCSI_TCP				= 0,
 	ISCSI_SCTP_TCP				= 1,
@@ -425,7 +428,6 @@ struct iscsi_cmd {
 	/* Number of times struct iscsi_cmd is present in immediate queue */
 	atomic_t		immed_queue_count;
 	atomic_t		response_queue_count;
-	atomic_t		transport_sent;
 	spinlock_t		datain_lock;
 	spinlock_t		dataout_timeout_lock;
 	/* spinlock for protecting struct iscsi_cmd->i_state */

+ 7 - 42
drivers/target/iscsi/iscsi_target_erl2.c

@@ -143,12 +143,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
 			list_del(&cmd->i_list);
 			cmd->conn = NULL;
 			spin_unlock(&cr->conn_recovery_cmd_lock);
-			if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
-			    !(cmd->se_cmd.transport_wait_for_tasks))
-				iscsit_release_cmd(cmd);
-			else
-				cmd->se_cmd.transport_wait_for_tasks(
-						&cmd->se_cmd, 1, 1);
+			iscsit_free_cmd(cmd);
 			spin_lock(&cr->conn_recovery_cmd_lock);
 		}
 		spin_unlock(&cr->conn_recovery_cmd_lock);
@@ -170,12 +165,7 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
 			list_del(&cmd->i_list);
 			cmd->conn = NULL;
 			spin_unlock(&cr->conn_recovery_cmd_lock);
-			if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
-			    !(cmd->se_cmd.transport_wait_for_tasks))
-				iscsit_release_cmd(cmd);
-			else
-				cmd->se_cmd.transport_wait_for_tasks(
-						&cmd->se_cmd, 1, 1);
+			iscsit_free_cmd(cmd);
 			spin_lock(&cr->conn_recovery_cmd_lock);
 		}
 		spin_unlock(&cr->conn_recovery_cmd_lock);
@@ -260,12 +250,7 @@ void iscsit_discard_cr_cmds_by_expstatsn(
 		iscsit_remove_cmd_from_connection_recovery(cmd, sess);
 
 		spin_unlock(&cr->conn_recovery_cmd_lock);
-		if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
-		    !(cmd->se_cmd.transport_wait_for_tasks))
-			iscsit_release_cmd(cmd);
-		else
-			cmd->se_cmd.transport_wait_for_tasks(
-					&cmd->se_cmd, 1, 0);
+		iscsit_free_cmd(cmd);
 		spin_lock(&cr->conn_recovery_cmd_lock);
 	}
 	spin_unlock(&cr->conn_recovery_cmd_lock);
@@ -319,12 +304,7 @@ int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *conn)
 		list_del(&cmd->i_list);
 
 		spin_unlock_bh(&conn->cmd_lock);
-		if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
-		    !(cmd->se_cmd.transport_wait_for_tasks))
-			iscsit_release_cmd(cmd);
-		else
-			cmd->se_cmd.transport_wait_for_tasks(
-					&cmd->se_cmd, 1, 1);
+		iscsit_free_cmd(cmd);
 		spin_lock_bh(&conn->cmd_lock);
 	}
 	spin_unlock_bh(&conn->cmd_lock);
@@ -377,13 +357,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
 
 			list_del(&cmd->i_list);
 			spin_unlock_bh(&conn->cmd_lock);
-
-			if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
-			    !(cmd->se_cmd.transport_wait_for_tasks))
-				iscsit_release_cmd(cmd);
-			else
-				cmd->se_cmd.transport_wait_for_tasks(
-						&cmd->se_cmd, 1, 0);
+			iscsit_free_cmd(cmd);
 			spin_lock_bh(&conn->cmd_lock);
 			continue;
 		}
@@ -403,13 +377,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
 		     (cmd->cmd_sn >= conn->sess->exp_cmd_sn)) {
 			list_del(&cmd->i_list);
 			spin_unlock_bh(&conn->cmd_lock);
-
-			if (!(cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) ||
-			    !(cmd->se_cmd.transport_wait_for_tasks))
-				iscsit_release_cmd(cmd);
-			else
-				cmd->se_cmd.transport_wait_for_tasks(
-						&cmd->se_cmd, 1, 1);
+			iscsit_free_cmd(cmd);
 			spin_lock_bh(&conn->cmd_lock);
 			continue;
 		}
@@ -434,10 +402,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
 
 		iscsit_free_all_datain_reqs(cmd);
 
-		if ((cmd->se_cmd.se_cmd_flags & SCF_SE_LUN_CMD) &&
-		     cmd->se_cmd.transport_wait_for_tasks)
-			cmd->se_cmd.transport_wait_for_tasks(&cmd->se_cmd,
-					0, 0);
+		transport_wait_for_tasks(&cmd->se_cmd);
 		/*
 		 * Add the struct iscsi_cmd to the connection recovery cmd list
 		 */

+ 3 - 3
drivers/target/iscsi/iscsi_target_tmr.c

@@ -250,7 +250,7 @@ static int iscsit_task_reassign_complete_write(
 	 * so if we have received all DataOUT we can safety ignore Initiator.
 	 */
 	if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) {
-		if (!atomic_read(&cmd->transport_sent)) {
+		if (!atomic_read(&cmd->se_cmd.t_transport_sent)) {
 			pr_debug("WRITE ITT: 0x%08x: t_state: %d"
 				" never sent to transport\n",
 				cmd->init_task_tag, cmd->se_cmd.t_state);
@@ -314,11 +314,11 @@ static int iscsit_task_reassign_complete_read(
 		cmd->acked_data_sn = (tmr_req->exp_data_sn - 1);
 	}
 
-	if (!atomic_read(&cmd->transport_sent)) {
+	if (!atomic_read(&cmd->se_cmd.t_transport_sent)) {
 		pr_debug("READ ITT: 0x%08x: t_state: %d never sent to"
 			" transport\n", cmd->init_task_tag,
 			cmd->se_cmd.t_state);
-		transport_generic_handle_cdb(se_cmd);
+		transport_handle_cdb_direct(se_cmd);
 		return 0;
 	}
 

+ 19 - 1
drivers/target/iscsi/iscsi_target_util.c

@@ -289,7 +289,8 @@ struct iscsi_cmd *iscsit_allocate_se_cmd_for_tmr(
 	}
 
 	se_cmd->se_tmr_req = core_tmr_alloc_req(se_cmd,
-				(void *)cmd->tmr_req, tcm_function);
+				(void *)cmd->tmr_req, tcm_function,
+				GFP_KERNEL);
 	if (!se_cmd->se_tmr_req)
 		goto out;
 
@@ -839,6 +840,23 @@ void iscsit_release_cmd(struct iscsi_cmd *cmd)
 	kmem_cache_free(lio_cmd_cache, cmd);
 }
 
+void iscsit_free_cmd(struct iscsi_cmd *cmd)
+{
+	/*
+	 * Determine if a struct se_cmd is assoicated with
+	 * this struct iscsi_cmd.
+	 */
+	switch (cmd->iscsi_opcode) {
+	case ISCSI_OP_SCSI_CMD:
+	case ISCSI_OP_SCSI_TMFUNC:
+		transport_generic_free_cmd(&cmd->se_cmd, 1);
+		break;
+	default:
+		iscsit_release_cmd(cmd);
+		break;
+	}
+}
+
 int iscsit_check_session_usage_count(struct iscsi_session *sess)
 {
 	spin_lock_bh(&sess->session_usage_lock);

+ 1 - 0
drivers/target/iscsi/iscsi_target_util.h

@@ -30,6 +30,7 @@ extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_c
 extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *);
 extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *);
 extern void iscsit_release_cmd(struct iscsi_cmd *);
+extern void iscsit_free_cmd(struct iscsi_cmd *);
 extern int iscsit_check_session_usage_count(struct iscsi_session *);
 extern void iscsit_dec_session_usage_count(struct iscsi_session *);
 extern void iscsit_inc_session_usage_count(struct iscsi_session *);

+ 15 - 3
drivers/target/loopback/tcm_loop.c

@@ -200,7 +200,7 @@ static void tcm_loop_check_stop_free(struct se_cmd *se_cmd)
 	 * Release the struct se_cmd, which will make a callback to release
 	 * struct tcm_loop_cmd * in tcm_loop_deallocate_core_cmd()
 	 */
-	transport_generic_free_cmd(se_cmd, 0, 0);
+	transport_generic_free_cmd(se_cmd, 0);
 }
 
 static void tcm_loop_release_cmd(struct se_cmd *se_cmd)
@@ -290,6 +290,15 @@ static int tcm_loop_queuecommand(
 	 */
 	tl_hba = *(struct tcm_loop_hba **)shost_priv(sc->device->host);
 	tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id];
+	/*
+	 * Ensure that this tl_tpg reference from the incoming sc->device->id
+	 * has already been configured via tcm_loop_make_naa_tpg().
+	 */
+	if (!tl_tpg->tl_hba) {
+		set_host_byte(sc, DID_NO_CONNECT);
+		sc->scsi_done(sc);
+		return 0;
+	}
 	se_tpg = &tl_tpg->tl_se_tpg;
 	/*
 	 * Determine the SAM Task Attribute and allocate tl_cmd and
@@ -366,7 +375,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
 	 * Allocate the LUN_RESET TMR
 	 */
 	se_cmd->se_tmr_req = core_tmr_alloc_req(se_cmd, tl_tmr,
-				TMR_LUN_RESET);
+						TMR_LUN_RESET, GFP_KERNEL);
 	if (IS_ERR(se_cmd->se_tmr_req))
 		goto release;
 	/*
@@ -388,7 +397,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
 		SUCCESS : FAILED;
 release:
 	if (se_cmd)
-		transport_generic_free_cmd(se_cmd, 1, 0);
+		transport_generic_free_cmd(se_cmd, 1);
 	else
 		kmem_cache_free(tcm_loop_cmd_cache, tl_cmd);
 	kfree(tl_tmr);
@@ -1245,6 +1254,9 @@ void tcm_loop_drop_naa_tpg(
 	 */
 	core_tpg_deregister(se_tpg);
 
+	tl_tpg->tl_hba = NULL;
+	tl_tpg->tl_tpgt = 0;
+
 	pr_debug("TCM_Loop_ConfigFS: Deallocated Emulated %s"
 		" Target Port %s,t,0x%04x\n", tcm_loop_dump_proto_id(tl_hba),
 		config_item_name(&wwn->wwn_group.cg_item), tpgt);

+ 20 - 1
drivers/target/target_core_alua.c

@@ -24,7 +24,6 @@
  *
  ******************************************************************************/
 
-#include <linux/version.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/configfs.h>
@@ -68,12 +67,32 @@ int core_emulate_report_target_port_groups(struct se_cmd *cmd)
 	unsigned char *buf;
 	u32 rd_len = 0, off = 4; /* Skip over RESERVED area to first
 				    Target port group descriptor */
+	/*
+	 * Need at least 4 bytes of response data or else we can't
+	 * even fit the return data length.
+	 */
+	if (cmd->data_length < 4) {
+		pr_warn("REPORT TARGET PORT GROUPS allocation length %u"
+			" too small\n", cmd->data_length);
+		return -EINVAL;
+	}
 
 	buf = transport_kmap_first_data_page(cmd);
 
 	spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
 	list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list,
 			tg_pt_gp_list) {
+		/*
+		 * Check if the Target port group and Target port descriptor list
+		 * based on tg_pt_gp_members count will fit into the response payload.
+		 * Otherwise, bump rd_len to let the initiator know we have exceeded
+		 * the allocation length and the response is truncated.
+		 */
+		if ((off + 8 + (tg_pt_gp->tg_pt_gp_members * 4)) >
+		     cmd->data_length) {
+			rd_len += 8 + (tg_pt_gp->tg_pt_gp_members * 4);
+			continue;
+		}
 		/*
 		 * PREF: Preferred target port bit, determine if this
 		 * bit should be set for port group.

+ 64 - 15
drivers/target/target_core_cdb.c

@@ -24,7 +24,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/ctype.h>
+#include <linux/module.h>
 #include <asm/unaligned.h>
 #include <scsi/scsi.h>
 
@@ -156,11 +156,12 @@ target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
 }
 
 static void
-target_parse_naa_6h_vendor_specific(struct se_device *dev, unsigned char *buf_off)
+target_parse_naa_6h_vendor_specific(struct se_device *dev, unsigned char *buf)
 {
 	unsigned char *p = &dev->se_sub_dev->t10_wwn.unit_serial[0];
-	unsigned char *buf = buf_off;
-	int cnt = 0, next = 1;
+	int cnt;
+	bool next = true;
+
 	/*
 	 * Generate up to 36 bits of VENDOR SPECIFIC IDENTIFIER starting on
 	 * byte 3 bit 3-0 for NAA IEEE Registered Extended DESIGNATOR field
@@ -169,19 +170,18 @@ target_parse_naa_6h_vendor_specific(struct se_device *dev, unsigned char *buf_of
 	 * NUMBER set via vpd_unit_serial in target_core_configfs.c to ensure
 	 * per device uniqeness.
 	 */
-	while (*p != '\0') {
-		if (cnt >= 13)
-			break;
-		if (!isxdigit(*p)) {
-			p++;
+	for (cnt = 0; *p && cnt < 13; p++) {
+		int val = hex_to_bin(*p);
+
+		if (val < 0)
 			continue;
-		}
-		if (next != 0) {
-			buf[cnt++] |= hex_to_bin(*p++);
-			next = 0;
+
+		if (next) {
+			next = false;
+			buf[cnt++] |= val;
 		} else {
-			buf[cnt] = hex_to_bin(*p++) << 4;
-			next = 1;
+			next = true;
+			buf[cnt] = val << 4;
 		}
 	}
 }
@@ -1266,3 +1266,52 @@ transport_emulate_control_cdb(struct se_task *task)
 
 	return PYX_TRANSPORT_SENT_TO_TRANSPORT;
 }
+
+/*
+ * Write a CDB into @cdb that is based on the one the intiator sent us,
+ * but updated to only cover the sectors that the current task handles.
+ */
+void target_get_task_cdb(struct se_task *task, unsigned char *cdb)
+{
+	struct se_cmd *cmd = task->task_se_cmd;
+	unsigned int cdb_len = scsi_command_size(cmd->t_task_cdb);
+
+	memcpy(cdb, cmd->t_task_cdb, cdb_len);
+	if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
+		unsigned long long lba = task->task_lba;
+		u32 sectors = task->task_sectors;
+
+		switch (cdb_len) {
+		case 6:
+			/* 21-bit LBA and 8-bit sectors */
+			cdb[1] = (lba >> 16) & 0x1f;
+			cdb[2] = (lba >> 8) & 0xff;
+			cdb[3] = lba & 0xff;
+			cdb[4] = sectors & 0xff;
+			break;
+		case 10:
+			/* 32-bit LBA and 16-bit sectors */
+			put_unaligned_be32(lba, &cdb[2]);
+			put_unaligned_be16(sectors, &cdb[7]);
+			break;
+		case 12:
+			/* 32-bit LBA and 32-bit sectors */
+			put_unaligned_be32(lba, &cdb[2]);
+			put_unaligned_be32(sectors, &cdb[6]);
+			break;
+		case 16:
+			/* 64-bit LBA and 32-bit sectors */
+			put_unaligned_be64(lba, &cdb[2]);
+			put_unaligned_be32(sectors, &cdb[10]);
+			break;
+		case 32:
+			/* 64-bit LBA and 32-bit sectors, extended CDB */
+			put_unaligned_be64(lba, &cdb[12]);
+			put_unaligned_be32(sectors, &cdb[28]);
+			break;
+		default:
+			BUG();
+		}
+	}
+}
+EXPORT_SYMBOL(target_get_task_cdb);

+ 1 - 15
drivers/target/target_core_configfs.c

@@ -23,7 +23,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/version.h>
 #include <generated/utsrelease.h>
 #include <linux/utsname.h>
 #include <linux/init.h>
@@ -132,14 +131,6 @@ static struct config_group *target_core_register_fabric(
 
 	pr_debug("Target_Core_ConfigFS: REGISTER -> group: %p name:"
 			" %s\n", group, name);
-	/*
-	 * Ensure that TCM subsystem plugins are loaded at this point for
-	 * using the RAMDISK_DR virtual LUN 0 and all other struct se_port
-	 * LUN symlinks.
-	 */
-	if (transport_subsystem_check_init() < 0)
-		return ERR_PTR(-EINVAL);
-
 	/*
 	 * Below are some hardcoded request_module() calls to automatically
 	 * local fabric modules when the following is called:
@@ -725,9 +716,6 @@ SE_DEV_ATTR_RO(hw_queue_depth);
 DEF_DEV_ATTRIB(queue_depth);
 SE_DEV_ATTR(queue_depth, S_IRUGO | S_IWUSR);
 
-DEF_DEV_ATTRIB(task_timeout);
-SE_DEV_ATTR(task_timeout, S_IRUGO | S_IWUSR);
-
 DEF_DEV_ATTRIB(max_unmap_lba_count);
 SE_DEV_ATTR(max_unmap_lba_count, S_IRUGO | S_IWUSR);
 
@@ -761,7 +749,6 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = {
 	&target_core_dev_attrib_optimal_sectors.attr,
 	&target_core_dev_attrib_hw_queue_depth.attr,
 	&target_core_dev_attrib_queue_depth.attr,
-	&target_core_dev_attrib_task_timeout.attr,
 	&target_core_dev_attrib_max_unmap_lba_count.attr,
 	&target_core_dev_attrib_max_unmap_block_desc_count.attr,
 	&target_core_dev_attrib_unmap_granularity.attr,
@@ -3080,8 +3067,7 @@ static struct config_group *target_core_call_addhbatotarget(
 	/*
 	 * Load up TCM subsystem plugins if they have not already been loaded.
 	 */
-	if (transport_subsystem_check_init() < 0)
-		return ERR_PTR(-EINVAL);
+	transport_subsystem_check_init();
 
 	hba = core_alloc_hba(se_plugin_str, plugin_dep_id, 0);
 	if (IS_ERR(hba))

+ 15 - 55
drivers/target/target_core_device.c

@@ -914,21 +914,6 @@ void se_dev_set_default_attribs(
 	dev->se_sub_dev->se_dev_attrib.queue_depth = dev_limits->queue_depth;
 }
 
-int se_dev_set_task_timeout(struct se_device *dev, u32 task_timeout)
-{
-	if (task_timeout > DA_TASK_TIMEOUT_MAX) {
-		pr_err("dev[%p]: Passed task_timeout: %u larger then"
-			" DA_TASK_TIMEOUT_MAX\n", dev, task_timeout);
-		return -EINVAL;
-	} else {
-		dev->se_sub_dev->se_dev_attrib.task_timeout = task_timeout;
-		pr_debug("dev[%p]: Set SE Device task_timeout: %u\n",
-			dev, task_timeout);
-	}
-
-	return 0;
-}
-
 int se_dev_set_max_unmap_lba_count(
 	struct se_device *dev,
 	u32 max_unmap_lba_count)
@@ -972,36 +957,24 @@ int se_dev_set_unmap_granularity_alignment(
 
 int se_dev_set_emulate_dpo(struct se_device *dev, int flag)
 {
-	if ((flag != 0) && (flag != 1)) {
+	if (flag != 0 && flag != 1) {
 		pr_err("Illegal value %d\n", flag);
 		return -EINVAL;
 	}
-	if (dev->transport->dpo_emulated == NULL) {
-		pr_err("dev->transport->dpo_emulated is NULL\n");
-		return -EINVAL;
-	}
-	if (dev->transport->dpo_emulated(dev) == 0) {
-		pr_err("dev->transport->dpo_emulated not supported\n");
-		return -EINVAL;
-	}
-	dev->se_sub_dev->se_dev_attrib.emulate_dpo = flag;
-	pr_debug("dev[%p]: SE Device Page Out (DPO) Emulation"
-			" bit: %d\n", dev, dev->se_sub_dev->se_dev_attrib.emulate_dpo);
-	return 0;
+
+	pr_err("dpo_emulated not supported\n");
+	return -EINVAL;
 }
 
 int se_dev_set_emulate_fua_write(struct se_device *dev, int flag)
 {
-	if ((flag != 0) && (flag != 1)) {
+	if (flag != 0 && flag != 1) {
 		pr_err("Illegal value %d\n", flag);
 		return -EINVAL;
 	}
-	if (dev->transport->fua_write_emulated == NULL) {
-		pr_err("dev->transport->fua_write_emulated is NULL\n");
-		return -EINVAL;
-	}
-	if (dev->transport->fua_write_emulated(dev) == 0) {
-		pr_err("dev->transport->fua_write_emulated not supported\n");
+
+	if (dev->transport->fua_write_emulated == 0) {
+		pr_err("fua_write_emulated not supported\n");
 		return -EINVAL;
 	}
 	dev->se_sub_dev->se_dev_attrib.emulate_fua_write = flag;
@@ -1012,36 +985,23 @@ int se_dev_set_emulate_fua_write(struct se_device *dev, int flag)
 
 int se_dev_set_emulate_fua_read(struct se_device *dev, int flag)
 {
-	if ((flag != 0) && (flag != 1)) {
+	if (flag != 0 && flag != 1) {
 		pr_err("Illegal value %d\n", flag);
 		return -EINVAL;
 	}
-	if (dev->transport->fua_read_emulated == NULL) {
-		pr_err("dev->transport->fua_read_emulated is NULL\n");
-		return -EINVAL;
-	}
-	if (dev->transport->fua_read_emulated(dev) == 0) {
-		pr_err("dev->transport->fua_read_emulated not supported\n");
-		return -EINVAL;
-	}
-	dev->se_sub_dev->se_dev_attrib.emulate_fua_read = flag;
-	pr_debug("dev[%p]: SE Device Forced Unit Access READs: %d\n",
-			dev, dev->se_sub_dev->se_dev_attrib.emulate_fua_read);
-	return 0;
+
+	pr_err("ua read emulated not supported\n");
+	return -EINVAL;
 }
 
 int se_dev_set_emulate_write_cache(struct se_device *dev, int flag)
 {
-	if ((flag != 0) && (flag != 1)) {
+	if (flag != 0 && flag != 1) {
 		pr_err("Illegal value %d\n", flag);
 		return -EINVAL;
 	}
-	if (dev->transport->write_cache_emulated == NULL) {
-		pr_err("dev->transport->write_cache_emulated is NULL\n");
-		return -EINVAL;
-	}
-	if (dev->transport->write_cache_emulated(dev) == 0) {
-		pr_err("dev->transport->write_cache_emulated not supported\n");
+	if (dev->transport->write_cache_emulated == 0) {
+		pr_err("write_cache_emulated not supported\n");
 		return -EINVAL;
 	}
 	dev->se_sub_dev->se_dev_attrib.emulate_write_cache = flag;

+ 0 - 1
drivers/target/target_core_fabric_configfs.c

@@ -22,7 +22,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/version.h>
 #include <generated/utsrelease.h>
 #include <linux/utsname.h>
 #include <linux/init.h>

+ 8 - 48
drivers/target/target_core_file.c

@@ -26,7 +26,6 @@
  *
  ******************************************************************************/
 
-#include <linux/version.h>
 #include <linux/string.h>
 #include <linux/parser.h>
 #include <linux/timer.h>
@@ -273,13 +272,14 @@ fd_alloc_task(unsigned char *cdb)
 static int fd_do_readv(struct se_task *task)
 {
 	struct fd_request *req = FILE_REQ(task);
-	struct fd_dev *dev = req->fd_task.se_dev->dev_ptr;
+	struct se_device *se_dev = req->fd_task.task_se_cmd->se_dev;
+	struct fd_dev *dev = se_dev->dev_ptr;
 	struct file *fd = dev->fd_file;
 	struct scatterlist *sg = task->task_sg;
 	struct iovec *iov;
 	mm_segment_t old_fs;
 	loff_t pos = (task->task_lba *
-		      task->se_dev->se_sub_dev->se_dev_attrib.block_size);
+		      se_dev->se_sub_dev->se_dev_attrib.block_size);
 	int ret = 0, i;
 
 	iov = kzalloc(sizeof(struct iovec) * task->task_sg_nents, GFP_KERNEL);
@@ -325,13 +325,14 @@ static int fd_do_readv(struct se_task *task)
 static int fd_do_writev(struct se_task *task)
 {
 	struct fd_request *req = FILE_REQ(task);
-	struct fd_dev *dev = req->fd_task.se_dev->dev_ptr;
+	struct se_device *se_dev = req->fd_task.task_se_cmd->se_dev;
+	struct fd_dev *dev = se_dev->dev_ptr;
 	struct file *fd = dev->fd_file;
 	struct scatterlist *sg = task->task_sg;
 	struct iovec *iov;
 	mm_segment_t old_fs;
 	loff_t pos = (task->task_lba *
-		      task->se_dev->se_sub_dev->se_dev_attrib.block_size);
+		      se_dev->se_sub_dev->se_dev_attrib.block_size);
 	int ret, i = 0;
 
 	iov = kzalloc(sizeof(struct iovec) * task->task_sg_nents, GFP_KERNEL);
@@ -398,33 +399,6 @@ static void fd_emulate_sync_cache(struct se_task *task)
 		transport_complete_sync_cache(cmd, ret == 0);
 }
 
-/*
- * Tell TCM Core that we are capable of WriteCache emulation for
- * an underlying struct se_device.
- */
-static int fd_emulated_write_cache(struct se_device *dev)
-{
-	return 1;
-}
-
-static int fd_emulated_dpo(struct se_device *dev)
-{
-	return 0;
-}
-/*
- * Tell TCM Core that we will be emulating Forced Unit Access (FUA) for WRITEs
- * for TYPE_DISK.
- */
-static int fd_emulated_fua_write(struct se_device *dev)
-{
-	return 1;
-}
-
-static int fd_emulated_fua_read(struct se_device *dev)
-{
-	return 0;
-}
-
 /*
  * WRITE Force Unit Access (FUA) emulation on a per struct se_task
  * LBA range basis..
@@ -608,17 +582,6 @@ static ssize_t fd_show_configfs_dev_params(
 	return bl;
 }
 
-/*	fd_get_cdb(): (Part of se_subsystem_api_t template)
- *
- *
- */
-static unsigned char *fd_get_cdb(struct se_task *task)
-{
-	struct fd_request *req = FILE_REQ(task);
-
-	return req->fd_scsi_cdb;
-}
-
 /*	fd_get_device_rev(): (Part of se_subsystem_api_t template)
  *
  *
@@ -650,15 +613,13 @@ static struct se_subsystem_api fileio_template = {
 	.name			= "fileio",
 	.owner			= THIS_MODULE,
 	.transport_type		= TRANSPORT_PLUGIN_VHBA_PDEV,
+	.write_cache_emulated	= 1,
+	.fua_write_emulated	= 1,
 	.attach_hba		= fd_attach_hba,
 	.detach_hba		= fd_detach_hba,
 	.allocate_virtdevice	= fd_allocate_virtdevice,
 	.create_virtdevice	= fd_create_virtdevice,
 	.free_device		= fd_free_device,
-	.dpo_emulated		= fd_emulated_dpo,
-	.fua_write_emulated	= fd_emulated_fua_write,
-	.fua_read_emulated	= fd_emulated_fua_read,
-	.write_cache_emulated	= fd_emulated_write_cache,
 	.alloc_task		= fd_alloc_task,
 	.do_task		= fd_do_task,
 	.do_sync_cache		= fd_emulate_sync_cache,
@@ -666,7 +627,6 @@ static struct se_subsystem_api fileio_template = {
 	.check_configfs_dev_params = fd_check_configfs_dev_params,
 	.set_configfs_dev_params = fd_set_configfs_dev_params,
 	.show_configfs_dev_params = fd_show_configfs_dev_params,
-	.get_cdb		= fd_get_cdb,
 	.get_device_rev		= fd_get_device_rev,
 	.get_device_type	= fd_get_device_type,
 	.get_blocks		= fd_get_blocks,

+ 1 - 3
drivers/target/target_core_file.h

@@ -14,9 +14,7 @@
 
 struct fd_request {
 	struct se_task	fd_task;
-	/* SCSI CDB from iSCSI Command PDU */
-	unsigned char	fd_scsi_cdb[TCM_MAX_COMMAND_SIZE];
-} ____cacheline_aligned;
+};
 
 #define FBDF_HAS_PATH		0x01
 #define FBDF_HAS_SIZE		0x02

+ 83 - 191
drivers/target/target_core_iblock.c

@@ -27,7 +27,6 @@
  *
  ******************************************************************************/
 
-#include <linux/version.h>
 #include <linux/string.h>
 #include <linux/parser.h>
 #include <linux/timer.h>
@@ -314,104 +313,42 @@ static unsigned long long iblock_emulate_read_cap_with_block_size(
 	return blocks_long;
 }
 
+static void iblock_end_io_flush(struct bio *bio, int err)
+{
+	struct se_cmd *cmd = bio->bi_private;
+
+	if (err)
+		pr_err("IBLOCK: cache flush failed: %d\n", err);
+
+	if (cmd)
+		transport_complete_sync_cache(cmd, err == 0);
+	bio_put(bio);
+}
+
 /*
- * Emulate SYCHRONIZE_CACHE_*
+ * Implement SYCHRONIZE CACHE.  Note that we can't handle lba ranges and must
+ * always flush the whole cache.
  */
 static void iblock_emulate_sync_cache(struct se_task *task)
 {
 	struct se_cmd *cmd = task->task_se_cmd;
 	struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr;
 	int immed = (cmd->t_task_cdb[1] & 0x2);
-	sector_t error_sector;
-	int ret;
+	struct bio *bio;
 
 	/*
 	 * If the Immediate bit is set, queue up the GOOD response
-	 * for this SYNCHRONIZE_CACHE op
+	 * for this SYNCHRONIZE_CACHE op.
 	 */
 	if (immed)
 		transport_complete_sync_cache(cmd, 1);
 
-	/*
-	 * blkdev_issue_flush() does not support a specifying a range, so
-	 * we have to flush the entire cache.
-	 */
-	ret = blkdev_issue_flush(ib_dev->ibd_bd, GFP_KERNEL, &error_sector);
-	if (ret != 0) {
-		pr_err("IBLOCK: block_issue_flush() failed: %d "
-			" error_sector: %llu\n", ret,
-			(unsigned long long)error_sector);
-	}
-
+	bio = bio_alloc(GFP_KERNEL, 0);
+	bio->bi_end_io = iblock_end_io_flush;
+	bio->bi_bdev = ib_dev->ibd_bd;
 	if (!immed)
-		transport_complete_sync_cache(cmd, ret == 0);
-}
-
-/*
- * Tell TCM Core that we are capable of WriteCache emulation for
- * an underlying struct se_device.
- */
-static int iblock_emulated_write_cache(struct se_device *dev)
-{
-	return 1;
-}
-
-static int iblock_emulated_dpo(struct se_device *dev)
-{
-	return 0;
-}
-
-/*
- * Tell TCM Core that we will be emulating Forced Unit Access (FUA) for WRITEs
- * for TYPE_DISK.
- */
-static int iblock_emulated_fua_write(struct se_device *dev)
-{
-	return 1;
-}
-
-static int iblock_emulated_fua_read(struct se_device *dev)
-{
-	return 0;
-}
-
-static int iblock_do_task(struct se_task *task)
-{
-	struct se_device *dev = task->task_se_cmd->se_dev;
-	struct iblock_req *req = IBLOCK_REQ(task);
-	struct bio *bio = req->ib_bio, *nbio = NULL;
-	struct blk_plug plug;
-	int rw;
-
-	if (task->task_data_direction == DMA_TO_DEVICE) {
-		/*
-		 * Force data to disk if we pretend to not have a volatile
-		 * write cache, or the initiator set the Force Unit Access bit.
-		 */
-		if (dev->se_sub_dev->se_dev_attrib.emulate_write_cache == 0 ||
-		    (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0 &&
-		     task->task_se_cmd->t_tasks_fua))
-			rw = WRITE_FUA;
-		else
-			rw = WRITE;
-	} else {
-		rw = READ;
-	}
-
-	blk_start_plug(&plug);
-	while (bio) {
-		nbio = bio->bi_next;
-		bio->bi_next = NULL;
-		pr_debug("Calling submit_bio() task: %p bio: %p"
-			" bio->bi_sector: %llu\n", task, bio,
-			 (unsigned long long)bio->bi_sector);
-
-		submit_bio(rw, bio);
-		bio = nbio;
-	}
-	blk_finish_plug(&plug);
-
-	return PYX_TRANSPORT_SENT_TO_TRANSPORT;
+		bio->bi_private = cmd;
+	submit_bio(WRITE_FLUSH, bio);
 }
 
 static int iblock_do_discard(struct se_device *dev, sector_t lba, u32 range)
@@ -425,20 +362,7 @@ static int iblock_do_discard(struct se_device *dev, sector_t lba, u32 range)
 
 static void iblock_free_task(struct se_task *task)
 {
-	struct iblock_req *req = IBLOCK_REQ(task);
-	struct bio *bio, *hbio = req->ib_bio;
-	/*
-	 * We only release the bio(s) here if iblock_bio_done() has not called
-	 * bio_put() -> iblock_bio_destructor().
-	 */
-	while (hbio != NULL) {
-		bio = hbio;
-		hbio = hbio->bi_next;
-		bio->bi_next = NULL;
-		bio_put(bio);
-	}
-
-	kfree(req);
+	kfree(IBLOCK_REQ(task));
 }
 
 enum {
@@ -552,25 +476,21 @@ static ssize_t iblock_show_configfs_dev_params(
 static void iblock_bio_destructor(struct bio *bio)
 {
 	struct se_task *task = bio->bi_private;
-	struct iblock_dev *ib_dev = task->se_dev->dev_ptr;
+	struct iblock_dev *ib_dev = task->task_se_cmd->se_dev->dev_ptr;
 
 	bio_free(bio, ib_dev->ibd_bio_set);
 }
 
-static struct bio *iblock_get_bio(
-	struct se_task *task,
-	struct iblock_req *ib_req,
-	struct iblock_dev *ib_dev,
-	int *ret,
-	sector_t lba,
-	u32 sg_num)
+static struct bio *
+iblock_get_bio(struct se_task *task, sector_t lba, u32 sg_num)
 {
+	struct iblock_dev *ib_dev = task->task_se_cmd->se_dev->dev_ptr;
+	struct iblock_req *ib_req = IBLOCK_REQ(task);
 	struct bio *bio;
 
 	bio = bio_alloc_bioset(GFP_NOIO, sg_num, ib_dev->ibd_bio_set);
 	if (!bio) {
 		pr_err("Unable to allocate memory for bio\n");
-		*ret = PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
 		return NULL;
 	}
 
@@ -591,17 +511,33 @@ static struct bio *iblock_get_bio(
 	return bio;
 }
 
-static int iblock_map_data_SG(struct se_task *task)
+static int iblock_do_task(struct se_task *task)
 {
 	struct se_cmd *cmd = task->task_se_cmd;
 	struct se_device *dev = cmd->se_dev;
-	struct iblock_dev *ib_dev = task->se_dev->dev_ptr;
-	struct iblock_req *ib_req = IBLOCK_REQ(task);
-	struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
+	struct bio *bio;
+	struct bio_list list;
 	struct scatterlist *sg;
-	int ret = 0;
 	u32 i, sg_num = task->task_sg_nents;
 	sector_t block_lba;
+	struct blk_plug plug;
+	int rw;
+
+	if (task->task_data_direction == DMA_TO_DEVICE) {
+		/*
+		 * Force data to disk if we pretend to not have a volatile
+		 * write cache, or the initiator set the Force Unit Access bit.
+		 */
+		if (dev->se_sub_dev->se_dev_attrib.emulate_write_cache == 0 ||
+		    (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0 &&
+		     task->task_se_cmd->t_tasks_fua))
+			rw = WRITE_FUA;
+		else
+			rw = WRITE;
+	} else {
+		rw = READ;
+	}
+
 	/*
 	 * Do starting conversion up from non 512-byte blocksize with
 	 * struct se_task SCSI blocksize into Linux/Block 512 units for BIO.
@@ -620,68 +556,43 @@ static int iblock_map_data_SG(struct se_task *task)
 		return PYX_TRANSPORT_LU_COMM_FAILURE;
 	}
 
-	bio = iblock_get_bio(task, ib_req, ib_dev, &ret, block_lba, sg_num);
+	bio = iblock_get_bio(task, block_lba, sg_num);
 	if (!bio)
-		return ret;
+		return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
+
+	bio_list_init(&list);
+	bio_list_add(&list, bio);
 
-	ib_req->ib_bio = bio;
-	hbio = tbio = bio;
-	/*
-	 * Use fs/bio.c:bio_add_pages() to setup the bio_vec maplist
-	 * from task->task_sg -> struct scatterlist memory.
-	 */
 	for_each_sg(task->task_sg, sg, task->task_sg_nents, i) {
-		pr_debug("task: %p bio: %p Calling bio_add_page(): page:"
-			" %p len: %u offset: %u\n", task, bio, sg_page(sg),
-				sg->length, sg->offset);
-again:
-		ret = bio_add_page(bio, sg_page(sg), sg->length, sg->offset);
-		if (ret != sg->length) {
-
-			pr_debug("*** Set bio->bi_sector: %llu\n",
-				 (unsigned long long)bio->bi_sector);
-			pr_debug("** task->task_size: %u\n",
-					task->task_size);
-			pr_debug("*** bio->bi_max_vecs: %u\n",
-					bio->bi_max_vecs);
-			pr_debug("*** bio->bi_vcnt: %u\n",
-					bio->bi_vcnt);
-
-			bio = iblock_get_bio(task, ib_req, ib_dev, &ret,
-						block_lba, sg_num);
+		/*
+		 * XXX: if the length the device accepts is shorter than the
+		 *	length of the S/G list entry this will cause and
+		 *	endless loop.  Better hope no driver uses huge pages.
+		 */
+		while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset)
+				!= sg->length) {
+			bio = iblock_get_bio(task, block_lba, sg_num);
 			if (!bio)
 				goto fail;
-
-			tbio = tbio->bi_next = bio;
-			pr_debug("-----------------> Added +1 bio: %p to"
-				" list, Going to again\n", bio);
-			goto again;
+			bio_list_add(&list, bio);
 		}
+
 		/* Always in 512 byte units for Linux/Block */
 		block_lba += sg->length >> IBLOCK_LBA_SHIFT;
 		sg_num--;
-		pr_debug("task: %p bio-add_page() passed!, decremented"
-			" sg_num to %u\n", task, sg_num);
-		pr_debug("task: %p bio_add_page() passed!, increased lba"
-			 " to %llu\n", task, (unsigned long long)block_lba);
-		pr_debug("task: %p bio_add_page() passed!, bio->bi_vcnt:"
-				" %u\n", task, bio->bi_vcnt);
 	}
 
-	return 0;
+	blk_start_plug(&plug);
+	while ((bio = bio_list_pop(&list)))
+		submit_bio(rw, bio);
+	blk_finish_plug(&plug);
+
+	return PYX_TRANSPORT_SENT_TO_TRANSPORT;
+
 fail:
-	while (hbio) {
-		bio = hbio;
-		hbio = hbio->bi_next;
-		bio->bi_next = NULL;
+	while ((bio = bio_list_pop(&list)))
 		bio_put(bio);
-	}
-	return ret;
-}
-
-static unsigned char *iblock_get_cdb(struct se_task *task)
-{
-	return IBLOCK_REQ(task)->ib_scsi_cdb;
+	return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
 }
 
 static u32 iblock_get_device_rev(struct se_device *dev)
@@ -707,6 +618,7 @@ static void iblock_bio_done(struct bio *bio, int err)
 {
 	struct se_task *task = bio->bi_private;
 	struct iblock_req *ibr = IBLOCK_REQ(task);
+
 	/*
 	 * Set -EIO if !BIO_UPTODATE and the passed is still err=0
 	 */
@@ -721,50 +633,31 @@ static void iblock_bio_done(struct bio *bio, int err)
 		 */
 		atomic_inc(&ibr->ib_bio_err_cnt);
 		smp_mb__after_atomic_inc();
-		bio_put(bio);
-		/*
-		 * Wait to complete the task until the last bio as completed.
-		 */
-		if (!atomic_dec_and_test(&ibr->ib_bio_cnt))
-			return;
-
-		ibr->ib_bio = NULL;
-		transport_complete_task(task, 0);
-		return;
 	}
-	pr_debug("done[%p] bio: %p task_lba: %llu bio_lba: %llu err=%d\n",
-		 task, bio, task->task_lba, (unsigned long long)bio->bi_sector, err);
-	/*
-	 * bio_put() will call iblock_bio_destructor() to release the bio back
-	 * to ibr->ib_bio_set.
-	 */
+
 	bio_put(bio);
-	/*
-	 * Wait to complete the task until the last bio as completed.
-	 */
+
 	if (!atomic_dec_and_test(&ibr->ib_bio_cnt))
 		return;
-	/*
-	 * Return GOOD status for task if zero ib_bio_err_cnt exists.
-	 */
-	ibr->ib_bio = NULL;
-	transport_complete_task(task, (!atomic_read(&ibr->ib_bio_err_cnt)));
+
+	pr_debug("done[%p] bio: %p task_lba: %llu bio_lba: %llu err=%d\n",
+		 task, bio, task->task_lba,
+		 (unsigned long long)bio->bi_sector, err);
+
+	transport_complete_task(task, !atomic_read(&ibr->ib_bio_err_cnt));
 }
 
 static struct se_subsystem_api iblock_template = {
 	.name			= "iblock",
 	.owner			= THIS_MODULE,
 	.transport_type		= TRANSPORT_PLUGIN_VHBA_PDEV,
-	.map_data_SG		= iblock_map_data_SG,
+	.write_cache_emulated	= 1,
+	.fua_write_emulated	= 1,
 	.attach_hba		= iblock_attach_hba,
 	.detach_hba		= iblock_detach_hba,
 	.allocate_virtdevice	= iblock_allocate_virtdevice,
 	.create_virtdevice	= iblock_create_virtdevice,
 	.free_device		= iblock_free_device,
-	.dpo_emulated		= iblock_emulated_dpo,
-	.fua_write_emulated	= iblock_emulated_fua_write,
-	.fua_read_emulated	= iblock_emulated_fua_read,
-	.write_cache_emulated	= iblock_emulated_write_cache,
 	.alloc_task		= iblock_alloc_task,
 	.do_task		= iblock_do_task,
 	.do_discard		= iblock_do_discard,
@@ -773,7 +666,6 @@ static struct se_subsystem_api iblock_template = {
 	.check_configfs_dev_params = iblock_check_configfs_dev_params,
 	.set_configfs_dev_params = iblock_set_configfs_dev_params,
 	.show_configfs_dev_params = iblock_show_configfs_dev_params,
-	.get_cdb		= iblock_get_cdb,
 	.get_device_rev		= iblock_get_device_rev,
 	.get_device_type	= iblock_get_device_type,
 	.get_blocks		= iblock_get_blocks,

+ 0 - 2
drivers/target/target_core_iblock.h

@@ -8,10 +8,8 @@
 
 struct iblock_req {
 	struct se_task ib_task;
-	unsigned char ib_scsi_cdb[TCM_MAX_COMMAND_SIZE];
 	atomic_t ib_bio_cnt;
 	atomic_t ib_bio_err_cnt;
-	struct bio *ib_bio;
 } ____cacheline_aligned;
 
 #define IBDF_HAS_UDEV_PATH		0x01

+ 0 - 1
drivers/target/target_core_pr.c

@@ -25,7 +25,6 @@
  *
  ******************************************************************************/
 
-#include <linux/version.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>

+ 68 - 193
drivers/target/target_core_pscsi.c

@@ -26,7 +26,6 @@
  *
  ******************************************************************************/
 
-#include <linux/version.h>
 #include <linux/string.h>
 #include <linux/parser.h>
 #include <linux/timer.h>
@@ -567,7 +566,7 @@ static struct se_device *pscsi_create_virtdevice(
 			if (IS_ERR(sh)) {
 				pr_err("pSCSI: Unable to locate"
 					" pdv_host_id: %d\n", pdv->pdv_host_id);
-				return (struct se_device *) sh;
+				return ERR_CAST(sh);
 			}
 		}
 	} else {
@@ -677,7 +676,7 @@ static inline struct pscsi_plugin_task *PSCSI_TASK(struct se_task *task)
  */
 static int pscsi_transport_complete(struct se_task *task)
 {
-	struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr;
+	struct pscsi_dev_virt *pdv = task->task_se_cmd->se_dev->dev_ptr;
 	struct scsi_device *sd = pdv->pdv_sd;
 	int result;
 	struct pscsi_plugin_task *pt = PSCSI_TASK(task);
@@ -777,95 +776,6 @@ pscsi_alloc_task(unsigned char *cdb)
 	return &pt->pscsi_task;
 }
 
-static inline void pscsi_blk_init_request(
-	struct se_task *task,
-	struct pscsi_plugin_task *pt,
-	struct request *req,
-	int bidi_read)
-{
-	/*
-	 * Defined as "scsi command" in include/linux/blkdev.h.
-	 */
-	req->cmd_type = REQ_TYPE_BLOCK_PC;
-	/*
-	 * For the extra BIDI-COMMAND READ struct request we do not
-	 * need to setup the remaining structure members
-	 */
-	if (bidi_read)
-		return;
-	/*
-	 * Setup the done function pointer for struct request,
-	 * also set the end_io_data pointer.to struct se_task.
-	 */
-	req->end_io = pscsi_req_done;
-	req->end_io_data = task;
-	/*
-	 * Load the referenced struct se_task's SCSI CDB into
-	 * include/linux/blkdev.h:struct request->cmd
-	 */
-	req->cmd_len = scsi_command_size(pt->pscsi_cdb);
-	req->cmd = &pt->pscsi_cdb[0];
-	/*
-	 * Setup pointer for outgoing sense data.
-	 */
-	req->sense = &pt->pscsi_sense[0];
-	req->sense_len = 0;
-}
-
-/*
- * Used for pSCSI data payloads for all *NON* SCF_SCSI_DATA_SG_IO_CDB
-*/
-static int pscsi_blk_get_request(struct se_task *task)
-{
-	struct pscsi_plugin_task *pt = PSCSI_TASK(task);
-	struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr;
-
-	pt->pscsi_req = blk_get_request(pdv->pdv_sd->request_queue,
-			(task->task_data_direction == DMA_TO_DEVICE),
-			GFP_KERNEL);
-	if (!pt->pscsi_req || IS_ERR(pt->pscsi_req)) {
-		pr_err("PSCSI: blk_get_request() failed: %ld\n",
-				IS_ERR(pt->pscsi_req));
-		return PYX_TRANSPORT_LU_COMM_FAILURE;
-	}
-	/*
-	 * Setup the newly allocated struct request for REQ_TYPE_BLOCK_PC,
-	 * and setup rq callback, CDB and sense.
-	 */
-	pscsi_blk_init_request(task, pt, pt->pscsi_req, 0);
-	return 0;
-}
-
-/*      pscsi_do_task(): (Part of se_subsystem_api_t template)
- *
- *
- */
-static int pscsi_do_task(struct se_task *task)
-{
-	struct pscsi_plugin_task *pt = PSCSI_TASK(task);
-	struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr;
-	/*
-	 * Set the struct request->timeout value based on peripheral
-	 * device type from SCSI.
-	 */
-	if (pdv->pdv_sd->type == TYPE_DISK)
-		pt->pscsi_req->timeout = PS_TIMEOUT_DISK;
-	else
-		pt->pscsi_req->timeout = PS_TIMEOUT_OTHER;
-
-	pt->pscsi_req->retries = PS_RETRY;
-	/*
-	 * Queue the struct request into the struct scsi_device->request_queue.
-	 * Also check for HEAD_OF_QUEUE SAM TASK attr from received se_cmd
-	 * descriptor
-	 */
-	blk_execute_rq_nowait(pdv->pdv_sd->request_queue, NULL, pt->pscsi_req,
-			(task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG),
-			pscsi_req_done);
-
-	return PYX_TRANSPORT_SENT_TO_TRANSPORT;
-}
-
 static void pscsi_free_task(struct se_task *task)
 {
 	struct pscsi_plugin_task *pt = PSCSI_TASK(task);
@@ -1049,15 +959,12 @@ static inline struct bio *pscsi_get_bio(int sg_num)
 	return bio;
 }
 
-static int __pscsi_map_SG(
-	struct se_task *task,
-	struct scatterlist *task_sg,
-	u32 task_sg_num,
-	int bidi_read)
+static int pscsi_map_sg(struct se_task *task, struct scatterlist *task_sg,
+		struct bio **hbio)
 {
-	struct pscsi_plugin_task *pt = PSCSI_TASK(task);
-	struct pscsi_dev_virt *pdv = task->se_dev->dev_ptr;
-	struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
+	struct pscsi_dev_virt *pdv = task->task_se_cmd->se_dev->dev_ptr;
+	u32 task_sg_num = task->task_sg_nents;
+	struct bio *bio = NULL, *tbio = NULL;
 	struct page *page;
 	struct scatterlist *sg;
 	u32 data_len = task->task_size, i, len, bytes, off;
@@ -1066,19 +973,8 @@ static int __pscsi_map_SG(
 	int nr_vecs = 0, rc, ret = PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
 	int rw = (task->task_data_direction == DMA_TO_DEVICE);
 
-	if (!task->task_size)
-		return 0;
-	/*
-	 * For SCF_SCSI_DATA_SG_IO_CDB, Use fs/bio.c:bio_add_page() to setup
-	 * the bio_vec maplist from task->task_sg ->
-	 * struct scatterlist memory.  The struct se_task->task_sg[] currently needs
-	 * to be attached to struct bios for submission to Linux/SCSI using
-	 * struct request to struct scsi_device->request_queue.
-	 *
-	 * Note that this will be changing post v2.6.28 as Target_Core_Mod/pSCSI
-	 * is ported to upstream SCSI passthrough functionality that accepts
-	 * struct scatterlist->page_link or struct page as a paraemeter.
-	 */
+	*hbio = NULL;
+
 	pr_debug("PSCSI: nr_pages: %d\n", nr_pages);
 
 	for_each_sg(task_sg, sg, task_sg_num, i) {
@@ -1115,8 +1011,8 @@ static int __pscsi_map_SG(
 				 * bios need to be added to complete a given
 				 * struct se_task
 				 */
-				if (!hbio)
-					hbio = tbio = bio;
+				if (!*hbio)
+					*hbio = tbio = bio;
 				else
 					tbio = tbio->bi_next = bio;
 			}
@@ -1152,92 +1048,82 @@ static int __pscsi_map_SG(
 			off = 0;
 		}
 	}
-	/*
-	 * Setup the primary pt->pscsi_req used for non BIDI and BIDI-COMMAND
-	 * primary SCSI WRITE poayload mapped for struct se_task->task_sg[]
-	 */
-	if (!bidi_read) {
-		/*
-		 * Starting with v2.6.31, call blk_make_request() passing in *hbio to
-		 * allocate the pSCSI task a struct request.
-		 */
-		pt->pscsi_req = blk_make_request(pdv->pdv_sd->request_queue,
-					hbio, GFP_KERNEL);
-		if (!pt->pscsi_req) {
-			pr_err("pSCSI: blk_make_request() failed\n");
-			goto fail;
-		}
-		/*
-		 * Setup the newly allocated struct request for REQ_TYPE_BLOCK_PC,
-		 * and setup rq callback, CDB and sense.
-		 */
-		pscsi_blk_init_request(task, pt, pt->pscsi_req, 0);
-
-		return task->task_sg_nents;
-	}
-	/*
-	 * Setup the secondary pt->pscsi_req->next_rq used for the extra BIDI-COMMAND
-	 * SCSI READ paylaod mapped for struct se_task->task_sg_bidi[]
-	 */
-	pt->pscsi_req->next_rq = blk_make_request(pdv->pdv_sd->request_queue,
-					hbio, GFP_KERNEL);
-	if (!pt->pscsi_req->next_rq) {
-		pr_err("pSCSI: blk_make_request() failed for BIDI\n");
-		goto fail;
-	}
-	pscsi_blk_init_request(task, pt, pt->pscsi_req->next_rq, 1);
 
 	return task->task_sg_nents;
 fail:
-	while (hbio) {
-		bio = hbio;
-		hbio = hbio->bi_next;
+	while (*hbio) {
+		bio = *hbio;
+		*hbio = (*hbio)->bi_next;
 		bio->bi_next = NULL;
-		bio_endio(bio, 0);
+		bio_endio(bio, 0);	/* XXX: should be error */
 	}
 	return ret;
 }
 
-/*
- * pSCSI maps both ->map_control_SG() and ->map_data_SG() to a single call.
- */
-static int pscsi_map_SG(struct se_task *task)
+static int pscsi_do_task(struct se_task *task)
 {
+	struct pscsi_dev_virt *pdv = task->task_se_cmd->se_dev->dev_ptr;
+	struct pscsi_plugin_task *pt = PSCSI_TASK(task);
+	struct request *req;
+	struct bio *hbio;
 	int ret;
 
-	/*
-	 * Setup the main struct request for the task->task_sg[] payload
-	 */
+	target_get_task_cdb(task, pt->pscsi_cdb);
+
+	if (task->task_se_cmd->se_cmd_flags & SCF_SCSI_NON_DATA_CDB) {
+		req = blk_get_request(pdv->pdv_sd->request_queue,
+				(task->task_data_direction == DMA_TO_DEVICE),
+				GFP_KERNEL);
+		if (!req || IS_ERR(req)) {
+			pr_err("PSCSI: blk_get_request() failed: %ld\n",
+					req ? IS_ERR(req) : -ENOMEM);
+			return PYX_TRANSPORT_LU_COMM_FAILURE;
+		}
+	} else {
+		BUG_ON(!task->task_size);
 
-	ret = __pscsi_map_SG(task, task->task_sg, task->task_sg_nents, 0);
-	if (ret >= 0 && task->task_sg_bidi) {
 		/*
-		 * If present, set up the extra BIDI-COMMAND SCSI READ
-		 * struct request and payload.
+		 * Setup the main struct request for the task->task_sg[] payload
 		 */
-		ret = __pscsi_map_SG(task, task->task_sg_bidi,
-					task->task_sg_nents, 1);
+		ret = pscsi_map_sg(task, task->task_sg, &hbio);
+		if (ret < 0)
+			return PYX_TRANSPORT_LU_COMM_FAILURE;
+
+		req = blk_make_request(pdv->pdv_sd->request_queue, hbio,
+				       GFP_KERNEL);
+		if (!req) {
+			pr_err("pSCSI: blk_make_request() failed\n");
+			goto fail;
+		}
 	}
 
-	if (ret < 0)
-		return PYX_TRANSPORT_LU_COMM_FAILURE;
-	return 0;
-}
+	req->cmd_type = REQ_TYPE_BLOCK_PC;
+	req->end_io = pscsi_req_done;
+	req->end_io_data = task;
+	req->cmd_len = scsi_command_size(pt->pscsi_cdb);
+	req->cmd = &pt->pscsi_cdb[0];
+	req->sense = &pt->pscsi_sense[0];
+	req->sense_len = 0;
+	if (pdv->pdv_sd->type == TYPE_DISK)
+		req->timeout = PS_TIMEOUT_DISK;
+	else
+		req->timeout = PS_TIMEOUT_OTHER;
+	req->retries = PS_RETRY;
 
-static int pscsi_CDB_none(struct se_task *task)
-{
-	return pscsi_blk_get_request(task);
-}
+	blk_execute_rq_nowait(pdv->pdv_sd->request_queue, NULL, req,
+			(task->task_se_cmd->sam_task_attr == MSG_HEAD_TAG),
+			pscsi_req_done);
 
-/*	pscsi_get_cdb():
- *
- *
- */
-static unsigned char *pscsi_get_cdb(struct se_task *task)
-{
-	struct pscsi_plugin_task *pt = PSCSI_TASK(task);
+	return PYX_TRANSPORT_SENT_TO_TRANSPORT;
 
-	return pt->pscsi_cdb;
+fail:
+	while (hbio) {
+		struct bio *bio = hbio;
+		hbio = hbio->bi_next;
+		bio->bi_next = NULL;
+		bio_endio(bio, 0);	/* XXX: should be error */
+	}
+	return PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES;
 }
 
 /*	pscsi_get_sense_buffer():
@@ -1328,23 +1214,13 @@ static void pscsi_req_done(struct request *req, int uptodate)
 	pt->pscsi_resid = req->resid_len;
 
 	pscsi_process_SAM_status(task, pt);
-	/*
-	 * Release BIDI-READ if present
-	 */
-	if (req->next_rq != NULL)
-		__blk_put_request(req->q, req->next_rq);
-
 	__blk_put_request(req->q, req);
-	pt->pscsi_req = NULL;
 }
 
 static struct se_subsystem_api pscsi_template = {
 	.name			= "pscsi",
 	.owner			= THIS_MODULE,
 	.transport_type		= TRANSPORT_PLUGIN_PHBA_PDEV,
-	.cdb_none		= pscsi_CDB_none,
-	.map_control_SG		= pscsi_map_SG,
-	.map_data_SG		= pscsi_map_SG,
 	.attach_hba		= pscsi_attach_hba,
 	.detach_hba		= pscsi_detach_hba,
 	.pmode_enable_hba	= pscsi_pmode_enable_hba,
@@ -1358,7 +1234,6 @@ static struct se_subsystem_api pscsi_template = {
 	.check_configfs_dev_params = pscsi_check_configfs_dev_params,
 	.set_configfs_dev_params = pscsi_set_configfs_dev_params,
 	.show_configfs_dev_params = pscsi_show_configfs_dev_params,
-	.get_cdb		= pscsi_get_cdb,
 	.get_sense_buffer	= pscsi_get_sense_buffer,
 	.get_device_rev		= pscsi_get_device_rev,
 	.get_device_type	= pscsi_get_device_type,

+ 0 - 1
drivers/target/target_core_pscsi.h

@@ -27,7 +27,6 @@ struct pscsi_plugin_task {
 	int	pscsi_direction;
 	int	pscsi_result;
 	u32	pscsi_resid;
-	struct request *pscsi_req;
 	unsigned char pscsi_cdb[0];
 } ____cacheline_aligned;
 

+ 3 - 16
drivers/target/target_core_rd.c

@@ -27,7 +27,6 @@
  *
  ******************************************************************************/
 
-#include <linux/version.h>
 #include <linux/string.h>
 #include <linux/parser.h>
 #include <linux/timer.h>
@@ -351,7 +350,7 @@ static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page)
 static int rd_MEMCPY_read(struct rd_request *req)
 {
 	struct se_task *task = &req->rd_task;
-	struct rd_dev *dev = req->rd_task.se_dev->dev_ptr;
+	struct rd_dev *dev = req->rd_task.task_se_cmd->se_dev->dev_ptr;
 	struct rd_dev_sg_table *table;
 	struct scatterlist *sg_d, *sg_s;
 	void *dst, *src;
@@ -467,7 +466,7 @@ static int rd_MEMCPY_read(struct rd_request *req)
 static int rd_MEMCPY_write(struct rd_request *req)
 {
 	struct se_task *task = &req->rd_task;
-	struct rd_dev *dev = req->rd_task.se_dev->dev_ptr;
+	struct rd_dev *dev = req->rd_task.task_se_cmd->se_dev->dev_ptr;
 	struct rd_dev_sg_table *table;
 	struct scatterlist *sg_d, *sg_s;
 	void *dst, *src;
@@ -582,7 +581,7 @@ static int rd_MEMCPY_write(struct rd_request *req)
  */
 static int rd_MEMCPY_do_task(struct se_task *task)
 {
-	struct se_device *dev = task->se_dev;
+	struct se_device *dev = task->task_se_cmd->se_dev;
 	struct rd_request *req = RD_REQ(task);
 	unsigned long long lba;
 	int ret;
@@ -692,17 +691,6 @@ static ssize_t rd_show_configfs_dev_params(
 	return bl;
 }
 
-/*	rd_get_cdb(): (Part of se_subsystem_api_t template)
- *
- *
- */
-static unsigned char *rd_get_cdb(struct se_task *task)
-{
-	struct rd_request *req = RD_REQ(task);
-
-	return req->rd_scsi_cdb;
-}
-
 static u32 rd_get_device_rev(struct se_device *dev)
 {
 	return SCSI_SPC_2; /* Returns SPC-3 in Initiator Data */
@@ -736,7 +724,6 @@ static struct se_subsystem_api rd_mcp_template = {
 	.check_configfs_dev_params = rd_check_configfs_dev_params,
 	.set_configfs_dev_params = rd_set_configfs_dev_params,
 	.show_configfs_dev_params = rd_show_configfs_dev_params,
-	.get_cdb		= rd_get_cdb,
 	.get_device_rev		= rd_get_device_rev,
 	.get_device_type	= rd_get_device_type,
 	.get_blocks		= rd_get_blocks,

+ 0 - 2
drivers/target/target_core_rd.h

@@ -22,8 +22,6 @@ void rd_module_exit(void);
 struct rd_request {
 	struct se_task	rd_task;
 
-	/* SCSI CDB from iSCSI Command PDU */
-	unsigned char	rd_scsi_cdb[TCM_MAX_COMMAND_SIZE];
 	/* Offset from start of page */
 	u32		rd_offset;
 	/* Starting page in Ramdisk for request */

+ 0 - 105
drivers/target/target_core_scdb.c

@@ -1,105 +0,0 @@
-/*******************************************************************************
- * Filename:  target_core_scdb.c
- *
- * This file contains the generic target engine Split CDB related functions.
- *
- * Copyright (c) 2004-2005 PyX Technologies, Inc.
- * Copyright (c) 2005, 2006, 2007 SBE, Inc.
- * Copyright (c) 2007-2010 Rising Tide Systems
- * Copyright (c) 2008-2010 Linux-iSCSI.org
- *
- * Nicholas A. Bellinger <nab@kernel.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- ******************************************************************************/
-
-#include <linux/net.h>
-#include <linux/string.h>
-#include <scsi/scsi.h>
-#include <asm/unaligned.h>
-
-#include <target/target_core_base.h>
-#include <target/target_core_transport.h>
-
-#include "target_core_scdb.h"
-
-/*	split_cdb_XX_6():
- *
- *      21-bit LBA w/ 8-bit SECTORS
- */
-void split_cdb_XX_6(
-	unsigned long long lba,
-	u32 sectors,
-	unsigned char *cdb)
-{
-	cdb[1] = (lba >> 16) & 0x1f;
-	cdb[2] = (lba >> 8) & 0xff;
-	cdb[3] = lba & 0xff;
-	cdb[4] = sectors & 0xff;
-}
-
-/*	split_cdb_XX_10():
- *
- *	32-bit LBA w/ 16-bit SECTORS
- */
-void split_cdb_XX_10(
-	unsigned long long lba,
-	u32 sectors,
-	unsigned char *cdb)
-{
-	put_unaligned_be32(lba, &cdb[2]);
-	put_unaligned_be16(sectors, &cdb[7]);
-}
-
-/*	split_cdb_XX_12():
- *
- *	32-bit LBA w/ 32-bit SECTORS
- */
-void split_cdb_XX_12(
-	unsigned long long lba,
-	u32 sectors,
-	unsigned char *cdb)
-{
-	put_unaligned_be32(lba, &cdb[2]);
-	put_unaligned_be32(sectors, &cdb[6]);
-}
-
-/*	split_cdb_XX_16():
- *
- *	64-bit LBA w/ 32-bit SECTORS
- */
-void split_cdb_XX_16(
-	unsigned long long lba,
-	u32 sectors,
-	unsigned char *cdb)
-{
-	put_unaligned_be64(lba, &cdb[2]);
-	put_unaligned_be32(sectors, &cdb[10]);
-}
-
-/*
- *	split_cdb_XX_32():
- *
- * 	64-bit LBA w/ 32-bit SECTORS such as READ_32, WRITE_32 and emulated XDWRITEREAD_32
- */
-void split_cdb_XX_32(
-	unsigned long long lba,
-	u32 sectors,
-	unsigned char *cdb)
-{
-	put_unaligned_be64(lba, &cdb[12]);
-	put_unaligned_be32(sectors, &cdb[28]);
-}

+ 0 - 10
drivers/target/target_core_scdb.h

@@ -1,10 +0,0 @@
-#ifndef TARGET_CORE_SCDB_H
-#define TARGET_CORE_SCDB_H
-
-extern void split_cdb_XX_6(unsigned long long, u32, unsigned char *);
-extern void split_cdb_XX_10(unsigned long long, u32, unsigned char *);
-extern void split_cdb_XX_12(unsigned long long, u32, unsigned char *);
-extern void split_cdb_XX_16(unsigned long long, u32, unsigned char *);
-extern void split_cdb_XX_32(unsigned long long, u32, unsigned char *);
-
-#endif /* TARGET_CORE_SCDB_H */

+ 0 - 1
drivers/target/target_core_stat.c

@@ -32,7 +32,6 @@
 #include <linux/delay.h>
 #include <linux/timer.h>
 #include <linux/string.h>
-#include <linux/version.h>
 #include <generated/utsrelease.h>
 #include <linux/utsname.h>
 #include <linux/proc_fs.h>

+ 152 - 99
drivers/target/target_core_tmr.c

@@ -24,7 +24,6 @@
  *
  ******************************************************************************/
 
-#include <linux/version.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
@@ -44,12 +43,12 @@
 struct se_tmr_req *core_tmr_alloc_req(
 	struct se_cmd *se_cmd,
 	void *fabric_tmr_ptr,
-	u8 function)
+	u8 function,
+	gfp_t gfp_flags)
 {
 	struct se_tmr_req *tmr;
 
-	tmr = kmem_cache_zalloc(se_tmr_req_cache, (in_interrupt()) ?
-					GFP_ATOMIC : GFP_KERNEL);
+	tmr = kmem_cache_zalloc(se_tmr_req_cache, gfp_flags);
 	if (!tmr) {
 		pr_err("Unable to allocate struct se_tmr_req\n");
 		return ERR_PTR(-ENOMEM);
@@ -67,15 +66,16 @@ void core_tmr_release_req(
 	struct se_tmr_req *tmr)
 {
 	struct se_device *dev = tmr->tmr_dev;
+	unsigned long flags;
 
 	if (!dev) {
 		kmem_cache_free(se_tmr_req_cache, tmr);
 		return;
 	}
 
-	spin_lock_irq(&dev->se_tmr_lock);
+	spin_lock_irqsave(&dev->se_tmr_lock, flags);
 	list_del(&tmr->tmr_list);
-	spin_unlock_irq(&dev->se_tmr_lock);
+	spin_unlock_irqrestore(&dev->se_tmr_lock, flags);
 
 	kmem_cache_free(se_tmr_req_cache, tmr);
 }
@@ -100,54 +100,20 @@ static void core_tmr_handle_tas_abort(
 	transport_cmd_finish_abort(cmd, 0);
 }
 
-int core_tmr_lun_reset(
+static void core_tmr_drain_tmr_list(
 	struct se_device *dev,
 	struct se_tmr_req *tmr,
-	struct list_head *preempt_and_abort_list,
-	struct se_cmd *prout_cmd)
+	struct list_head *preempt_and_abort_list)
 {
-	struct se_cmd *cmd, *tcmd;
-	struct se_node_acl *tmr_nacl = NULL;
-	struct se_portal_group *tmr_tpg = NULL;
-	struct se_queue_obj *qobj = &dev->dev_queue_obj;
+	LIST_HEAD(drain_tmr_list);
 	struct se_tmr_req *tmr_p, *tmr_pp;
-	struct se_task *task, *task_tmp;
+	struct se_cmd *cmd;
 	unsigned long flags;
-	int fe_count, tas;
-	/*
-	 * TASK_ABORTED status bit, this is configurable via ConfigFS
-	 * struct se_device attributes.  spc4r17 section 7.4.6 Control mode page
-	 *
-	 * A task aborted status (TAS) bit set to zero specifies that aborted
-	 * tasks shall be terminated by the device server without any response
-	 * to the application client. A TAS bit set to one specifies that tasks
-	 * aborted by the actions of an I_T nexus other than the I_T nexus on
-	 * which the command was received shall be completed with TASK ABORTED
-	 * status (see SAM-4).
-	 */
-	tas = dev->se_sub_dev->se_dev_attrib.emulate_tas;
-	/*
-	 * Determine if this se_tmr is coming from a $FABRIC_MOD
-	 * or struct se_device passthrough..
-	 */
-	if (tmr && tmr->task_cmd && tmr->task_cmd->se_sess) {
-		tmr_nacl = tmr->task_cmd->se_sess->se_node_acl;
-		tmr_tpg = tmr->task_cmd->se_sess->se_tpg;
-		if (tmr_nacl && tmr_tpg) {
-			pr_debug("LUN_RESET: TMR caller fabric: %s"
-				" initiator port %s\n",
-				tmr_tpg->se_tpg_tfo->get_fabric_name(),
-				tmr_nacl->initiatorname);
-		}
-	}
-	pr_debug("LUN_RESET: %s starting for [%s], tas: %d\n",
-		(preempt_and_abort_list) ? "Preempt" : "TMR",
-		dev->transport->name, tas);
 	/*
 	 * Release all pending and outgoing TMRs aside from the received
 	 * LUN_RESET tmr..
 	 */
-	spin_lock_irq(&dev->se_tmr_lock);
+	spin_lock_irqsave(&dev->se_tmr_lock, flags);
 	list_for_each_entry_safe(tmr_p, tmr_pp, &dev->dev_tmr_list, tmr_list) {
 		/*
 		 * Allow the received TMR to return with FUNCTION_COMPLETE.
@@ -169,29 +135,48 @@ int core_tmr_lun_reset(
 		    (core_scsi3_check_cdb_abort_and_preempt(
 					preempt_and_abort_list, cmd) != 0))
 			continue;
-		spin_unlock_irq(&dev->se_tmr_lock);
 
-		spin_lock_irqsave(&cmd->t_state_lock, flags);
+		spin_lock(&cmd->t_state_lock);
 		if (!atomic_read(&cmd->t_transport_active)) {
-			spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-			spin_lock_irq(&dev->se_tmr_lock);
+			spin_unlock(&cmd->t_state_lock);
 			continue;
 		}
 		if (cmd->t_state == TRANSPORT_ISTATE_PROCESSING) {
-			spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-			spin_lock_irq(&dev->se_tmr_lock);
+			spin_unlock(&cmd->t_state_lock);
 			continue;
 		}
+		spin_unlock(&cmd->t_state_lock);
+
+		list_move_tail(&tmr->tmr_list, &drain_tmr_list);
+	}
+	spin_unlock_irqrestore(&dev->se_tmr_lock, flags);
+
+	while (!list_empty(&drain_tmr_list)) {
+		tmr = list_entry(drain_tmr_list.next, struct se_tmr_req, tmr_list);
+		list_del(&tmr->tmr_list);
+		cmd = tmr_p->task_cmd;
+
 		pr_debug("LUN_RESET: %s releasing TMR %p Function: 0x%02x,"
 			" Response: 0x%02x, t_state: %d\n",
-			(preempt_and_abort_list) ? "Preempt" : "", tmr_p,
-			tmr_p->function, tmr_p->response, cmd->t_state);
-		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+			(preempt_and_abort_list) ? "Preempt" : "", tmr,
+			tmr->function, tmr->response, cmd->t_state);
 
-		transport_cmd_finish_abort_tmr(cmd);
-		spin_lock_irq(&dev->se_tmr_lock);
+		transport_cmd_finish_abort(cmd, 1);
 	}
-	spin_unlock_irq(&dev->se_tmr_lock);
+}
+
+static void core_tmr_drain_task_list(
+	struct se_device *dev,
+	struct se_cmd *prout_cmd,
+	struct se_node_acl *tmr_nacl,
+	int tas,
+	struct list_head *preempt_and_abort_list)
+{
+	LIST_HEAD(drain_task_list);
+	struct se_cmd *cmd;
+	struct se_task *task, *task_tmp;
+	unsigned long flags;
+	int fe_count;
 	/*
 	 * Complete outstanding struct se_task CDBs with TASK_ABORTED SAM status.
 	 * This is following sam4r17, section 5.6 Aborting commands, Table 38
@@ -236,18 +221,28 @@ int core_tmr_lun_reset(
 		if (prout_cmd == cmd)
 			continue;
 
-		list_del(&task->t_state_list);
+		list_move_tail(&task->t_state_list, &drain_task_list);
 		atomic_set(&task->task_state_active, 0);
-		spin_unlock_irqrestore(&dev->execute_task_lock, flags);
+		/*
+		 * Remove from task execute list before processing drain_task_list
+		 */
+		if (!list_empty(&task->t_execute_list))
+			__transport_remove_task_from_execute_queue(task, dev);
+	}
+	spin_unlock_irqrestore(&dev->execute_task_lock, flags);
+
+	while (!list_empty(&drain_task_list)) {
+		task = list_entry(drain_task_list.next, struct se_task, t_state_list);
+		list_del(&task->t_state_list);
+		cmd = task->task_se_cmd;
 
-		spin_lock_irqsave(&cmd->t_state_lock, flags);
 		pr_debug("LUN_RESET: %s cmd: %p task: %p"
-			" ITT/CmdSN: 0x%08x/0x%08x, i_state: %d, t_state/"
-			"def_t_state: %d/%d cdb: 0x%02x\n",
+			" ITT/CmdSN: 0x%08x/0x%08x, i_state: %d, t_state: %d"
+			"cdb: 0x%02x\n",
 			(preempt_and_abort_list) ? "Preempt" : "", cmd, task,
 			cmd->se_tfo->get_task_tag(cmd), 0,
 			cmd->se_tfo->get_cmd_state(cmd), cmd->t_state,
-			cmd->deferred_t_state, cmd->t_task_cdb[0]);
+			cmd->t_task_cdb[0]);
 		pr_debug("LUN_RESET: ITT[0x%08x] - pr_res_key: 0x%016Lx"
 			" t_task_cdbs: %d t_task_cdbs_left: %d"
 			" t_task_cdbs_sent: %d -- t_transport_active: %d"
@@ -260,35 +255,24 @@ int core_tmr_lun_reset(
 			atomic_read(&cmd->t_transport_stop),
 			atomic_read(&cmd->t_transport_sent));
 
-		if (atomic_read(&task->task_active)) {
-			atomic_set(&task->task_stop, 1);
-			spin_unlock_irqrestore(
-				&cmd->t_state_lock, flags);
-
-			pr_debug("LUN_RESET: Waiting for task: %p to shutdown"
-				" for dev: %p\n", task, dev);
-			wait_for_completion(&task->task_stop_comp);
-			pr_debug("LUN_RESET Completed task: %p shutdown for"
-				" dev: %p\n", task, dev);
-			spin_lock_irqsave(&cmd->t_state_lock, flags);
-			atomic_dec(&cmd->t_task_cdbs_left);
-
-			atomic_set(&task->task_active, 0);
-			atomic_set(&task->task_stop, 0);
-		} else {
-			if (atomic_read(&task->task_execute_queue) != 0)
-				transport_remove_task_from_execute_queue(task, dev);
-		}
-		__transport_stop_task_timer(task, &flags);
+		/*
+		 * If the command may be queued onto a workqueue cancel it now.
+		 *
+		 * This is equivalent to removal from the execute queue in the
+		 * loop above, but we do it down here given that
+		 * cancel_work_sync may block.
+		 */
+		if (cmd->t_state == TRANSPORT_COMPLETE)
+			cancel_work_sync(&cmd->work);
+
+		spin_lock_irqsave(&cmd->t_state_lock, flags);
+		target_stop_task(task, &flags);
 
 		if (!atomic_dec_and_test(&cmd->t_task_cdbs_ex_left)) {
-			spin_unlock_irqrestore(
-					&cmd->t_state_lock, flags);
+			spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 			pr_debug("LUN_RESET: Skipping task: %p, dev: %p for"
 				" t_task_cdbs_ex_left: %d\n", task, dev,
 				atomic_read(&cmd->t_task_cdbs_ex_left));
-
-			spin_lock_irqsave(&dev->execute_task_lock, flags);
 			continue;
 		}
 		fe_count = atomic_read(&cmd->t_fe_count);
@@ -298,22 +282,31 @@ int core_tmr_lun_reset(
 				" task: %p, t_fe_count: %d dev: %p\n", task,
 				fe_count, dev);
 			atomic_set(&cmd->t_transport_aborted, 1);
-			spin_unlock_irqrestore(&cmd->t_state_lock,
-						flags);
-			core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
+			spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-			spin_lock_irqsave(&dev->execute_task_lock, flags);
+			core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
 			continue;
 		}
 		pr_debug("LUN_RESET: Got t_transport_active = 0 for task: %p,"
 			" t_fe_count: %d dev: %p\n", task, fe_count, dev);
 		atomic_set(&cmd->t_transport_aborted, 1);
 		spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-		core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
 
-		spin_lock_irqsave(&dev->execute_task_lock, flags);
+		core_tmr_handle_tas_abort(tmr_nacl, cmd, tas, fe_count);
 	}
-	spin_unlock_irqrestore(&dev->execute_task_lock, flags);
+}
+
+static void core_tmr_drain_cmd_list(
+	struct se_device *dev,
+	struct se_cmd *prout_cmd,
+	struct se_node_acl *tmr_nacl,
+	int tas,
+	struct list_head *preempt_and_abort_list)
+{
+	LIST_HEAD(drain_cmd_list);
+	struct se_queue_obj *qobj = &dev->dev_queue_obj;
+	struct se_cmd *cmd, *tcmd;
+	unsigned long flags;
 	/*
 	 * Release all commands remaining in the struct se_device cmd queue.
 	 *
@@ -337,11 +330,26 @@ int core_tmr_lun_reset(
 		 */
 		if (prout_cmd == cmd)
 			continue;
+		/*
+		 * Skip direct processing of TRANSPORT_FREE_CMD_INTR for
+		 * HW target mode fabrics.
+		 */
+		spin_lock(&cmd->t_state_lock);
+		if (cmd->t_state == TRANSPORT_FREE_CMD_INTR) {
+			spin_unlock(&cmd->t_state_lock);
+			continue;
+		}
+		spin_unlock(&cmd->t_state_lock);
 
-		atomic_dec(&cmd->t_transport_queue_active);
+		atomic_set(&cmd->t_transport_queue_active, 0);
 		atomic_dec(&qobj->queue_cnt);
-		list_del(&cmd->se_queue_node);
-		spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
+		list_move_tail(&cmd->se_queue_node, &drain_cmd_list);
+	}
+	spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
+
+	while (!list_empty(&drain_cmd_list)) {
+		cmd = list_entry(drain_cmd_list.next, struct se_cmd, se_queue_node);
+		list_del_init(&cmd->se_queue_node);
 
 		pr_debug("LUN_RESET: %s from Device Queue: cmd: %p t_state:"
 			" %d t_fe_count: %d\n", (preempt_and_abort_list) ?
@@ -354,9 +362,53 @@ int core_tmr_lun_reset(
 
 		core_tmr_handle_tas_abort(tmr_nacl, cmd, tas,
 				atomic_read(&cmd->t_fe_count));
-		spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
 	}
-	spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
+}
+
+int core_tmr_lun_reset(
+        struct se_device *dev,
+        struct se_tmr_req *tmr,
+        struct list_head *preempt_and_abort_list,
+        struct se_cmd *prout_cmd)
+{
+	struct se_node_acl *tmr_nacl = NULL;
+	struct se_portal_group *tmr_tpg = NULL;
+	int tas;
+        /*
+	 * TASK_ABORTED status bit, this is configurable via ConfigFS
+	 * struct se_device attributes.  spc4r17 section 7.4.6 Control mode page
+	 *
+	 * A task aborted status (TAS) bit set to zero specifies that aborted
+	 * tasks shall be terminated by the device server without any response
+	 * to the application client. A TAS bit set to one specifies that tasks
+	 * aborted by the actions of an I_T nexus other than the I_T nexus on
+	 * which the command was received shall be completed with TASK ABORTED
+	 * status (see SAM-4).
+	 */
+	tas = dev->se_sub_dev->se_dev_attrib.emulate_tas;
+	/*
+	 * Determine if this se_tmr is coming from a $FABRIC_MOD
+	 * or struct se_device passthrough..
+	 */
+	if (tmr && tmr->task_cmd && tmr->task_cmd->se_sess) {
+		tmr_nacl = tmr->task_cmd->se_sess->se_node_acl;
+		tmr_tpg = tmr->task_cmd->se_sess->se_tpg;
+		if (tmr_nacl && tmr_tpg) {
+			pr_debug("LUN_RESET: TMR caller fabric: %s"
+				" initiator port %s\n",
+				tmr_tpg->se_tpg_tfo->get_fabric_name(),
+				tmr_nacl->initiatorname);
+		}
+	}
+	pr_debug("LUN_RESET: %s starting for [%s], tas: %d\n",
+		(preempt_and_abort_list) ? "Preempt" : "TMR",
+		dev->transport->name, tas);
+
+	core_tmr_drain_tmr_list(dev, tmr, preempt_and_abort_list);
+	core_tmr_drain_task_list(dev, prout_cmd, tmr_nacl, tas,
+				preempt_and_abort_list);
+	core_tmr_drain_cmd_list(dev, prout_cmd, tmr_nacl, tas,
+				preempt_and_abort_list);
 	/*
 	 * Clear any legacy SPC-2 reservation when called during
 	 * LOGICAL UNIT RESET
@@ -379,3 +431,4 @@ int core_tmr_lun_reset(
 			dev->transport->name);
 	return 0;
 }
+

Plik diff jest za duży
+ 165 - 476
drivers/target/target_core_transport.c


+ 0 - 1
drivers/target/target_core_ua.c

@@ -24,7 +24,6 @@
  *
  ******************************************************************************/
 
-#include <linux/version.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <scsi/scsi.h>

+ 8 - 10
drivers/target/tcm_fc/tfc_cmd.c

@@ -19,7 +19,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/version.h>
 #include <generated/utsrelease.h>
 #include <linux/utsname.h>
 #include <linux/init.h>
@@ -115,7 +114,7 @@ void ft_release_cmd(struct se_cmd *se_cmd)
 
 void ft_check_stop_free(struct se_cmd *se_cmd)
 {
-	transport_generic_free_cmd(se_cmd, 0, 0);
+	transport_generic_free_cmd(se_cmd, 0);
 }
 
 /*
@@ -268,9 +267,8 @@ static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg)
 
 	if (IS_ERR(fp)) {
 		/* XXX need to find cmd if queued */
-		cmd->se_cmd.t_state = TRANSPORT_REMOVE;
 		cmd->seq = NULL;
-		transport_generic_free_cmd(&cmd->se_cmd, 0, 0);
+		transport_generic_free_cmd(&cmd->se_cmd, 0);
 		return;
 	}
 
@@ -288,7 +286,7 @@ static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg)
 		       __func__, fh->fh_r_ctl);
 		ft_invl_hw_context(cmd);
 		fc_frame_free(fp);
-		transport_generic_free_cmd(&cmd->se_cmd, 0, 0);
+		transport_generic_free_cmd(&cmd->se_cmd, 0);
 		break;
 	}
 }
@@ -397,7 +395,7 @@ static void ft_send_tm(struct ft_cmd *cmd)
 	}
 
 	pr_debug("alloc tm cmd fn %d\n", tm_func);
-	tmr = core_tmr_alloc_req(&cmd->se_cmd, cmd, tm_func);
+	tmr = core_tmr_alloc_req(&cmd->se_cmd, cmd, tm_func, GFP_KERNEL);
 	if (!tmr) {
 		pr_debug("alloc failed\n");
 		ft_send_resp_code_and_free(cmd, FCP_TMF_FAILED);
@@ -421,7 +419,7 @@ static void ft_send_tm(struct ft_cmd *cmd)
 			sess = cmd->sess;
 			transport_send_check_condition_and_sense(&cmd->se_cmd,
 				cmd->se_cmd.scsi_sense_reason, 0);
-			transport_generic_free_cmd(&cmd->se_cmd, 0, 0);
+			transport_generic_free_cmd(&cmd->se_cmd, 0);
 			ft_sess_put(sess);
 			return;
 		}
@@ -628,7 +626,7 @@ static void ft_send_work(struct work_struct *work)
 	if (ret == -ENOMEM) {
 		transport_send_check_condition_and_sense(se_cmd,
 				TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
-		transport_generic_free_cmd(se_cmd, 0, 0);
+		transport_generic_free_cmd(se_cmd, 0);
 		return;
 	}
 	if (ret == -EINVAL) {
@@ -637,10 +635,10 @@ static void ft_send_work(struct work_struct *work)
 		else
 			transport_send_check_condition_and_sense(se_cmd,
 					se_cmd->scsi_sense_reason, 0);
-		transport_generic_free_cmd(se_cmd, 0, 0);
+		transport_generic_free_cmd(se_cmd, 0);
 		return;
 	}
-	transport_generic_handle_cdb(se_cmd);
+	transport_handle_cdb_direct(se_cmd);
 	return;
 
 err:

+ 5 - 8
drivers/target/tcm_fc/tfc_conf.c

@@ -23,7 +23,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/version.h>
 #include <generated/utsrelease.h>
 #include <linux/utsname.h>
 #include <linux/init.h>
@@ -32,6 +31,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/configfs.h>
+#include <linux/kernel.h>
 #include <linux/ctype.h>
 #include <asm/unaligned.h>
 #include <scsi/scsi.h>
@@ -71,10 +71,10 @@ static ssize_t ft_parse_wwn(const char *name, u64 *wwn, int strict)
 {
 	const char *cp;
 	char c;
-	u32 nibble;
 	u32 byte = 0;
 	u32 pos = 0;
 	u32 err;
+	int val;
 
 	*wwn = 0;
 	for (cp = name; cp < &name[FT_NAMELEN - 1]; cp++) {
@@ -95,13 +95,10 @@ static ssize_t ft_parse_wwn(const char *name, u64 *wwn, int strict)
 			return cp - name;
 		}
 		err = 3;
-		if (isdigit(c))
-			nibble = c - '0';
-		else if (isxdigit(c) && (islower(c) || !strict))
-			nibble = tolower(c) - 'a' + 10;
-		else
+		val = hex_to_bin(c);
+		if (val < 0 || (strict && isupper(c)))
 			goto fail;
-		*wwn = (*wwn << 4) | nibble;
+		*wwn = (*wwn << 4) | val;
 	}
 	err = 4;
 fail:

+ 0 - 1
drivers/target/tcm_fc/tfc_io.c

@@ -28,7 +28,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/version.h>
 #include <generated/utsrelease.h>
 #include <linux/utsname.h>
 #include <linux/init.h>

+ 0 - 1
drivers/target/tcm_fc/tfc_sess.c

@@ -19,7 +19,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/version.h>
 #include <generated/utsrelease.h>
 #include <linux/utsname.h>
 #include <linux/init.h>

+ 21 - 50
include/target/target_core_base.h

@@ -10,10 +10,7 @@
 #include <net/tcp.h>
 
 #define TARGET_CORE_MOD_VERSION		"v4.1.0-rc1-ml"
-#define SHUTDOWN_SIGS	(sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGABRT))
 
-/* Used by transport_generic_allocate_iovecs() */
-#define TRANSPORT_IOV_DATA_BUFFER		5
 /* Maximum Number of LUNs per Target Portal Group */
 /* Don't raise above 511 or REPORT_LUNS needs to handle >1 page */
 #define TRANSPORT_MAX_LUNS_PER_TPG		256
@@ -75,32 +72,26 @@ enum transport_tpg_type_table {
 };
 
 /* Used for generate timer flags */
-enum timer_flags_table {
-	TF_RUNNING	= 0x01,
-	TF_STOP		= 0x02,
+enum se_task_flags {
+	TF_ACTIVE		= (1 << 0),
+	TF_SENT			= (1 << 1),
+	TF_REQUEST_STOP		= (1 << 2),
 };
 
 /* Special transport agnostic struct se_cmd->t_states */
 enum transport_state_table {
 	TRANSPORT_NO_STATE	= 0,
 	TRANSPORT_NEW_CMD	= 1,
-	TRANSPORT_DEFERRED_CMD	= 2,
 	TRANSPORT_WRITE_PENDING	= 3,
 	TRANSPORT_PROCESS_WRITE	= 4,
 	TRANSPORT_PROCESSING	= 5,
-	TRANSPORT_COMPLETE_OK	= 6,
-	TRANSPORT_COMPLETE_FAILURE = 7,
-	TRANSPORT_COMPLETE_TIMEOUT = 8,
+	TRANSPORT_COMPLETE	= 6,
 	TRANSPORT_PROCESS_TMR	= 9,
-	TRANSPORT_TMR_COMPLETE	= 10,
 	TRANSPORT_ISTATE_PROCESSING = 11,
-	TRANSPORT_ISTATE_PROCESSED = 12,
-	TRANSPORT_KILL		= 13,
-	TRANSPORT_REMOVE	= 14,
-	TRANSPORT_FREE		= 15,
 	TRANSPORT_NEW_CMD_MAP	= 16,
 	TRANSPORT_FREE_CMD_INTR = 17,
 	TRANSPORT_COMPLETE_QF_WP = 18,
+	TRANSPORT_COMPLETE_QF_OK = 19,
 };
 
 /* Used for struct se_cmd->se_cmd_flags */
@@ -125,7 +116,6 @@ enum se_cmd_flags_table {
 	SCF_UNUSED			= 0x00100000,
 	SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00400000,
 	SCF_EMULATE_CDB_ASYNC		= 0x01000000,
-	SCF_EMULATE_QUEUE_FULL		= 0x02000000,
 };
 
 /* struct se_dev_entry->lun_flags and struct se_lun->lun_access */
@@ -401,34 +391,22 @@ struct se_queue_obj {
 } ____cacheline_aligned;
 
 struct se_task {
-	unsigned char	task_sense;
-	struct scatterlist *task_sg;
-	u32		task_sg_nents;
-	struct scatterlist *task_sg_bidi;
-	u8		task_scsi_status;
-	u8		task_flags;
-	int		task_error_status;
-	int		task_state_flags;
-	bool		task_padded_sg;
 	unsigned long long	task_lba;
-	u32		task_no;
-	u32		task_sectors;
-	u32		task_size;
+	u32			task_sectors;
+	u32			task_size;
+	struct se_cmd		*task_se_cmd;
+	struct scatterlist	*task_sg;
+	u32			task_sg_nents;
+	u16			task_flags;
+	u8			task_sense;
+	u8			task_scsi_status;
+	int			task_error_status;
 	enum dma_data_direction	task_data_direction;
-	struct se_cmd *task_se_cmd;
-	struct se_device	*se_dev;
+	atomic_t		task_state_active;
+	struct list_head	t_list;
+	struct list_head	t_execute_list;
+	struct list_head	t_state_list;
 	struct completion	task_stop_comp;
-	atomic_t	task_active;
-	atomic_t	task_execute_queue;
-	atomic_t	task_timeout;
-	atomic_t	task_sent;
-	atomic_t	task_stop;
-	atomic_t	task_state_active;
-	struct timer_list	task_timer;
-	struct se_device *se_obj_ptr;
-	struct list_head t_list;
-	struct list_head t_execute_list;
-	struct list_head t_state_list;
 } ____cacheline_aligned;
 
 struct se_cmd {
@@ -446,8 +424,6 @@ struct se_cmd {
 	int			sam_task_attr;
 	/* Transport protocol dependent state, see transport_state_table */
 	enum transport_state_table t_state;
-	/* Transport protocol dependent state for out of order CmdSNs */
-	int			deferred_t_state;
 	/* Transport specific error status */
 	int			transport_error_status;
 	/* See se_cmd_flags_table */
@@ -461,7 +437,6 @@ struct se_cmd {
 	u32			orig_fe_lun;
 	/* Persistent Reservation key */
 	u64			pr_res_key;
-	atomic_t                transport_sent;
 	/* Used for sense data */
 	void			*sense_buffer;
 	struct list_head	se_delayed_node;
@@ -479,10 +454,7 @@ struct se_cmd {
 	struct list_head	se_queue_node;
 	struct target_core_fabric_ops *se_tfo;
 	int (*transport_emulate_cdb)(struct se_cmd *);
-	void (*transport_split_cdb)(unsigned long long, u32, unsigned char *);
-	void (*transport_wait_for_tasks)(struct se_cmd *, int, int);
 	void (*transport_complete_callback)(struct se_cmd *);
-	int (*transport_qf_callback)(struct se_cmd *);
 
 	unsigned char		*t_task_cdb;
 	unsigned char		__t_task_cdb[TCM_MAX_COMMAND_SIZE];
@@ -495,7 +467,6 @@ struct se_cmd {
 	atomic_t		t_se_count;
 	atomic_t		t_task_cdbs_left;
 	atomic_t		t_task_cdbs_ex_left;
-	atomic_t		t_task_cdbs_timeout_left;
 	atomic_t		t_task_cdbs_sent;
 	atomic_t		t_transport_aborted;
 	atomic_t		t_transport_active;
@@ -503,7 +474,6 @@ struct se_cmd {
 	atomic_t		t_transport_queue_active;
 	atomic_t		t_transport_sent;
 	atomic_t		t_transport_stop;
-	atomic_t		t_transport_timeout;
 	atomic_t		transport_dev_active;
 	atomic_t		transport_lun_active;
 	atomic_t		transport_lun_fe_stop;
@@ -514,6 +484,8 @@ struct se_cmd {
 	struct completion	transport_lun_stop_comp;
 	struct scatterlist	*t_tasks_sg_chained;
 
+	struct work_struct	work;
+
 	/*
 	 * Used for pre-registered fabric SGL passthrough WRITE and READ
 	 * with the special SCF_PASSTHROUGH_CONTIG_TO_SG case for TCM_Loop
@@ -670,7 +642,6 @@ struct se_dev_attrib {
 	u32		optimal_sectors;
 	u32		hw_queue_depth;
 	u32		queue_depth;
-	u32		task_timeout;
 	u32		max_unmap_lba_count;
 	u32		max_unmap_block_desc_count;
 	u32		unmap_granularity;

+ 1 - 1
include/target/target_core_tmr.h

@@ -27,7 +27,7 @@ enum tcm_tmrsp_table {
 
 extern struct kmem_cache *se_tmr_req_cache;
 
-extern struct se_tmr_req *core_tmr_alloc_req(struct se_cmd *, void *, u8);
+extern struct se_tmr_req *core_tmr_alloc_req(struct se_cmd *, void *, u8, gfp_t);
 extern void core_tmr_release_req(struct se_tmr_req *);
 extern int core_tmr_lun_reset(struct se_device *, struct se_tmr_req *,
 				struct list_head *, struct se_cmd *);

+ 14 - 61
include/target/target_core_transport.h

@@ -22,10 +22,9 @@
 #define PYX_TRANSPORT_LU_COMM_FAILURE		-7
 #define PYX_TRANSPORT_UNKNOWN_MODE_PAGE		-8
 #define PYX_TRANSPORT_WRITE_PROTECTED		-9
-#define PYX_TRANSPORT_TASK_TIMEOUT		-10
-#define PYX_TRANSPORT_RESERVATION_CONFLICT	-11
-#define PYX_TRANSPORT_ILLEGAL_REQUEST		-12
-#define PYX_TRANSPORT_USE_SENSE_REASON		-13
+#define PYX_TRANSPORT_RESERVATION_CONFLICT	-10
+#define PYX_TRANSPORT_ILLEGAL_REQUEST		-11
+#define PYX_TRANSPORT_USE_SENSE_REASON		-12
 
 #ifndef SAM_STAT_RESERVATION_CONFLICT
 #define SAM_STAT_RESERVATION_CONFLICT		0x18
@@ -38,16 +37,6 @@
 #define TRANSPORT_PLUGIN_VHBA_PDEV		2
 #define TRANSPORT_PLUGIN_VHBA_VDEV		3
 
-/* For SE OBJ Plugins, in seconds */
-#define TRANSPORT_TIMEOUT_TUR			10
-#define TRANSPORT_TIMEOUT_TYPE_DISK		60
-#define TRANSPORT_TIMEOUT_TYPE_ROM		120
-#define TRANSPORT_TIMEOUT_TYPE_TAPE		600
-#define TRANSPORT_TIMEOUT_TYPE_OTHER		300
-
-/* For se_task->task_state_flags */
-#define TSF_EXCEPTION_CLEARED			0x01
-
 /*
  * struct se_subsystem_dev->su_dev_flags
 */
@@ -64,8 +53,6 @@
 #define DF_SPC2_RESERVATIONS_WITH_ISID		0x00000004
 
 /* struct se_dev_attrib sanity values */
-/* 10 Minutes */
-#define DA_TASK_TIMEOUT_MAX			600
 /* Default max_unmap_lba_count */
 #define DA_MAX_UNMAP_LBA_COUNT			0
 /* Default max_unmap_block_desc_count */
@@ -110,16 +97,13 @@
 
 #define MOD_MAX_SECTORS(ms, bs)			(ms % (PAGE_SIZE / bs))
 
-struct se_mem;
 struct se_subsystem_api;
 
-extern struct kmem_cache *se_mem_cache;
-
 extern int init_se_kmem_caches(void);
 extern void release_se_kmem_caches(void);
 extern u32 scsi_get_new_index(scsi_index_t);
 extern void transport_init_queue_obj(struct se_queue_obj *);
-extern int transport_subsystem_check_init(void);
+extern void transport_subsystem_check_init(void);
 extern int transport_subsystem_register(struct se_subsystem_api *);
 extern void transport_subsystem_release(struct se_subsystem_api *);
 extern void transport_load_plugins(void);
@@ -134,7 +118,6 @@ extern void transport_free_session(struct se_session *);
 extern void transport_deregister_session_configfs(struct se_session *);
 extern void transport_deregister_session(struct se_session *);
 extern void transport_cmd_finish_abort(struct se_cmd *, int);
-extern void transport_cmd_finish_abort_tmr(struct se_cmd *);
 extern void transport_complete_sync_cache(struct se_cmd *, int);
 extern void transport_complete_task(struct se_task *, int);
 extern void transport_add_task_to_execute_queue(struct se_task *,
@@ -142,6 +125,8 @@ extern void transport_add_task_to_execute_queue(struct se_task *,
 						struct se_device *);
 extern void transport_remove_task_from_execute_queue(struct se_task *,
 						struct se_device *);
+extern void __transport_remove_task_from_execute_queue(struct se_task *,
+						struct se_device *);
 unsigned char *transport_dump_cmd_direction(struct se_cmd *);
 extern void transport_dump_dev_state(struct se_device *, char *, int *);
 extern void transport_dump_dev_info(struct se_device *, struct se_lun *,
@@ -169,29 +154,24 @@ extern void transport_init_se_cmd(struct se_cmd *,
 					unsigned char *);
 void *transport_kmap_first_data_page(struct se_cmd *cmd);
 void transport_kunmap_first_data_page(struct se_cmd *cmd);
-extern void transport_free_se_cmd(struct se_cmd *);
 extern int transport_generic_allocate_tasks(struct se_cmd *, unsigned char *);
-extern int transport_generic_handle_cdb(struct se_cmd *);
 extern int transport_handle_cdb_direct(struct se_cmd *);
 extern int transport_generic_handle_cdb_map(struct se_cmd *);
 extern int transport_generic_handle_data(struct se_cmd *);
 extern void transport_new_cmd_failure(struct se_cmd *);
 extern int transport_generic_handle_tmr(struct se_cmd *);
 extern void transport_generic_free_cmd_intr(struct se_cmd *);
-extern void __transport_stop_task_timer(struct se_task *, unsigned long *);
+extern bool target_stop_task(struct se_task *task, unsigned long *flags);
 extern int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *, u32,
 				struct scatterlist *, u32);
 extern int transport_clear_lun_from_sessions(struct se_lun *);
+extern void transport_wait_for_tasks(struct se_cmd *);
 extern int transport_check_aborted_status(struct se_cmd *, int);
 extern int transport_send_check_condition_and_sense(struct se_cmd *, u8, int);
 extern void transport_send_task_abort(struct se_cmd *);
 extern void transport_release_cmd(struct se_cmd *);
-extern void transport_generic_free_cmd(struct se_cmd *, int, int);
+extern void transport_generic_free_cmd(struct se_cmd *, int);
 extern void transport_generic_wait_for_cmds(struct se_cmd *, int);
-extern int transport_init_task_sg(struct se_task *, struct se_mem *, u32);
-extern int transport_map_mem_to_sg(struct se_task *, struct list_head *,
-					struct scatterlist *, struct se_mem *,
-					struct se_mem **, u32 *, u32 *);
 extern void transport_do_task_sg_chain(struct se_cmd *);
 extern void transport_generic_process_write(struct se_cmd *);
 extern int transport_generic_new_cmd(struct se_cmd *);
@@ -200,6 +180,7 @@ extern int transport_generic_do_tmr(struct se_cmd *);
 extern int core_alua_check_nonop_delay(struct se_cmd *);
 /* From target_core_cdb.c */
 extern int transport_emulate_control_cdb(struct se_task *);
+extern void target_get_task_cdb(struct se_task *task, unsigned char *cdb);
 
 /*
  * Each se_transport_task_t can have N number of possible struct se_task's
@@ -227,6 +208,10 @@ struct se_subsystem_api {
 	 * Transport Type.
 	 */
 	u8 transport_type;
+
+	unsigned int fua_write_emulated : 1;
+	unsigned int write_cache_emulated : 1;
+
 	/*
 	 * struct module for struct se_hba references
 	 */
@@ -235,18 +220,6 @@ struct se_subsystem_api {
 	 * Used for global se_subsystem_api list_head
 	 */
 	struct list_head sub_api_list;
-	/*
-	 * For SCF_SCSI_NON_DATA_CDB
-	 */
-	int (*cdb_none)(struct se_task *);
-	/*
-	 * For SCF_SCSI_DATA_SG_IO_CDB
-	 */
-	int (*map_data_SG)(struct se_task *);
-	/*
-	 * For SCF_SCSI_CONTROL_SG_IO_CDB
-	 */
-	int (*map_control_SG)(struct se_task *);
 	/*
 	 * attach_hba():
 	 */
@@ -274,22 +247,6 @@ struct se_subsystem_api {
 	 */
 	void (*free_device)(void *);
 
-	/*
-	 * dpo_emulated():
-	 */
-	int (*dpo_emulated)(struct se_device *);
-	/*
-	 * fua_write_emulated():
-	 */
-	int (*fua_write_emulated)(struct se_device *);
-	/*
-	 * fua_read_emulated():
-	 */
-	int (*fua_read_emulated)(struct se_device *);
-	/*
-	 * write_cache_emulated():
-	 */
-	int (*write_cache_emulated)(struct se_device *);
 	/*
 	 * transport_complete():
 	 *
@@ -330,10 +287,6 @@ struct se_subsystem_api {
 	 */
 	ssize_t (*show_configfs_dev_params)(struct se_hba *, struct se_subsystem_dev *,
 						char *);
-	/*
-	 * get_cdb():
-	 */
-	unsigned char *(*get_cdb)(struct se_task *);
 	/*
 	 * get_device_rev():
 	 */

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików