[PATCH 2/2] bsg: convert bsg to use the generic ring buffer code

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

 



This converts bsg to use the generic ring buffer code.

A new data structure, bsg_fd, is introduced to let each process to
have its own ring buffers (that is, several ring buffer pairs could be
attached to one bsg device).


Signed-off-by: FUJITA Tomonori <fujita.tomonori@xxxxxxxxxxxxx>
---
 block/bsg.c |  252 ++++++++++++++++++++++++++--------------------------------
 1 files changed, 113 insertions(+), 139 deletions(-)

diff --git a/block/bsg.c b/block/bsg.c
index c85d961..1ce35d3 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -25,6 +25,8 @@ #include <linux/cdev.h>
 #include <linux/percpu.h>
 #include <linux/uio.h>
 #include <linux/bsg.h>
+#include <linux/eventchannel.h>
+#include <linux/eventchannel_if.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_ioctl.h>
@@ -51,6 +53,11 @@ struct bsg_device {
 	unsigned long flags;
 };
 
+struct bsg_fd {
+	struct bsg_device *bd;
+	struct ec_info *eci;
+};
+
 enum {
 	BSG_F_BLOCK		= 1,
 	BSG_F_WRITE_PERM	= 2,
@@ -418,7 +425,7 @@ static struct bsg_command *__bsg_get_don
 }
 
 static struct bsg_command *
-bsg_get_done_cmd(struct bsg_device *bd, const struct iovec *iov)
+bsg_get_done_cmd(struct bsg_device *bd)
 {
 	return __bsg_get_done_cmd(bd, TASK_INTERRUPTIBLE);
 }
@@ -519,46 +526,28 @@ static int bsg_complete_all_commands(str
 
 typedef struct bsg_command *(*bsg_command_callback)(struct bsg_device *bd, const struct iovec *iov);
 
-static ssize_t
-__bsg_read(char __user *buf, size_t count, bsg_command_callback get_bc,
-	   struct bsg_device *bd, const struct iovec *iov, ssize_t *bytes_read)
+static int bsg_send_response(struct file *file, char __user *buf)
 {
+	struct bsg_fd *bf = file->private_data;
+	struct bsg_device *bd = bf->bd;
 	struct bsg_command *bc;
-	int nr_commands, ret;
-
-	if (count % sizeof(struct sg_io_v4))
-		return -EINVAL;
-
-	ret = 0;
-	nr_commands = count / sizeof(struct sg_io_v4);
-	while (nr_commands) {
-		bc = get_bc(bd, iov);
-		if (IS_ERR(bc)) {
-			ret = PTR_ERR(bc);
-			break;
-		}
-
-		/*
-		 * this is the only case where we need to copy data back
-		 * after completing the request. so do that here,
-		 * bsg_complete_work() cannot do that for us
-		 */
-		ret = blk_complete_sgv4_hdr_rq(bc->rq, &bc->hdr, bc->bio);
-
-		if (copy_to_user(buf, (char *) &bc->hdr, sizeof(bc->hdr)))
-			ret = -EFAULT;
+	int ret;
 
-		bsg_free_command(bc);
+	bc = bsg_get_done_cmd(bd);
+	if (IS_ERR(bc))
+		return 1;
 
-		if (ret)
-			break;
+	/*
+	 * this is the only case where we need to copy data back
+	 * after completing the request. so do that here,
+	 * bsg_complete_work() cannot do that for us
+	 */
+	ret = blk_complete_sgv4_hdr_rq(bc->rq, &bc->hdr, bc->bio);
 
-		buf += sizeof(struct sg_io_v4);
-		*bytes_read += sizeof(struct sg_io_v4);
-		nr_commands--;
-	}
+	ret = copy_to_user(buf, (char *) &bc->hdr, sizeof(bc->hdr));
 
-	return ret;
+	bsg_free_command(bc);
+	return 0;
 }
 
 static inline void bsg_set_block(struct bsg_device *bd, struct file *file)
@@ -585,107 +574,59 @@ static inline int err_block_err(int ret)
 	return 0;
 }
 
