Skip to contentSkip to conversation

zfcp: improve management of request IDs

PATCH New Andreas Herrmann 1 participant 1 message Aug 2, 2006

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/3 zfcp: improve management of request IDs

From: Volker Sameske <[email protected]>

Improve request handling. Use hash table to manage request IDs.

---
 drivers/s390/scsi/zfcp_aux.c  |  120 +++++++++++++++++++++++++++++++++++++---
 drivers/s390/scsi/zfcp_ccw.c  |    5 ++
 drivers/s390/scsi/zfcp_def.h  |   11 ++--
 drivers/s390/scsi/zfcp_erp.c  |   16 ++---
 drivers/s390/scsi/zfcp_ext.h  |    6 ++
 drivers/s390/scsi/zfcp_fsf.c  |  122 ++++++++++++++++++++++-------------------
 drivers/s390/scsi/zfcp_qdio.c |   79 +++++++++++----------------
 7 files changed, 231 insertions(+), 128 deletions(-)
drivers/s390/scsi/zfcp_aux.c +111 -9
index 9cd789b..adc9d8f 100644
@@ -112,6 +112,105 @@ _zfcp_hex_dump(char *addr, int count)
 		printk("\n");
 }
 
+
+/****************************************************************/
+/****** Functions to handle the request ID hash table    ********/
+/****************************************************************/
+
+#define ZFCP_LOG_AREA			ZFCP_LOG_AREA_FSF
+
+static int zfcp_reqlist_init(struct zfcp_adapter *adapter)
+{
+	int i;
+
+	adapter->req_list = kcalloc(REQUEST_LIST_SIZE, sizeof(struct list_head),
+				    GFP_KERNEL);
+
+	if (!adapter->req_list)
+		return -ENOMEM;
+
+	for (i=0; i<REQUEST_LIST_SIZE; i++)
+		INIT_LIST_HEAD(&adapter->req_list[i]);
+
+	return 0;
+}
+
+static void zfcp_reqlist_free(struct zfcp_adapter *adapter)
+{
+	struct zfcp_fsf_req *request, *tmp;
+	unsigned int i;
+
+	for (i=0; i<REQUEST_LIST_SIZE; i++) {
+		if (list_empty(&adapter->req_list[i]))
+			continue;
+
+		list_for_each_entry_safe(request, tmp,
+					 &adapter->req_list[i], list)
+			list_del(&request->list);
+	}
+
+	kfree(adapter->req_list);
+}
+
+void zfcp_reqlist_add(struct zfcp_adapter *adapter,
+		      struct zfcp_fsf_req *fsf_req)
+{
+	unsigned int i;
+
+	i = fsf_req->req_id % REQUEST_LIST_SIZE;
+	list_add_tail(&fsf_req->list, &adapter->req_list[i]);
+}
+
+void zfcp_reqlist_remove(struct zfcp_adapter *adapter, unsigned long req_id)
+{
+	struct zfcp_fsf_req *request, *tmp;
+	unsigned int i, counter;
+	u64 dbg_tmp[2];
+
+	i = req_id % REQUEST_LIST_SIZE;
+	BUG_ON(list_empty(&adapter->req_list[i]));
+
+	counter = 0;
+	list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list) {
+		if (request->req_id == req_id) {
+			dbg_tmp[0] = (u64) atomic_read(&adapter->reqs_active);
+			dbg_tmp[1] = (u64) counter;
+			debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16);
+			list_del(&request->list);
+			break;
+		}
+		counter++;
+	}
+}
+
+struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *adapter,
+					   unsigned long req_id)
+{
+	struct zfcp_fsf_req *request, *tmp;
+	unsigned int i;
+
+	i = req_id % REQUEST_LIST_SIZE;
+
+	list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list)
+		if (request->req_id == req_id)
+			return request;
+
+	return NULL;
+}
+
+int zfcp_reqlist_isempty(struct zfcp_adapter *adapter)
+{
+	unsigned int i;
+
+	for (i=0; i<REQUEST_LIST_SIZE; i++)
+		if (!list_empty(&adapter->req_list[i]))
+			return 0;
+
+	return 1;
+}
+
+#undef ZFCP_LOG_AREA
+
 /****************************************************************/
 /************** Uncategorised Functions *************************/
 /****************************************************************/
