diff options
| author | Stefani Seibold <stefani@seibold.net> | 2009-12-21 14:37:26 -0800 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-22 14:17:55 -0800 | 
| commit | 45465487897a1c6d508b14b904dc5777f7ec7e04 (patch) | |
| tree | 935c8dae68dc793ff2f795d57cf027531475cd53 /drivers/scsi/libiscsi_tcp.c | |
| parent | 2ec91eec47f713e3d158ba5b28a24a85a2cf3650 (diff) | |
kfifo: move struct kfifo in place
This is a new generic kernel FIFO implementation.
The current kernel fifo API is not very widely used, because it has to
many constrains.  Only 17 files in the current 2.6.31-rc5 used it.
FIFO's are like list's a very basic thing and a kfifo API which handles
the most use case would save a lot of development time and memory
resources.
I think this are the reasons why kfifo is not in use:
 - The API is to simple, important functions are missing
 - A fifo can be only allocated dynamically
 - There is a requirement of a spinlock whether you need it or not
 - There is no support for data records inside a fifo
So I decided to extend the kfifo in a more generic way without blowing up
the API to much.  The new API has the following benefits:
 - Generic usage: For kernel internal use and/or device driver.
 - Provide an API for the most use case.
 - Slim API: The whole API provides 25 functions.
 - Linux style habit.
 - DECLARE_KFIFO, DEFINE_KFIFO and INIT_KFIFO Macros
 - Direct copy_to_user from the fifo and copy_from_user into the fifo.
 - The kfifo itself is an in place member of the using data structure, this save an
   indirection access and does not waste the kernel allocator.
 - Lockless access: if only one reader and one writer is active on the fifo,
   which is the common use case, no additional locking is necessary.
 - Remove spinlock - give the user the freedom of choice what kind of locking to use if
   one is required.
 - Ability to handle records. Three type of records are supported:
   - Variable length records between 0-255 bytes, with a record size
     field of 1 bytes.
   - Variable length records between 0-65535 bytes, with a record size
     field of 2 bytes.
   - Fixed size records, which no record size field.
 - Preserve memory resource.
 - Performance!
 - Easy to use!
This patch:
Since most users want to have the kfifo as part of another object,
reorganize the code to allow including struct kfifo in another data
structure.  This requires changing the kfifo_alloc and kfifo_init
prototypes so that we pass an existing kfifo pointer into them.  This
patch changes the implementation and all existing users.
[akpm@linux-foundation.org: fix warning]
Signed-off-by: Stefani Seibold <stefani@seibold.net>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/scsi/libiscsi_tcp.c')
| -rw-r--r-- | drivers/scsi/libiscsi_tcp.c | 29 | 
1 files changed, 14 insertions, 15 deletions
| diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index ca25ee5190b0..a83ee56a185e 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -445,15 +445,15 @@ void iscsi_tcp_cleanup_task(struct iscsi_task *task)  		return;  	/* flush task's r2t queues */ -	while (__kfifo_get(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) { -		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t, +	while (__kfifo_get(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) { +		__kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t,  			    sizeof(void*));  		ISCSI_DBG_TCP(task->conn, "pending r2t dropped\n");  	}  	r2t = tcp_task->r2t;  	if (r2t != NULL) { -		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t, +		__kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t,  			    sizeof(void*));  		tcp_task->r2t = NULL;  	} @@ -541,7 +541,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)  		return 0;  	} -	rc = __kfifo_get(tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); +	rc = __kfifo_get(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*));  	if (!rc) {  		iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. "  				  "Target has sent more R2Ts than it " @@ -554,7 +554,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)  	if (r2t->data_length == 0) {  		iscsi_conn_printk(KERN_ERR, conn,  				  "invalid R2T with zero data len\n"); -		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t, +		__kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t,  			    sizeof(void*));  		return ISCSI_ERR_DATALEN;  	} @@ -570,7 +570,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)  				  "invalid R2T with data len %u at offset %u "  				  "and total length %d\n", r2t->data_length,  				  r2t->data_offset, scsi_out(task->sc)->length); -		__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t, +		__kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t,  			    sizeof(void*));  		return ISCSI_ERR_DATALEN;  	} @@ -580,7 +580,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)  	r2t->sent = 0;  	tcp_task->exp_datasn = r2tsn + 1; -	__kfifo_put(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*)); +	__kfifo_put(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*));  	conn->r2t_pdus_cnt++;  	iscsi_requeue_task(task); @@ -951,7 +951,7 @@ int iscsi_tcp_task_init(struct iscsi_task *task)  		return conn->session->tt->init_pdu(task, 0, task->data_count);  	} -	BUG_ON(__kfifo_len(tcp_task->r2tqueue)); +	BUG_ON(__kfifo_len(&tcp_task->r2tqueue));  	tcp_task->exp_datasn = 0;  	/* Prepare PDU, optionally w/ immediate data */ @@ -982,7 +982,7 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task)  			if (r2t->data_length <= r2t->sent) {  				ISCSI_DBG_TCP(task->conn,  					      "  done with r2t %p\n", r2t); -				__kfifo_put(tcp_task->r2tpool.queue, +				__kfifo_put(&tcp_task->r2tpool.queue,  					    (void *)&tcp_task->r2t,  					    sizeof(void *));  				tcp_task->r2t = r2t = NULL; @@ -990,7 +990,7 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task)  		}  		if (r2t == NULL) { -			__kfifo_get(tcp_task->r2tqueue, +			__kfifo_get(&tcp_task->r2tqueue,  				    (void *)&tcp_task->r2t, sizeof(void *));  			r2t = tcp_task->r2t;  		} @@ -1127,9 +1127,8 @@ int iscsi_tcp_r2tpool_alloc(struct iscsi_session *session)  		}  		/* R2T xmit queue */ -		tcp_task->r2tqueue = kfifo_alloc( -		      session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL); -		if (tcp_task->r2tqueue == ERR_PTR(-ENOMEM)) { +		if (kfifo_alloc(&tcp_task->r2tqueue, +		      session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL)) {  			iscsi_pool_free(&tcp_task->r2tpool);  			goto r2t_alloc_fail;  		} @@ -1142,7 +1141,7 @@ r2t_alloc_fail:  		struct iscsi_task *task = session->cmds[i];  		struct iscsi_tcp_task *tcp_task = task->dd_data; -		kfifo_free(tcp_task->r2tqueue); +		kfifo_free(&tcp_task->r2tqueue);  		iscsi_pool_free(&tcp_task->r2tpool);  	}  	return -ENOMEM; @@ -1157,7 +1156,7 @@ void iscsi_tcp_r2tpool_free(struct iscsi_session *session)  		struct iscsi_task *task = session->cmds[i];  		struct iscsi_tcp_task *tcp_task = task->dd_data; -		kfifo_free(tcp_task->r2tqueue); +		kfifo_free(&tcp_task->r2tqueue);  		iscsi_pool_free(&tcp_task->r2tpool);  	}  } | 