-static ssize_t
-bsg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+static int bsg_prepare_send_response(struct file *file)
 {
-	struct bsg_device *bd = file->private_data;
-	int ret;
-	ssize_t bytes_read;
+	struct bsg_fd *bf = file->private_data;
+	struct bsg_device *bd = bf->bd;
 
-	dprintk("%s: read %Zd bytes\n", bd->name, count);
+	dprintk("%s: read\n", bd->name);
 
 	bsg_set_block(bd, file);
-	bytes_read = 0;
-	ret = __bsg_read(buf, count, bsg_get_done_cmd,
-			bd, NULL, &bytes_read);
-	*ppos = bytes_read;
-
-	if (!bytes_read || (bytes_read && err_block_err(ret)))
-		bytes_read = ret;
-
-	return bytes_read;
+	return 0;
 }
 
-static ssize_t __bsg_write(struct bsg_device *bd, const char __user *buf,
-			   size_t count, ssize_t *bytes_read)
+static int bsg_recv_request(struct file *file, char __user *buf)
 {
+	struct bsg_fd *bf = file->private_data;
+	struct bsg_device *bd = bf->bd;
 	struct bsg_command *bc;
 	struct request *rq;
-	int ret, nr_commands;
-
-	if (count % sizeof(struct sg_io_v4))
-		return -EINVAL;
-
-	nr_commands = count / sizeof(struct sg_io_v4);
-	rq = NULL;
-	bc = NULL;
-	ret = 0;
-	while (nr_commands) {
-		request_queue_t *q = bd->queue;
+	request_queue_t *q = bd->queue;
 
-		bc = bsg_get_command(bd);
-		if (!bc)
-			break;
-		if (IS_ERR(bc)) {
-			ret = PTR_ERR(bc);
-			bc = NULL;
-			break;
-		}
+	bc = bsg_get_command(bd);
+	if (!bc)
+		return ENOMEM;
 
-		bc->uhdr = (struct sg_io_v4 __user *) buf;
-		if (copy_from_user(&bc->hdr, buf, sizeof(bc->hdr))) {
-			ret = -EFAULT;
-			break;
-		}
+	if (IS_ERR(bc))
+		return PTR_ERR(bc);
 
-		/*
-		 * get a request, fill in the blanks, and add to request queue
-		 */
-		rq = bsg_map_hdr(bd, &bc->hdr);
-		if (IS_ERR(rq)) {
-			ret = PTR_ERR(rq);
-			rq = NULL;
-			break;
-		}
-
-		bsg_add_command(bd, q, bc, rq);
-		bc = NULL;
-		rq = NULL;
-		nr_commands--;
-		buf += sizeof(struct sg_io_v4);
-		*bytes_read += sizeof(struct sg_io_v4);
+	bc->uhdr = (struct sg_io_v4 __user *) buf;
+	if (copy_from_user(&bc->hdr, buf, sizeof(bc->hdr))) {
+		bsg_free_command(bc);
+		return EFAULT;
 	}
 
-	if (bc)
+	rq = bsg_map_hdr(bd, &bc->hdr);
+	if (IS_ERR(rq)) {
 		bsg_free_command(bc);
+		return PTR_ERR(rq);
+	}
 
-	return ret;
+	bsg_add_command(bd, q, bc, rq);
+
+	return 0;
 }
 
-static ssize_t
-bsg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+static int bsg_prepare_recv_request(struct file *file)
 {
-	struct bsg_device *bd = file->private_data;
-	ssize_t bytes_read;
-	int ret;
+	struct bsg_fd *bf = file->private_data;
+	struct bsg_device *bd = bf->bd;
 
-	dprintk("%s: write %Zd bytes\n", bd->name, count);
+	dprintk("%s write\n", bd->name);
 
 	bsg_set_block(bd, file);
 	bsg_set_write_perm(bd, file);
-
-	bytes_read = 0;
-	ret = __bsg_write(bd, buf, count, &bytes_read);
-	*ppos = bytes_read;
-
-	/*
-	 * return bytes written on non-fatal errors
-	 */
-	if (!bytes_read || (bytes_read && err_block_err(ret)))
-		bytes_read = ret;
-
-	dprintk("%s: returning %Zd\n", bd->name, bytes_read);
-	return bytes_read;
+	return 0;
 }
 
 static struct bsg_device *bsg_alloc_device(void)
@@ -822,46 +763,42 @@ static struct bsg_device *bsg_get_device
 
 static int bsg_open(struct inode *inode, struct file *file)
 {
-	struct bsg_device *bd = bsg_get_device(inode, file);
+	struct bsg_device *bd;
+	struct bsg_fd *bf;
+
+	bf = kzalloc(sizeof(*bf), GFP_KERNEL);
+	if (!bf)
+		return -ENOMEM;
 
-	if (IS_ERR(bd))
+	bd = bsg_get_device(inode, file);
+	if (IS_ERR(bd)) {
+		kfree(bf);
 		return PTR_ERR(bd);
+	}
 
-	file->private_data = bd;
+	bf->bd = bd;
+	file->private_data = bf;
 	return 0;
 }
 
 static int bsg_release(struct inode *inode, struct file *file)
 {
-	struct bsg_device *bd = file->private_data;
+	struct bsg_fd *bf = file->private_data;
+	struct bsg_device *bd = bf->bd;
 
 	file->private_data = NULL;
+	if (bf->eci)
+		ec_info_free(bf->eci);
+	kfree(bf);
 	return bsg_put_device(bd);
 }
 
-static unsigned int bsg_poll(struct file *file, poll_table *wait)
-{
-	struct bsg_device *bd = file->private_data;
-	unsigned int mask = 0;
-
-	poll_wait(file, &bd->wq_done, wait);
-	poll_wait(file, &bd->wq_free, wait);
-
-	spin_lock_irq(&bd->lock);
-	if (!list_empty(&bd->done_list))
-		mask |= POLLIN | POLLRDNORM;
-	if (bd->queued_cmds >= bd->max_queue)
-		mask |= POLLOUT;
-	spin_unlock_irq(&bd->lock);
-
-	return mask;
-}
-
 static int
 bsg_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	  unsigned long arg)
 {
-	struct bsg_device *bd = file->private_data;
+	struct bsg_fd *bf = file->private_data;
+	struct bsg_device *bd = bf->bd;
 	int __user *uarg = (int __user *) arg;
 
 	if (!bd)
@@ -936,9 +873,6 @@ #endif
 }
 
 static struct file_operations bsg_fops = {
-	.read		=	bsg_read,
-	.write		=	bsg_write,
-	.poll		=	bsg_poll,
 	.open		=	bsg_open,
 	.release	=	bsg_release,
 	.ioctl		=	bsg_ioctl,
@@ -997,10 +931,50 @@ err:
 	return -ENOMEM;
 }
 