@@ -961,8 +1060,12 @@ zfcp_adapter_enqueue(struct ccw_device *
 	INIT_LIST_HEAD(&adapter->port_remove_lh);
 
 	/* initialize list of fsf requests */
-	spin_lock_init(&adapter->fsf_req_list_lock);
-	INIT_LIST_HEAD(&adapter->fsf_req_list_head);
+	spin_lock_init(&adapter->req_list_lock);
+	retval = zfcp_reqlist_init(adapter);
+	if (retval) {
+		ZFCP_LOG_INFO("request list initialization failed\n");
+		goto failed_low_mem_buffers;
+	}
 
 	/* initialize debug locks */
 
@@ -1041,8 +1144,6 @@ zfcp_adapter_enqueue(struct ccw_device *
  *		!0 - struct zfcp_adapter  data structure could not be removed
  *			(e.g. still used)
  * locks:	adapter list write lock is assumed to be held by caller
- *              adapter->fsf_req_list_lock is taken and released within this 
- *              function and must not be held on entry
  */
 void
 zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
@@ -1054,14 +1155,14 @@ zfcp_adapter_dequeue(struct zfcp_adapter
 	zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
 	dev_set_drvdata(&adapter->ccw_device->dev, NULL);
 	/* sanity check: no pending FSF requests */
-	spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
-	retval = !list_empty(&adapter->fsf_req_list_head);
-	spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
-	if (retval) {
+	spin_lock_irqsave(&adapter->req_list_lock, flags);
+	retval = zfcp_reqlist_isempty(adapter);
+	spin_unlock_irqrestore(&adapter->req_list_lock, flags);
+	if (!retval) {
 		ZFCP_LOG_NORMAL("bug: adapter %s (%p) still in use, "
 				"%i requests outstanding\n",
 				zfcp_get_busid_by_adapter(adapter), adapter,
-				atomic_read(&adapter->fsf_reqs_active));
+				atomic_read(&adapter->reqs_active));
 		retval = -EBUSY;
 		goto out;
 	}
@@ -1087,6 +1188,7 @@ zfcp_adapter_dequeue(struct zfcp_adapter
 	zfcp_free_low_mem_buffers(adapter);
 	/* free memory of adapter data structure and queues */
 	zfcp_qdio_free_queues(adapter);
+	zfcp_reqlist_free(adapter);
 	kfree(adapter->fc_stats);
 	kfree(adapter->stats_reset_data);
 	ZFCP_LOG_TRACE("freeing adapter structure\n");
drivers/s390/scsi/zfcp_ccw.c +5 -0
index 57d8e4b..fdabade 100644
@@ -164,6 +164,11 @@ zfcp_ccw_set_online(struct ccw_device *c
 	retval = zfcp_adapter_scsi_register(adapter);
 	if (retval)
 		goto out_scsi_register;
+
+	/* initialize request counter */
+	BUG_ON(!zfcp_reqlist_isempty(adapter));
+	adapter->req_no = 0;
+
 	zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING,
 				       ZFCP_SET);
 	zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
drivers/s390/scsi/zfcp_def.h +6 -5
index 2df512a..72293f3 100644
@@ -886,11 +886,11 @@ struct zfcp_adapter {
 	struct list_head        port_remove_lh;    /* head of ports to be
 						      removed */
 	u32			ports;	           /* number of remote ports */
-        struct timer_list       scsi_er_timer;     /* SCSI err recovery watch */
-	struct list_head	fsf_req_list_head; /* head of FSF req list */
-	spinlock_t		fsf_req_list_lock; /* lock for ops on list of
-						      FSF requests */
-        atomic_t       		fsf_reqs_active;   /* # active FSF reqs */
+	struct timer_list	scsi_er_timer;     /* SCSI err recovery watch */
+	atomic_t		reqs_active;	   /* # active FSF reqs */
+	unsigned long		req_no;		   /* unique FSF req number */
+	struct list_head	*req_list;	   /* list of pending reqs */
+	spinlock_t		req_list_lock;	   /* request list lock */
 	struct zfcp_qdio_queue	request_queue;	   /* request queue */
 	u32			fsf_req_seq_no;	   /* FSF cmnd seq number */
 	wait_queue_head_t	request_wq;	   /* can be used to wait for
@@ -986,6 +986,7 @@ struct zfcp_unit {
 /* FSF request */
 struct zfcp_fsf_req {
 	struct list_head       list;	       /* list of FSF requests */
+	unsigned long	       req_id;	       /* unique request ID */
 	struct zfcp_adapter    *adapter;       /* adapter request belongs to */
 	u8		       sbal_number;    /* nr of SBALs free for use */
 	u8		       sbal_first;     /* first SBAL for this request */
drivers/s390/scsi/zfcp_erp.c +7 -9
index 8ec8da0..f74412b 100644
@@ -848,18 +848,16 @@ zfcp_erp_strategy_check_fsfreq(struct zf
 	struct zfcp_adapter *adapter = erp_action->adapter;
 
 	if (erp_action->fsf_req) {
-		/* take lock to ensure that request is not being deleted meanwhile */
-		spin_lock(&adapter->fsf_req_list_lock);
-		/* check whether fsf req does still exist */
-		list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list)
-		    if (fsf_req == erp_action->fsf_req)
-			break;
-		if (fsf_req && (fsf_req->erp_action == erp_action)) {
+		/* take lock to ensure that request is not deleted meanwhile */
+		spin_lock(&adapter->req_list_lock);
+		if ((!zfcp_reqlist_ismember(adapter,
+					    erp_action->fsf_req->req_id)) &&
+		    (fsf_req->erp_action == erp_action)) {
 			/* fsf_req still exists */
 			debug_text_event(adapter->erp_dbf, 3, "a_ca_req");
 			debug_event(adapter->erp_dbf, 3, &fsf_req,
 				    sizeof (unsigned long));
-			/* dismiss fsf_req of timed out or dismissed erp_action */
+			/* dismiss fsf_req of timed out/dismissed erp_action */
 			if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED |
 						  ZFCP_STATUS_ERP_TIMEDOUT)) {
 				debug_text_event(adapter->erp_dbf, 3,
@@ -892,7 +890,7 @@ zfcp_erp_strategy_check_fsfreq(struct zf
 			 */
 			erp_action->fsf_req = NULL;
 		}
-		spin_unlock(&adapter->fsf_req_list_lock);
+		spin_unlock(&adapter->req_list_lock);
 	} else
 		debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq");
 
drivers/s390/scsi/zfcp_ext.h +5 -1
index d023660..04bb3a9 100644
@@ -63,7 +63,6 @@ extern int  zfcp_qdio_allocate_queues(st
 extern void zfcp_qdio_free_queues(struct zfcp_adapter *);
 extern int  zfcp_qdio_determine_pci(struct zfcp_qdio_queue *,
 				    struct zfcp_fsf_req *);
-extern int  zfcp_qdio_reqid_check(struct zfcp_adapter *, void *);
 
 extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_req
 	(struct zfcp_fsf_req *, int, int);
@@ -190,5 +189,10 @@ extern void zfcp_scsi_dbf_event_abort(co
 				      struct zfcp_fsf_req *);
 extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
 					 struct scsi_cmnd *);
+extern void zfcp_reqlist_add(struct zfcp_adapter *, struct zfcp_fsf_req *);
+extern void zfcp_reqlist_remove(struct zfcp_adapter *, unsigned long);
+extern struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *,
+						  unsigned long);
+extern int zfcp_reqlist_isempty(struct zfcp_adapter *);
 
 #endif	/* ZFCP_EXT_H */
drivers/s390/scsi/zfcp_fsf.c +65 -57

202 lines not on this page · raw message

drivers/s390/scsi/zfcp_qdio.c +32 -47

97 lines not on this page · raw message

Signature · 1 line
1.4.2.rc2.gef1d9