Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca2d02c2 authored by Heiko Carstens's avatar Heiko Carstens Committed by James Bottomley
Browse files

[SCSI] zfcp: rework request ID management.



Simplify request ID management and make sure that frequently used
functions are inlined. Also fix a memory leak in zfcp_adapter_enqueue()
which only gets hit in error handling.

Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarSwen Schillig <swen@vnet.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 5f852be9
Loading
Loading
Loading
Loading
+9 −73
Original line number Diff line number Diff line
@@ -118,97 +118,32 @@ _zfcp_hex_dump(char *addr, int count)

#define ZFCP_LOG_AREA			ZFCP_LOG_AREA_FSF

static int zfcp_reqlist_init(struct zfcp_adapter *adapter)
static int zfcp_reqlist_alloc(struct zfcp_adapter *adapter)
{
	int i;
	int idx;

	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]);

	for (idx = 0; idx < REQUEST_LIST_SIZE; idx++)
		INIT_LIST_HEAD(&adapter->req_list[idx]);
	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;

	/* 0 is reserved as an invalid req_id */
	if (req_id == 0)
		return NULL;

	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;
	unsigned int idx;

	for (i=0; i<REQUEST_LIST_SIZE; i++)
		if (!list_empty(&adapter->req_list[i]))
	for (idx = 0; idx < REQUEST_LIST_SIZE; idx++)
		if (!list_empty(&adapter->req_list[idx]))
			return 0;

	return 1;
}

@@ -1106,7 +1041,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)

	/* initialize list of fsf requests */
	spin_lock_init(&adapter->req_list_lock);
	retval = zfcp_reqlist_init(adapter);
	retval = zfcp_reqlist_alloc(adapter);
	if (retval) {
		ZFCP_LOG_INFO("request list initialization failed\n");
		goto failed_low_mem_buffers;
@@ -1167,6 +1102,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
	zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
 sysfs_failed:
	dev_set_drvdata(&ccw_device->dev, NULL);
	zfcp_reqlist_free(adapter);
 failed_low_mem_buffers:
	zfcp_free_low_mem_buffers(adapter);
	if (qdio_free(ccw_device) != 0)
+36 −0
Original line number Diff line number Diff line
@@ -1089,6 +1089,42 @@ extern void _zfcp_hex_dump(char *, int);
#define zfcp_get_busid_by_port(port) (zfcp_get_busid_by_adapter(port->adapter))
#define zfcp_get_busid_by_unit(unit) (zfcp_get_busid_by_port(unit->port))

/*
 * Helper functions for request ID management.
 */
static inline int zfcp_reqlist_hash(unsigned long req_id)
{
	return req_id % REQUEST_LIST_SIZE;
}

static inline void zfcp_reqlist_add(struct zfcp_adapter *adapter,
				    struct zfcp_fsf_req *fsf_req)
{
	unsigned int idx;

	idx = zfcp_reqlist_hash(fsf_req->req_id);
	list_add_tail(&fsf_req->list, &adapter->req_list[idx]);
}

static inline void zfcp_reqlist_remove(struct zfcp_adapter *adapter,
				       struct zfcp_fsf_req *fsf_req)
{
	list_del(&fsf_req->list);
}

static inline struct zfcp_fsf_req *
zfcp_reqlist_find(struct zfcp_adapter *adapter, unsigned long req_id)
{
	struct zfcp_fsf_req *request;
	unsigned int idx;

	idx = zfcp_reqlist_hash(req_id);
	list_for_each_entry(request, &adapter->req_list[idx], list)
		if (request->req_id == req_id)
			return request;
	return NULL;
}

/*
 *  functions needed for reference/usage counting
 */
+1 −2
Original line number Diff line number Diff line
@@ -847,8 +847,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
	if (erp_action->fsf_req) {
		/* 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)) {
		if (zfcp_reqlist_find(adapter, erp_action->fsf_req->req_id)) {
			/* fsf_req still exists */
			debug_text_event(adapter->erp_dbf, 3, "a_ca_req");
			debug_event(adapter->erp_dbf, 3, &erp_action->fsf_req,
+0 −4
Original line number Diff line number Diff line
@@ -184,10 +184,6 @@ extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
				      unsigned long);
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 */
+1 −1
Original line number Diff line number Diff line
@@ -4787,7 +4787,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req)
		retval = -EIO;
		del_timer(&fsf_req->timer);
		spin_lock(&adapter->req_list_lock);
		zfcp_reqlist_remove(adapter, fsf_req->req_id);
		zfcp_reqlist_remove(adapter, fsf_req);
		spin_unlock(&adapter->req_list_lock);
		/* undo changes in request queue made for this request */
		zfcp_qdio_zero_sbals(req_queue->buffer,
Loading