[PATCH 1/7] [Target_Core_Mod]: Add SPC-3 PERSISTENT_RESERVE_* Infrastrcture

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>From c95cbb3437d09c5211a2ea3380526ff2f2541e69 Mon Sep 17 00:00:00 2001
From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>
Date: Mon, 26 Jan 2009 00:28:54 -0800
Subject: [PATCH 1/7] [Target_Core_Mod]: Add SPC-3 PERSISTENT_RESERVE_* Infrastrcture

This patch adds additional structure members to t10_reservation_template_t and
adds t10_pr_registration_s and (placeholder) t10_pr_reservation_t structure defines
to Target_Core_Mod.

Tjos patch makes non-execption submission for se_cmd_t->emulate_cdb() function pointer
to queue generically in __transport_execute_tasks().

This patch also renames iscsi_send_check_condition_and_sense ->
transport_send_check_condition_and_sense() and updates
transport_generic_request_failure() to handle new exceptions.

Signed-off-by: Nicholas A. Bellinger <nab@xxxxxxxxxxxxxxx>
---
 drivers/lio-core/target_core_base.h      |   39 +++++++++++++--
 drivers/lio-core/target_core_transport.c |   75 ++++++++++++++++++++++-------
 drivers/lio-core/target_core_transport.h |   14 ++++--
 3 files changed, 100 insertions(+), 28 deletions(-)

diff --git a/drivers/lio-core/target_core_base.h b/drivers/lio-core/target_core_base.h
index 7e113d8..c5b6f3e 100644
--- a/drivers/lio-core/target_core_base.h
+++ b/drivers/lio-core/target_core_base.h
@@ -217,7 +217,10 @@
 #define DEV_STATUS_THR_TAKE_OFFLINE		3
 #define DEV_STATUS_THR_SHUTDOWN			4
 
-/* iscsi_send_check_condition_and_sense() */
+/* se_dev_entry_t->deve_flags */
+#define DEF_PR_REGISTERED			0x01
+
+/* transport_send_check_condition_and_sense() */
 #define NON_EXISTENT_LUN			0x1
 #define UNSUPPORTED_SCSI_OPCODE			0x2
 #define INCORRECT_AMOUNT_OF_DATA		0x3
@@ -226,9 +229,10 @@
 #define SNACK_REJECTED				0x6
 #define SECTOR_COUNT_TOO_MANY			0x7
 #define INVALID_CDB_FIELD			0x8