+static int bsg_ec_init(struct file *file, struct ec_ring __user *kupring,
+		       struct ec_ring __user *ukpring, unsigned int num,
+		       unsigned int flags)
+{
+	struct bsg_fd *bf = file->private_data;
+	struct bsg_device *bd = bf->bd;
+	struct ec_info *eci;
+
+	if (bf->eci)
+		return -EINVAL;
+
+	eci = ec_info_alloc(kupring, &bd->wq_done, &bd->done_cmds,
+			    ukpring, NULL, NULL,
+			    num, flags);
+	if (!eci)
+		return -ENOMEM;
+
+	bf->eci = eci;
+	return 0;
+}
+
+static struct ec_info *bsg_file_to_ecinfo(struct file *file)
+{
+	return ((struct bsg_fd *) (file->private_data))->eci;
+}
+
+static struct ec_operations bsg_ec_ops = {
+	.ec_init			=	bsg_ec_init,
+	.file_to_ecinfo			=	bsg_file_to_ecinfo,
+	.prepare_send_event_to_user	=	bsg_prepare_send_response,
+	.send_event_to_user		=	bsg_send_response,
+	.prepare_recv_event_from_user	=	bsg_prepare_recv_request,
+	.recv_event_from_user		=	bsg_recv_request,
+};
+
 static int __init bsg_init(void)
 {
 	int ret, i;
 
+	ret = ec_register(EC_TYPE_BSG, sizeof(struct sg_io_v4), &bsg_ec_ops,
+			  &bsg_fops);
+	if (ret)
+		return -EINVAL;
+
 	bsg_cmd_cachep = kmem_cache_create("bsg_cmd",
 				sizeof(struct bsg_command), 0, 0, NULL, NULL);
 	if (!bsg_cmd_cachep) {
-- 
1.4.3.2

-
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