-#define LOGICAL_UNIT_COMMUNICATION_FAILURE	0x9
-#define UNKNOWN_MODE_PAGE			0xa
-#define WRITE_PROTECTED				0xb
+#define INVALID_PARAMETER_LIST			0x9
+#define LOGICAL_UNIT_COMMUNICATION_FAILURE	0xa
+#define UNKNOWN_MODE_PAGE			0xb
+#define WRITE_PROTECTED				0xc
 
 typedef struct se_obj_s {
 	atomic_t obj_access_count;
@@ -264,7 +268,12 @@ typedef enum {
 struct se_cmd_s;
 
 typedef struct t10_reservation_template_s {
+	int pr_all_tg_pt; /* Reservation effects all target ports */
+	u32 pr_generation;
 	t10_reservations_index_t res_type;
+	spinlock_t registration_lock;
+	struct se_node_acl_s *pr_res_holder; /* Reservation holder when pr_all_tg_pt=1 */
+	struct list_head registration_list;
 	int (*t10_reservation_check)(struct se_cmd_s *);
 	int (*t10_reserve)(struct se_cmd_s *);
 	int (*t10_release)(struct se_cmd_s *);
@@ -273,6 +282,21 @@ typedef struct t10_reservation_template_s {
 	int (*t10_pr_clear)(struct se_cmd_s *);
 } ____cacheline_aligned t10_reservation_template_t;
 
+typedef struct t10_pr_registration_s {
+	int pr_reg_all_tg_pt; /* Reservation effects all target ports */
+	int pr_res_type;
+	int pr_res_scope;
+	u32 pr_res_generation;
+	u64 pr_res_key;
+	struct se_node_acl_s *pr_reg_nacl;
+	struct se_dev_entry_s *pr_reg_deve;
+	struct list_head pr_reg_list;
+} t10_pr_registration_t;
+
+typedef struct t10_pr_reservation_s {
+	
+} t10_pr_reservation_t;
+
 typedef struct se_queue_req_s {
         int                     state;
         void                    *queue_se_obj_ptr;
@@ -522,6 +546,7 @@ typedef struct se_lun_acl_s {
 typedef struct se_dev_entry_s {
 	u32			lun_flags;
 	u32			deve_cmds;
+	u32			deve_flags;
 	u32			mapped_lun;
 	u32			average_bytes;
 	u32			last_byte_count;
@@ -602,7 +627,8 @@ typedef struct se_device_s {
 	spinlock_t		dev_status_lock;
 	spinlock_t		dev_status_thr_lock;
 	spinlock_t		se_port_lock;
-	struct se_node_acl_s	*dev_reserved_node_acl;
+	struct se_node_acl_s	*dev_reserved_node_acl; /* Used for legacy SPC-2 reservationsa */
+	struct t10_pr_registration_s *dev_pr_res_holder; /* Used for SPC-3 Persistent Reservations */
 	struct list_head	dev_sep_list;
 	struct timer_list		dev_status_timer;
 	struct task_struct		*process_thread; /* Pointer to descriptor for processing thread */
@@ -623,6 +649,7 @@ typedef struct se_device_s {
 }  ____cacheline_aligned se_device_t;
 
 #define SE_DEV(cmd)		((se_device_t *)(cmd)->se_lun->se_dev)
+#define SU_DEV(dev)		((se_subsystem_dev_t *)(dev)->se_sub_dev)
 #define ISCSI_DEV(cmd)		SE_DEV(cmd)
 #define DEV_ATTRIB(dev)		(&(dev)->se_sub_dev->se_dev_attrib)
 #define DEV_T10_WWN(dev)	(&(dev)->se_sub_dev->t10_wwn)
@@ -662,6 +689,7 @@ typedef struct se_lun_s {
 	int			lun_type;
 	int			lun_status;
 	u32			lun_access;
+	u32			lun_flags;
 	u32			unpacked_lun;
 	spinlock_t		lun_acl_lock;
 	spinlock_t		lun_cmd_lock;
@@ -671,6 +699,7 @@ typedef struct se_lun_s {
 	se_lun_acl_t		*lun_acl_head;
 	se_lun_acl_t		*lun_acl_tail;
 	se_device_t		*se_dev;
+	struct t10_pr_registration_s *lun_pr_res_holder; /* Used for SPC-3 Persistent Reservations */
 	void			*lun_type_ptr;
 	struct config_group	lun_group;
 	struct se_obj_lun_type_s *lun_obj_api;
diff --git a/drivers/lio-core/target_core_transport.c b/drivers/lio-core/target_core_transport.c
index c83ed5d..ad2dd75 100644
--- a/drivers/lio-core/target_core_transport.c
+++ b/drivers/lio-core/target_core_transport.c
@@ -206,6 +206,7 @@ se_global_t *se_global;
 struct kmem_cache *se_cmd_cache = NULL;
 struct kmem_cache *se_task_cache = NULL;
 struct kmem_cache *se_sess_cache = NULL;
+struct kmem_cache *t10_pr_reg_cache = NULL;
 
 EXPORT_SYMBOL(se_global);
 static int transport_generic_write_pending (se_cmd_t *);
@@ -271,7 +272,12 @@ extern int init_se_global (void)
 		printk(KERN_ERR "kmem_cache_create() for se_session_t failed\n");
 		goto out;
 	}
-
+	if (!(t10_pr_reg_cache = kmem_cache_create("t10_pr_reg_cache",
+			sizeof(t10_pr_registration_t), __alignof__(t10_pr_registration_t),
+			0, NULL))) {
+		printk(KERN_ERR "kmem_cache_create() for t10_pr_registration_t failed\n");
+		goto out;
+	}
         if (!(global->hba_list = kzalloc((sizeof(se_hba_t) *
 				TRANSPORT_MAX_GLOBAL_HBAS), GFP_KERNEL))) {
                 TRACE_ERROR("Unable to allocate global->hba_list\n");
@@ -309,6 +315,8 @@ out:
 		kmem_cache_destroy(se_task_cache);
 	if (se_sess_cache)
 		kmem_cache_destroy(se_sess_cache);
+	if (t10_pr_reg_cache)
+		kmem_cache_destroy(t10_pr_reg_cache);
 	kfree(global);
         return(-1);
 }
@@ -325,6 +333,7 @@ extern void release_se_global (void)
 	kmem_cache_destroy(se_cmd_cache);
 	kmem_cache_destroy(se_task_cache);
 	kmem_cache_destroy(se_sess_cache);
+	kmem_cache_destroy(t10_pr_reg_cache);
 	kfree(global);
 
 	se_global = NULL;
@@ -2946,6 +2955,9 @@ extern void transport_generic_request_failure (se_cmd_t *cmd, se_device_t *dev,
 	case PYX_TRANSPORT_INVALID_CDB_FIELD:
 		cmd->scsi_sense_reason = INVALID_CDB_FIELD;
 		break;
+	case PYX_TRANSPORT_INVALID_PARAMETER_LIST:
+		cmd->scsi_sense_reason = INVALID_PARAMETER_LIST;
+		break;
 	case PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES:
 		if (!(cmd->se_cmd_flags & SCF_CMD_PASSTHROUGH)) {
 			if (!sc)
@@ -2970,6 +2982,18 @@ extern void transport_generic_request_failure (se_cmd_t *cmd, se_device_t *dev,
 	case PYX_TRANSPORT_WRITE_PROTECTED:
 		cmd->scsi_sense_reason = WRITE_PROTECTED;
 		break;
+	case PYX_TRANSPORT_RESERVATION_CONFLICT:
+		/*
+		 * No SENSE Data payload for this case, set SCSI Status
+		 * and queue the response to $FABRIC_MOD.  
+		 *
+		 * Uses linux/include/scsi/scsi.h SAM status codes defs
+		 */
+		cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
+		if (!(cmd->se_cmd_flags & SCF_CMD_PASSTHROUGH))
+			CMD_TFO(cmd)->queue_status(cmd);
+
+		goto check_stop;
 	default:
 		TRACE_ERROR("Unknown transport error for CDB 0x%02x: %d\n",
 			T_TASK(cmd)->t_task_cdb[0], cmd->transport_error_status);
@@ -2980,8 +3004,8 @@ extern void transport_generic_request_failure (se_cmd_t *cmd, se_device_t *dev,
 	if (!sc)
 		transport_new_cmd_failure(cmd);
 	else
-		iscsi_send_check_condition_and_sense(cmd, cmd->scsi_sense_reason, 0);
-	
+		transport_send_check_condition_and_sense(cmd,
+			cmd->scsi_sense_reason, 0);
 check_stop:
 	transport_lun_remove_cmd(cmd);
 	if (!(transport_cmd_check_stop(cmd, 2, 0)))
@@ -3828,7 +3852,15 @@ check_depth:
 			atomic_set(&cmd->transport_sent, 0);
 			transport_stop_tasks_for_cmd(cmd);
 			transport_generic_request_failure(cmd, dev, 0, 1);
+			goto check_depth;
 		}
+		/*
+		 * Handle the successful completion for transport_emulate_cdb()
+		 * usage.
+		 */
+		cmd->scsi_status = SAM_STAT_GOOD;
+		task->task_scsi_status = GOOD;
+		transport_complete_task(task, 1);
 	} else {
 		if ((error = TRANSPORT(dev)->do_task(task)) != 0) {
 			cmd->transport_error_status = error;
@@ -4004,7 +4036,7 @@ extern int transport_generic_emulate_inquiry (
 	if (!(cdb[1] & 0x1)) {
 		if (type == TYPE_TAPE)
 			buf[1] = 0x80;
-		buf[2]          = 0x02;
+		buf[2]          = TRANSPORT(dev)->get_device_rev(dev);
 		buf[4]          = 31;
 		buf[7]		= 0x32; /* Sync=1 and CmdQue=1 */
 		
@@ -4506,9 +4538,9 @@ static int transport_generic_cmd_sequencer (
 			(T10_RES(su_dev)->res_type == SPC3_PERSISTENT_RESERVATIONS) ?
 			&core_scsi3_emulate_pr : NULL;
 		size = (cdb[7] << 8) + cdb[8];
-		CMD_ORIG_OBJ_API(cmd)->get_mem_SG(cmd->se_orig_obj_ptr, cmd);
+		CMD_ORIG_OBJ_API(cmd)->get_mem_buf(cmd->se_orig_obj_ptr, cmd);
 		transport_get_maps(cmd);
-		ret = 1;
+		ret = 2;
 		break;
 	case READ_DVD_STRUCTURE:
 		SET_GENERIC_TRANSPORT_FUNCTIONS(cmd);
@@ -5147,7 +5179,7 @@ extern void transport_generic_complete_ok (se_cmd_t *cmd)
 		 * a non GOOD status.
 		 */
 		if (cmd->scsi_status) {
-			iscsi_send_check_condition_and_sense(cmd, reason, 1);
+			transport_send_check_condition_and_sense(cmd, reason, 1);
 			transport_lun_remove_cmd(cmd);
 			transport_cmd_check_stop(cmd, 2, 0);
 			return;
@@ -6445,7 +6477,7 @@ extern void transport_clear_lun_from_sessions (se_lun_t *lun)
                  * Initiator Node.  Return this SCSI CDB back with an CHECK_CONDITION
                  * status.
                  */
-                iscsi_send_check_condition_and_sense(cmd, NON_EXISTENT_LUN, 0);
+                transport_send_check_condition_and_sense(cmd, NON_EXISTENT_LUN, 0);
 
                 /*
                  * If the iSCSI frontend is waiting for this iscsi_cmd_t to be released,
@@ -6556,7 +6588,7 @@ remove:
 	return;
 }
 
-extern int iscsi_send_check_condition_and_sense (se_cmd_t *cmd, u8 reason, int from_transport)
+extern int transport_send_check_condition_and_sense (se_cmd_t *cmd, u8 reason, int from_transport)
 {
 	unsigned char *buffer = NULL;
 	unsigned long flags;
@@ -6620,6 +6652,11 @@ extern int iscsi_send_check_condition_and_sense (se_cmd_t *cmd, u8 reason, int f
                 buffer[4] = 0x0b; /* ABORTED COMMAND */
                 buffer[14] = 0x24; /* INVALID FIELD IN CDB */
                 break;
+	case INVALID_PARAMETER_LIST:
+		buffer[2] = 0x70; /* CURRENT ERROR */
+		buffer[4] = 0x0b; /* ABORTED COMMAND */
+		buffer[14] = 0x26; /* INVALID FIELD IN PARAMETER LIST */
+		break;
         case UNEXPECTED_UNSOLICITED_DATA:
                 buffer[2] = 0x70; /* CURRENT ERROR */
                 buffer[4] = 0x0b; /* ABORTED COMMAND */
@@ -6650,12 +6687,13 @@ extern int iscsi_send_check_condition_and_sense (se_cmd_t *cmd, u8 reason, int f
                 buffer[14] = 0x80; /* LOGICAL UNIT COMMUNICATION FAILURE */
                 break;
         }
-
 	/*
-	 * LINUX defines CHECK_CONDITION as 0x01, but follow SPC-3 anyways.
+	 * This code uses linux/include/scsi/scsi.h SAM status codes!
 	 */
-        cmd->scsi_status        = 0x02; /* CHECK CONDITION */
-        cmd->scsi_sense_length  = TRANSPORT_SENSE_SEGMENT_LENGTH; /* Automatically padded */
+	cmd->scsi_status = SAM_STAT_CHECK_CONDITION;
+
+	/* Automatically padded */
+	cmd->scsi_sense_length  = TRANSPORT_SENSE_SEGMENT_LENGTH;
 
 after_reason:
         if (!(cmd->se_cmd_flags & SCF_CMD_PASSTHROUGH))
@@ -6664,7 +6702,7 @@ after_reason:
 	return(0);
 }
 
-EXPORT_SYMBOL(iscsi_send_check_condition_and_sense);
+EXPORT_SYMBOL(transport_send_check_condition_and_sense);
 
 /*	transport_generic_lun_reset():
  *
@@ -7159,7 +7197,7 @@ fail_cmd:
 		spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
 
 		if (!remove)
-			iscsi_send_check_condition_and_sense(cmd, LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
+			transport_send_check_condition_and_sense(cmd, LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
 
 		transport_remove_cmd_from_queue(cmd,
 			CMD_ORIG_OBJ_API(cmd)->get_queue_obj(cmd->se_orig_obj_ptr));
@@ -7403,7 +7441,7 @@ static void transport_processing_shutdown (se_device_t *dev)
 
 			if (atomic_read(&T_TASK(cmd)->t_fe_count)) {
 				spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
-				iscsi_send_check_condition_and_sense(cmd, LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
+				transport_send_check_condition_and_sense(cmd, LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
 				transport_remove_cmd_from_queue(cmd,
 						CMD_ORIG_OBJ_API(cmd)->get_queue_obj(cmd->se_orig_obj_ptr));
 
@@ -7431,7 +7469,7 @@ static void transport_processing_shutdown (se_device_t *dev)
 
 		if (atomic_read(&T_TASK(cmd)->t_fe_count)) {
 			spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);	
-			iscsi_send_check_condition_and_sense(cmd, LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
+			transport_send_check_condition_and_sense(cmd, LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
 			transport_remove_cmd_from_queue(cmd,
 					CMD_ORIG_OBJ_API(cmd)->get_queue_obj(cmd->se_orig_obj_ptr));
 
@@ -7468,7 +7506,8 @@ static void transport_processing_shutdown (se_device_t *dev)
 		DEBUG_DO("From Device Queue: cmd: %p t_state: %d\n", cmd, state);
 		
 		if (atomic_read(&T_TASK(cmd)->t_fe_count)) {
-			iscsi_send_check_condition_and_sense(cmd, LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
+			transport_send_check_condition_and_sense(cmd,
+				LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
 
 			transport_lun_remove_cmd(cmd);
 			if (!(transport_cmd_check_stop(cmd, 1, 0)))
diff --git a/drivers/lio-core/target_core_transport.h b/drivers/lio-core/target_core_transport.h
index 27a127c..768b8c7 100644
--- a/drivers/lio-core/target_core_transport.h
+++ b/drivers/lio-core/target_core_transport.h
@@ -46,10 +46,12 @@
 #define PYX_TRANSPORT_REQ_TOO_MANY_SECTORS	-3
 #define PYX_TRANSPORT_OUT_OF_MEMORY_RESOURCES	-4
 #define PYX_TRANSPORT_INVALID_CDB_FIELD		-5
-#define PYX_TRANSPORT_LOGICAL_UNIT_COMMUNICATION_FAILURE -6
-#define PYX_TRANSPORT_UNKNOWN_MODE_PAGE		-7
-#define PYX_TRANSPORT_WRITE_PROTECTED		-8
-#define PYX_TRANSPORT_TASK_TIMEOUT		-9
+#define PYX_TRANSPORT_INVALID_PARAMETER_LIST	-6
+#define PYX_TRANSPORT_LOGICAL_UNIT_COMMUNICATION_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
 
 #ifndef SAM_STAT_RESERVATION_CONFLICT
 #define SAM_STAT_RESERVATION_CONFLICT		0x18
@@ -89,6 +91,8 @@
 #define DF_PERSISTENT_CLAIMED_BLOCKDEV		0x00000020
 #define DF_DISABLE_STATUS_THREAD		0x00000040
 #define DF_READ_ONLY				0x00000080
+#define DF_SPC3_PERSISTENT_RESERVE		0x00000100
+#define DF_SPC2_RESERVATIONS			0x00000200
 
 /* se_dev_attrib_t sanity values */
 #define DA_TASK_TIMEOUT_MAX			600 /* 10 Minutes, see transport_get_default_task_timeout()  */
@@ -189,7 +193,7 @@ extern void transport_release_fe_cmd (se_cmd_t *);
 extern int transport_generic_remove (se_cmd_t *, int, int);
 extern int transport_lun_wait_for_tasks (se_cmd_t *, se_lun_t *);
 extern void transport_clear_lun_from_sessions (se_lun_t *);
-extern int iscsi_send_check_condition_and_sense (se_cmd_t *, __u8, int);
+extern int transport_send_check_condition_and_sense (se_cmd_t *, __u8, int);
 extern void transport_release_cmd_to_pool (se_cmd_t *);
 extern void transport_generic_free_cmd (se_cmd_t *, int, int, int);
 extern void transport_generic_wait_for_cmds (se_cmd_t *, int);
-- 
1.5.4.1



--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux