Linux virtualization list
 help / color / mirror / Atom feed
* Re: [GIT PULL net-2.6] vhost-net: rcu fixup
From: David Miller @ 2010-11-28 19:27 UTC (permalink / raw)
  To: mst; +Cc: kvm, virtualization, netdev, linux-kernel
In-Reply-To: <20101125122301.GA15990@redhat.com>

From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Thu, 25 Nov 2010 14:23:01 +0200

> Please merge the following fix for 2.6.36.
> Thanks!
> 
> The following changes since commit a27e13d370415add3487949c60810e36069a23a6:
> 
>   econet: fix CVE-2010-3848 (2010-11-24 11:51:47 -0800)
> 
> are available in the git repository at:
>   git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git vhost-net
> 
> Michael S. Tsirkin (1):
>       vhost/net: fix rcu check usage
> 

Pulled, thanks Michael.

^ permalink raw reply

* [PATCH] vhost: correctly set bits of dirty pages
From: Jason Wang @ 2010-11-29  5:48 UTC (permalink / raw)
  To: virtualization, netdev, linux-kernel, kvm, mst

When counting pages we should increase it by 1 instead of VHOST_PAGE_SIZE,
and also make log_write() can correctly process the request across
pages with write_address not start at page boundary.

Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 drivers/vhost/vhost.c |   20 +++++++++-----------
 1 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index a29d91c..576300b 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -884,23 +884,21 @@ static int set_bit_to_user(int nr, void __user *addr)
 static int log_write(void __user *log_base,
 		     u64 write_address, u64 write_length)
 {
-	int r;
-	if (!write_length)
-		return 0;
-	write_address /= VHOST_PAGE_SIZE;
-	for (;;) {
+	int r = 0;
+	while (write_length > 0) {
+		u64 l = VHOST_PAGE_SIZE - write_address % VHOST_PAGE_SIZE;
+		u64 write_page = write_address / VHOST_PAGE_SIZE;
 		u64 base = (u64)(unsigned long)log_base;
-		u64 log = base + write_address / 8;
-		int bit = write_address % 8;
+		u64 log = base + write_page / 8;
+		int bit = write_page % 8;
 		if ((u64)(unsigned long)log != log)
 			return -EFAULT;
 		r = set_bit_to_user(bit, (void __user *)(unsigned long)log);
 		if (r < 0)
 			return r;
-		if (write_length <= VHOST_PAGE_SIZE)
-			break;
-		write_length -= VHOST_PAGE_SIZE;
-		write_address += VHOST_PAGE_SIZE;
+		l = min(l, write_length);
+		write_length -= l;
+		write_address += l;
 	}
 	return r;
 }

^ permalink raw reply related

* [PATCH] vhost: fix typos in comment
From: Jason Wang @ 2010-11-29  5:48 UTC (permalink / raw)
  To: virtualization, netdev, linux-kernel, kvm, mst

Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 drivers/vhost/net.c   |    2 +-
 drivers/vhost/vhost.h |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index d10da28..14fc189 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -452,7 +452,7 @@ static void handle_rx_mergeable(struct vhost_net *net)
 			move_iovec_hdr(vq->iov, vq->hdr, vhost_hlen, in);
 		else
 			/* Copy the header for use in VIRTIO_NET_F_MRG_RXBUF:
-			 * needed because sendmsg can modify msg_iov. */
+			 * needed because recvmsg can modify msg_iov. */
 			copy_iovec_hdr(vq->iov, vq->hdr, sock_hlen, in);
 		msg.msg_iovlen = in;
 		err = sock->ops->recvmsg(NULL, sock, &msg,
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index 073d06a..2af44b7 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -102,7 +102,7 @@ struct vhost_virtqueue {
 	 * flush the vhost_work instead of synchronize_rcu. Therefore readers do
 	 * not need to call rcu_read_lock/rcu_read_unlock: the beginning of
 	 * vhost_work execution acts instead of rcu_read_lock() and the end of
-	 * vhost_work execution acts instead of rcu_read_lock().
+	 * vhost_work execution acts instead of rcu_read_unlock().
 	 * Writers use virtqueue mutex. */
 	void __rcu *private_data;
 	/* Log write descriptors */

^ permalink raw reply related

* Re: [PATCH] vhost: fix typos in comment
From: Michael S. Tsirkin @ 2010-11-29  8:05 UTC (permalink / raw)
  To: Jason Wang; +Cc: virtualization, netdev, linux-kernel, kvm
In-Reply-To: <20101129054840.24951.29849.stgit@dhcp-91-7.nay.redhat.com.englab.nay.redhat.com>

On Mon, Nov 29, 2010 at 01:48:40PM +0800, Jason Wang wrote:
> Signed-off-by: Jason Wang <jasowang@redhat.com>

Applied, thanks.

> ---
>  drivers/vhost/net.c   |    2 +-
>  drivers/vhost/vhost.h |    2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
> index d10da28..14fc189 100644
> --- a/drivers/vhost/net.c
> +++ b/drivers/vhost/net.c
> @@ -452,7 +452,7 @@ static void handle_rx_mergeable(struct vhost_net *net)
>  			move_iovec_hdr(vq->iov, vq->hdr, vhost_hlen, in);
>  		else
>  			/* Copy the header for use in VIRTIO_NET_F_MRG_RXBUF:
> -			 * needed because sendmsg can modify msg_iov. */
> +			 * needed because recvmsg can modify msg_iov. */
>  			copy_iovec_hdr(vq->iov, vq->hdr, sock_hlen, in);
>  		msg.msg_iovlen = in;
>  		err = sock->ops->recvmsg(NULL, sock, &msg,
> diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
> index 073d06a..2af44b7 100644
> --- a/drivers/vhost/vhost.h
> +++ b/drivers/vhost/vhost.h
> @@ -102,7 +102,7 @@ struct vhost_virtqueue {
>  	 * flush the vhost_work instead of synchronize_rcu. Therefore readers do
>  	 * not need to call rcu_read_lock/rcu_read_unlock: the beginning of
>  	 * vhost_work execution acts instead of rcu_read_lock() and the end of
> -	 * vhost_work execution acts instead of rcu_read_lock().
> +	 * vhost_work execution acts instead of rcu_read_unlock().
>  	 * Writers use virtqueue mutex. */
>  	void __rcu *private_data;
>  	/* Log write descriptors */

^ permalink raw reply

* Re: [PATCH] vhost: correctly set bits of dirty pages
From: Michael S. Tsirkin @ 2010-11-29  8:18 UTC (permalink / raw)
  To: Jason Wang; +Cc: virtualization, netdev, linux-kernel, kvm
In-Reply-To: <20101129054819.24923.26439.stgit@dhcp-91-7.nay.redhat.com.englab.nay.redhat.com>

On Mon, Nov 29, 2010 at 01:48:20PM +0800, Jason Wang wrote:
> When counting pages we should increase it by 1 instead of VHOST_PAGE_SIZE,
> and also make log_write() can correctly process the request across
> pages with write_address not start at page boundary.
> 
> Signed-off-by: Jason Wang <jasowang@redhat.com>


Thanks, good catch!
But let's to it in small steps: first, a small patch to fix the bug:
I think this is equivalent, right?

Subject: vhost: correctly set bits of dirty pages

When counting pages we should increase address by 1 instead of
VHOST_PAGE_SIZE, and also make log_write() can correctly process the
request across pages with write_address not starting at page boundary.

Reported-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

---

diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 568eb70..d0a3552 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -887,6 +887,7 @@ static int log_write(void __user *log_base,
 	int r;
 	if (!write_length)
 		return 0;
+	write_length += write_address % VHOST_PAGE_SIZE;
 	write_address /= VHOST_PAGE_SIZE;
 	for (;;) {
 		u64 base = (u64)(unsigned long)log_base;
@@ -900,7 +901,7 @@ static int log_write(void __user *log_base,
 		if (write_length <= VHOST_PAGE_SIZE)
 			break;
 		write_length -= VHOST_PAGE_SIZE;
-		write_address += VHOST_PAGE_SIZE;
+		write_address += 1;
 	}
 	return r;
 }

^ permalink raw reply related

* Re: [PATCH] vhost: correctly set bits of dirty pages
From: Michael S. Tsirkin @ 2010-11-29  8:25 UTC (permalink / raw)
  To: Jason Wang; +Cc: virtualization, netdev, linux-kernel, kvm
In-Reply-To: <20101129081840.GB25496@redhat.com>

On Mon, Nov 29, 2010 at 10:18:40AM +0200, Michael S. Tsirkin wrote:
> On Mon, Nov 29, 2010 at 01:48:20PM +0800, Jason Wang wrote:
> > When counting pages we should increase it by 1 instead of VHOST_PAGE_SIZE,
> > and also make log_write() can correctly process the request across
> > pages with write_address not start at page boundary.
> > 
> > Signed-off-by: Jason Wang <jasowang@redhat.com>
> 
> 
> Thanks, good catch!
> But let's to it in small steps: first, a small patch to fix the bug:
> I think this is equivalent, right?
> 
> Subject: vhost: correctly set bits of dirty pages
> 
> When counting pages we should increase address by 1 instead of
> VHOST_PAGE_SIZE, and also make log_write() can correctly process the
> request across pages with write_address not starting at page boundary.
> 
> Reported-by: Jason Wang <jasowang@redhat.com>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

And then this on top:


vhost: better variable name in logging

We really store a page offset in write_address,
so rename it write_page to avoid confusion.

Signed-off-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

---

diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index d0a3552..1a3d3ed 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -884,15 +884,15 @@ static int set_bit_to_user(int nr, void __user *addr)
 static int log_write(void __user *log_base,
 		     u64 write_address, u64 write_length)
 {
+	u64 write_page = write_address / VHOST_PAGE_SIZE
 	int r;
 	if (!write_length)
 		return 0;
 	write_length += write_address % VHOST_PAGE_SIZE;
-	write_address /= VHOST_PAGE_SIZE;
 	for (;;) {
 		u64 base = (u64)(unsigned long)log_base;
-		u64 log = base + write_address / 8;
-		int bit = write_address % 8;
+		u64 log = base + write_page / 8;
+		int bit = write_page % 8;
 		if ((u64)(unsigned long)log != log)
 			return -EFAULT;
 		r = set_bit_to_user(bit, (void __user *)(unsigned long)log);
@@ -901,7 +901,7 @@ static int log_write(void __user *log_base,
 		if (write_length <= VHOST_PAGE_SIZE)
 			break;
 		write_length -= VHOST_PAGE_SIZE;
-		write_address += 1;
+		write_page += 1;
 	}
 	return r;
 }

^ permalink raw reply related

* Re: [PATCH] vhost: correctly set bits of dirty pages
From: Jason Wang @ 2010-11-29 13:50 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Jason Wang, virtualization, netdev, linux-kernel, kvm
In-Reply-To: <20101129081840.GB25496@redhat.com>

Michael S. Tsirkin writes:
 > On Mon, Nov 29, 2010 at 01:48:20PM +0800, Jason Wang wrote:
 > > When counting pages we should increase it by 1 instead of VHOST_PAGE_SIZE,
 > > and also make log_write() can correctly process the request across
 > > pages with write_address not start at page boundary.
 > > 
 > > Signed-off-by: Jason Wang <jasowang@redhat.com>
 > 
 > dd
 > Thanks, good catch!
 > But let's to it in small steps: first, a small patch to fix the bug:
 > I think this is equivalent, right?
 > 

Yes.

 > Subject: vhost: correctly set bits of dirty pages
 > 
 > When counting pages we should increase address by 1 instead of
 > VHOST_PAGE_SIZE, and also make log_write() can correctly process the
 > request across pages with write_address not starting at page boundary.
 > 
 > Reported-by: Jason Wang <jasowang@redhat.com>
 > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 > 

I'm fine with this, thanks!

 > ---
 > 
 > diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
 > index 568eb70..d0a3552 100644
 > --- a/drivers/vhost/vhost.c
 > +++ b/drivers/vhost/vhost.c
 > @@ -887,6 +887,7 @@ static int log_write(void __user *log_base,
 >  	int r;
 >  	if (!write_length)
 >  		return 0;
 > +	write_length += write_address % VHOST_PAGE_SIZE;
 >  	write_address /= VHOST_PAGE_SIZE;
 >  	for (;;) {
 >  		u64 base = (u64)(unsigned long)log_base;
 > @@ -900,7 +901,7 @@ static int log_write(void __user *log_base,
 >  		if (write_length <= VHOST_PAGE_SIZE)
 >  			break;
 >  		write_length -= VHOST_PAGE_SIZE;
 > -		write_address += VHOST_PAGE_SIZE;
 > +		write_address += 1;
 >  	}
 >  	return r;
 >  }
 > --
 > To unsubscribe from this list: send the line "unsubscribe kvm" in
 > the body of a message to majordomo@vger.kernel.org
 > More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 0/2] tools/virtio: virtio_ring testing tool
From: Michael S. Tsirkin @ 2010-11-29 17:04 UTC (permalink / raw)
  To: virtualization, kvm, rusty; +Cc: linux-kernel

This implements a virtio simulator:
 - adds stubs for enough support functions to compile
   virtio ring in userspace.
 - Adds a stub vhost based module this can talk to.
 
This should help us decide things like which ring layout
works best.
 
Communication is currently done using an eventfd descriptor.
This means there's a shared spinlock there: what I would like to do
in the future, is run this under kvm and use interrupt injection and
io for communication, to make it more real-life and avoid lock
contention.

This patchset applies on top of vhost-net-next branch in my tree.
In particular you must have commits:
commit 64e1c80748afca3b4818ebb232a9668bf529886d
    vhost-net: batch use/unuse mm
commit 533a19b4b88fcf81da3106b94f0ac4ac8b33a248
    vhost: put mm after thread stop
 
I think it's probably best to keep this part of kernel tree,
to avoid version skew and so we don't need to commit to
any kind of API.

Since there's a dependency on vhost here it's easiest
to merge this through my vhost tree, so that's what
I intend to do unless someone complains, soon.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

^ permalink raw reply

* [PATCH 1/2] vhost test module
From: Michael S. Tsirkin @ 2010-11-29 17:09 UTC (permalink / raw)
  To: virtualization, kvm, rusty; +Cc: linux-kernel
In-Reply-To: <20101129170431.GA4027@redhat.com>

This adds a test module for vhost infrastructure.
Intentionally not tied to kbuild to prevent people
from installing and loading it accidentally.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

---

diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
new file mode 100644
index 0000000..099f302
--- /dev/null
+++ b/drivers/vhost/test.c
@@ -0,0 +1,320 @@
+/* Copyright (C) 2009 Red Hat, Inc.
+ * Author: Michael S. Tsirkin <mst@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ *
+ * test virtio server in host kernel.
+ */
+
+#include <linux/compat.h>
+#include <linux/eventfd.h>
+#include <linux/vhost.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/rcupdate.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+
+#include "test.h"
+#include "vhost.c"
+
+/* Max number of bytes transferred before requeueing the job.
+ * Using this limit prevents one virtqueue from starving others. */
+#define VHOST_TEST_WEIGHT 0x80000
+
+enum {
+	VHOST_TEST_VQ = 0,
+	VHOST_TEST_VQ_MAX = 1,
+};
+
+struct vhost_test {
+	struct vhost_dev dev;
+	struct vhost_virtqueue vqs[VHOST_TEST_VQ_MAX];
+};
+
+/* Expects to be always run from workqueue - which acts as
+ * read-size critical section for our kind of RCU. */
+static void handle_vq(struct vhost_test *n)
+{
+	struct vhost_virtqueue *vq = &n->dev.vqs[VHOST_TEST_VQ];
+	unsigned out, in;
+	int head;
+	size_t len, total_len = 0;
+	void *private;
+
+	private = rcu_dereference_check(vq->private_data, 1);
+	if (!private)
+		return;
+
+	mutex_lock(&vq->mutex);
+	vhost_disable_notify(vq);
+
+	for (;;) {
+		head = vhost_get_vq_desc(&n->dev, vq, vq->iov,
+					 ARRAY_SIZE(vq->iov),
+					 &out, &in,
+					 NULL, NULL);
+		/* On error, stop handling until the next kick. */
+		if (unlikely(head < 0))
+			break;
+		/* Nothing new?  Wait for eventfd to tell us they refilled. */
+		if (head == vq->num) {
+			if (unlikely(vhost_enable_notify(vq))) {
+				vhost_disable_notify(vq);
+				continue;
+			}
+			break;
+		}
+		if (in) {
+			vq_err(vq, "Unexpected descriptor format for TX: "
+			       "out %d, int %d\n", out, in);
+			break;
+		}
+		len = iov_length(vq->iov, out);
+		/* Sanity check */
+		if (!len) {
+			vq_err(vq, "Unexpected 0 len for TX\n");
+			break;
+		}
+		vhost_add_used_and_signal(&n->dev, vq, head, 0);
+		total_len += len;
+		if (unlikely(total_len >= VHOST_TEST_WEIGHT)) {
+			vhost_poll_queue(&vq->poll);
+			break;
+		}
+	}
+
+	mutex_unlock(&vq->mutex);
+}
+
+static void handle_vq_kick(struct vhost_work *work)
+{
+	struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue,
+						  poll.work);
+	struct vhost_test *n = container_of(vq->dev, struct vhost_test, dev);
+
+	handle_vq(n);
+}
+
+static int vhost_test_open(struct inode *inode, struct file *f)
+{
+	struct vhost_test *n = kmalloc(sizeof *n, GFP_KERNEL);
+	struct vhost_dev *dev;
+	int r;
+
+	if (!n)
+		return -ENOMEM;
+
+	dev = &n->dev;
+	n->vqs[VHOST_TEST_VQ].handle_kick = handle_vq_kick;
+	r = vhost_dev_init(dev, n->vqs, VHOST_TEST_VQ_MAX);
+	if (r < 0) {
+		kfree(n);
+		return r;
+	}
+
+	f->private_data = n;
+
+	return 0;
+}
+
+static void *vhost_test_stop_vq(struct vhost_test *n,
+				struct vhost_virtqueue *vq)
+{
+	void *private;
+
+	mutex_lock(&vq->mutex);
+	private = rcu_dereference_protected(vq->private_data,
+					 lockdep_is_held(&vq->mutex));
+	rcu_assign_pointer(vq->private_data, NULL);
+	mutex_unlock(&vq->mutex);
+	return private;
+}
+
+static void vhost_test_stop(struct vhost_test *n, void **privatep)
+{
+	*privatep = vhost_test_stop_vq(n, n->vqs + VHOST_TEST_VQ);
+}
+
+static void vhost_test_flush_vq(struct vhost_test *n, int index)
+{
+	vhost_poll_flush(&n->dev.vqs[index].poll);
+}
+
+static void vhost_test_flush(struct vhost_test *n)
+{
+	vhost_test_flush_vq(n, VHOST_TEST_VQ);
+}
+
+static int vhost_test_release(struct inode *inode, struct file *f)
+{
+	struct vhost_test *n = f->private_data;
+	void  *private;
+
+	vhost_test_stop(n, &private);
+	vhost_test_flush(n);
+	vhost_dev_cleanup(&n->dev);
+	/* We do an extra flush before freeing memory,
+	 * since jobs can re-queue themselves. */
+	vhost_test_flush(n);
+	kfree(n);
+	return 0;
+}
+
+static long vhost_test_run(struct vhost_test *n, int test)
+{
+	void *priv, *oldpriv;
+	struct vhost_virtqueue *vq;
+	int r, index;
+
+	if (test < 0 || test > 1)
+		return -EINVAL;
+
+	mutex_lock(&n->dev.mutex);
+	r = vhost_dev_check_owner(&n->dev);
+	if (r)
+		goto err;
+
+	for (index = 0; index < n->dev.nvqs; ++index) {
+		/* Verify that ring has been setup correctly. */
+		if (!vhost_vq_access_ok(&n->vqs[index])) {
+			r = -EFAULT;
+			goto err;
+		}
+	}
+
+	for (index = 0; index < n->dev.nvqs; ++index) {
+		vq = n->vqs + index;
+		mutex_lock(&vq->mutex);
+		priv = test ? n : NULL;
+
+		/* start polling new socket */
+		oldpriv = rcu_dereference_protected(vq->private_data,
+						    lockdep_is_held(&vq->mutex));
+		rcu_assign_pointer(vq->private_data, priv);
+
+		mutex_unlock(&vq->mutex);
+
+		if (oldpriv) {
+			vhost_test_flush_vq(n, index);
+		}
+	}
+
+	mutex_unlock(&n->dev.mutex);
+	return 0;
+
+err:
+	mutex_unlock(&n->dev.mutex);
+	return r;
+}
+
+static long vhost_test_reset_owner(struct vhost_test *n)
+{
+	void *priv = NULL;
+	long err;
+	mutex_lock(&n->dev.mutex);
+	err = vhost_dev_check_owner(&n->dev);
+	if (err)
+		goto done;
+	vhost_test_stop(n, &priv);
+	vhost_test_flush(n);
+	err = vhost_dev_reset_owner(&n->dev);
+done:
+	mutex_unlock(&n->dev.mutex);
+	return err;
+}
+
+static int vhost_test_set_features(struct vhost_test *n, u64 features)
+{
+	mutex_lock(&n->dev.mutex);
+	if ((features & (1 << VHOST_F_LOG_ALL)) &&
+	    !vhost_log_access_ok(&n->dev)) {
+		mutex_unlock(&n->dev.mutex);
+		return -EFAULT;
+	}
+	n->dev.acked_features = features;
+	smp_wmb();
+	vhost_test_flush(n);
+	mutex_unlock(&n->dev.mutex);
+	return 0;
+}
+
+static long vhost_test_ioctl(struct file *f, unsigned int ioctl,
+			     unsigned long arg)
+{
+	struct vhost_test *n = f->private_data;
+	void __user *argp = (void __user *)arg;
+	u64 __user *featurep = argp;
+	int test;
+	u64 features;
+	int r;
+	switch (ioctl) {
+	case VHOST_TEST_RUN:
+		if (copy_from_user(&test, argp, sizeof test))
+			return -EFAULT;
+		return vhost_test_run(n, test);
+	case VHOST_GET_FEATURES:
+		features = VHOST_FEATURES;
+		if (copy_to_user(featurep, &features, sizeof features))
+			return -EFAULT;
+		return 0;
+	case VHOST_SET_FEATURES:
+		if (copy_from_user(&features, featurep, sizeof features))
+			return -EFAULT;
+		if (features & ~VHOST_FEATURES)
+			return -EOPNOTSUPP;
+		return vhost_test_set_features(n, features);
+	case VHOST_RESET_OWNER:
+		return vhost_test_reset_owner(n);
+	default:
+		mutex_lock(&n->dev.mutex);
+		r = vhost_dev_ioctl(&n->dev, ioctl, arg);
+		vhost_test_flush(n);
+		mutex_unlock(&n->dev.mutex);
+		return r;
+	}
+}
+
+#ifdef CONFIG_COMPAT
+static long vhost_test_compat_ioctl(struct file *f, unsigned int ioctl,
+				   unsigned long arg)
+{
+	return vhost_test_ioctl(f, ioctl, (unsigned long)compat_ptr(arg));
+}
+#endif
+
+static const struct file_operations vhost_test_fops = {
+	.owner          = THIS_MODULE,
+	.release        = vhost_test_release,
+	.unlocked_ioctl = vhost_test_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl   = vhost_test_compat_ioctl,
+#endif
+	.open           = vhost_test_open,
+	.llseek		= noop_llseek,
+};
+
+static struct miscdevice vhost_test_misc = {
+	MISC_DYNAMIC_MINOR,
+	"vhost-test",
+	&vhost_test_fops,
+};
+
+static int vhost_test_init(void)
+{
+	return misc_register(&vhost_test_misc);
+}
+module_init(vhost_test_init);
+
+static void vhost_test_exit(void)
+{
+	misc_deregister(&vhost_test_misc);
+}
+module_exit(vhost_test_exit);
+
+MODULE_VERSION("0.0.1");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Michael S. Tsirkin");
+MODULE_DESCRIPTION("Host kernel side for virtio simulator");
diff --git a/drivers/vhost/test.h b/drivers/vhost/test.h
new file mode 100644
index 0000000..1fef5df
--- /dev/null
+++ b/drivers/vhost/test.h
@@ -0,0 +1,7 @@
+#ifndef LINUX_VHOST_TEST_H
+#define LINUX_VHOST_TEST_H
+
+/* Start a given test on the virtio null device. 0 stops all tests. */
+#define VHOST_TEST_RUN _IOW(VHOST_VIRTIO, 0x31, int)
+
+#endif
diff --git a/tools/virtio/vhost_test/Makefile b/tools/virtio/vhost_test/Makefile
new file mode 100644
index 0000000..a1d35b8
--- /dev/null
+++ b/tools/virtio/vhost_test/Makefile
@@ -0,0 +1,2 @@
+obj-m += vhost_test.o
+EXTRA_CFLAGS += -Idrivers/vhost
diff --git a/tools/virtio/vhost_test/vhost_test.c b/tools/virtio/vhost_test/vhost_test.c
new file mode 100644
index 0000000..1873518
--- /dev/null
+++ b/tools/virtio/vhost_test/vhost_test.c
@@ -0,0 +1 @@
+#include "test.c"

^ permalink raw reply related

* [PATCH 2/2] tools/virtio: virtio_test tool
From: Michael S. Tsirkin @ 2010-11-29 17:16 UTC (permalink / raw)
  To: virtualization, kvm, rusty; +Cc: linux-kernel
In-Reply-To: <20101129170431.GA4027@redhat.com>

This is the userspace part of the tool: it includes a bunch of stubs for
linux APIs, somewhat simular to linuxsched. This makes it possible to
recompile the ring code in userspace.

A small test example is implemented combining this with vhost_test
module.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

---

diff --git a/tools/virtio/Makefile b/tools/virtio/Makefile
new file mode 100644
index 0000000..d1d442e
--- /dev/null
+++ b/tools/virtio/Makefile
@@ -0,0 +1,12 @@
+all: test mod
+test: virtio_test
+virtio_test: virtio_ring.o virtio_test.o
+CFLAGS += -g -O2 -Wall -I. -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow  -MMD
+vpath %.c ../../drivers/virtio
+mod:
+	${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test
+.PHONY: all test mod clean
+clean:
+	${RM} *.o vhost_test/*.o vhost_test/.*.cmd \
+              vhost_test/Module.symvers vhost_test/modules.order *.d
+-include *.d
diff --git a/tools/virtio/linux/device.h b/tools/virtio/linux/device.h
new file mode 100644
index 0000000..4ad7e1d
--- /dev/null
+++ b/tools/virtio/linux/device.h
@@ -0,0 +1,2 @@
+#ifndef LINUX_DEVICE_H
+#endif
diff --git a/tools/virtio/linux/slab.h b/tools/virtio/linux/slab.h
new file mode 100644
index 0000000..81baeac
--- /dev/null
+++ b/tools/virtio/linux/slab.h
@@ -0,0 +1,2 @@
+#ifndef LINUX_SLAB_H
+#endif
diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h
new file mode 100644
index 0000000..669bcdd
--- /dev/null
+++ b/tools/virtio/linux/virtio.h
@@ -0,0 +1,223 @@
+#ifndef LINUX_VIRTIO_H
+#define LINUX_VIRTIO_H
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <linux/types.h>
+#include <errno.h>
+
+typedef unsigned long long dma_addr_t;
+
+struct scatterlist {
+	unsigned long	page_link;
+	unsigned int	offset;
+	unsigned int	length;
+	dma_addr_t	dma_address;
+};
+
+struct page {
+	unsigned long long dummy;
+};
+
+#define BUG_ON(__BUG_ON_cond) assert(!(__BUG_ON_cond))
+
+/* Physical == Virtual */
+#define virt_to_phys(p) ((unsigned long)p)
+#define phys_to_virt(a) ((void *)(unsigned long)(a))
+/* Page address: Virtual / 4K */
+#define virt_to_page(p) ((struct page*)((virt_to_phys(p) / 4096) * \
+					sizeof(struct page)))
+#define offset_in_page(p) (((unsigned long)p) % 4096)
+#define sg_phys(sg) ((sg->page_link & ~0x3) / sizeof(struct page) * 4096 + \
+		     sg->offset)
+static inline void sg_mark_end(struct scatterlist *sg)
+{
+	/*
+	 * Set termination bit, clear potential chain bit
+	 */
+	sg->page_link |= 0x02;
+	sg->page_link &= ~0x01;
+}
+static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents)
+{
+	memset(sgl, 0, sizeof(*sgl) * nents);
+	sg_mark_end(&sgl[nents - 1]);
+}
+static inline void sg_assign_page(struct scatterlist *sg, struct page *page)
+{
+	unsigned long page_link = sg->page_link & 0x3;
+
+	/*
+	 * In order for the low bit stealing approach to work, pages
+	 * must be aligned at a 32-bit boundary as a minimum.
+	 */
+	BUG_ON((unsigned long) page & 0x03);
+	sg->page_link = page_link | (unsigned long) page;
+}
+
+static inline void sg_set_page(struct scatterlist *sg, struct page *page,
+			       unsigned int len, unsigned int offset)
+{
+	sg_assign_page(sg, page);
+	sg->offset = offset;
+	sg->length = len;
+}
+
+static inline void sg_set_buf(struct scatterlist *sg, const void *buf,
+			      unsigned int buflen)
+{
+	sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
+}
+
+static inline void sg_init_one(struct scatterlist *sg, const void *buf, unsigned int buflen)
+{
+	sg_init_table(sg, 1);
+	sg_set_buf(sg, buf, buflen);
+}
+
+typedef __u16 u16;
+
+typedef enum {
+	GFP_KERNEL,
+	GFP_ATOMIC,
+} gfp_t;
+typedef enum {
+	IRQ_NONE,
+	IRQ_HANDLED
+} irqreturn_t;
+
+static inline void *kmalloc(size_t s, gfp_t gfp)
+{
+	return malloc(s);
+}
+
+static inline void kfree(void *p)
+{
+	free(p);
+}
+
+#define container_of(ptr, type, member) ({			\
+	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
+	(type *)( (char *)__mptr - offsetof(type,member) );})
+
+#define uninitialized_var(x) x = x
+
+# ifndef likely
+#  define likely(x)	(__builtin_expect(!!(x), 1))
+# endif
+# ifndef unlikely
+#  define unlikely(x)	(__builtin_expect(!!(x), 0))
+# endif
+
+#define pr_err(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
+#ifdef DEBUG
+#define pr_debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
+#else
+#define pr_debug(format, ...) do {} while (0)
+#endif
+#define dev_err(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)
+#define dev_warn(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)
+
+/* TODO: empty stubs for now. Broken but enough for virtio_ring.c */
+#define list_add_tail(a, b) do {} while (0)
+#define list_del(a) do {} while (0)
+
+#define BIT_WORD(nr)		((nr) / BITS_PER_LONG)
+#define BITS_PER_BYTE		8
+#define BITS_PER_LONG (sizeof(long) * BITS_PER_BYTE)
+#define BIT_MASK(nr)		(1UL << ((nr) % BITS_PER_LONG))
+/* TODO: Not atomic as it should be:
+ * we don't use this for anything important. */
+static inline void clear_bit(int nr, volatile unsigned long *addr)
+{
+	unsigned long mask = BIT_MASK(nr);
+	unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+
+	*p &= ~mask;
+}
+
+static inline int test_bit(int nr, const volatile unsigned long *addr)
+{
+        return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
+}
+
+/* The only feature we care to support */
+#define virtio_has_feature(dev, feature) \
+	test_bit((feature), (dev)->features)
+/* end of stubs */
+
+struct virtio_device {
+	void *dev;
+	unsigned long features[1];
+};
+
+struct virtqueue {
+	/* TODO: commented as list macros are empty stubs for now.
+	 * Broken but enough for virtio_ring.c
+	 * struct list_head list; */
+	void (*callback)(struct virtqueue *vq);
+	const char *name;
+	struct virtio_device *vdev;
+	void *priv;
+};
+
+#define EXPORT_SYMBOL_GPL(__EXPORT_SYMBOL_GPL_name) \
+	void __EXPORT_SYMBOL_GPL##__EXPORT_SYMBOL_GPL_name() { \
+}
+#define MODULE_LICENSE(__MODULE_LICENSE_value) \
+	const char *__MODULE_LICENSE_name = __MODULE_LICENSE_value
+
+#define CONFIG_SMP
+
+#if defined(__i386__) || defined(__x86_64__)
+#define barrier() asm volatile("" ::: "memory")
+#define mb() __sync_synchronize()
+
+#define smp_mb()	mb()
+# define smp_rmb()	barrier()
+# define smp_wmb()	barrier()
+#else
+#error Please fill in barrier macros
+#endif
+
+/* Interfaces exported by virtio_ring. */
+int virtqueue_add_buf_gfp(struct virtqueue *vq,
+			  struct scatterlist sg[],
+			  unsigned int out_num,
+			  unsigned int in_num,
+			  void *data,
+			  gfp_t gfp);
+
+static inline int virtqueue_add_buf(struct virtqueue *vq,
+				    struct scatterlist sg[],
+				    unsigned int out_num,
+				    unsigned int in_num,
+				    void *data)
+{
+	return virtqueue_add_buf_gfp(vq, sg, out_num, in_num, data, GFP_ATOMIC);
+}
+
+void virtqueue_kick(struct virtqueue *vq);
+
+void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len);
+
+void virtqueue_disable_cb(struct virtqueue *vq);
+
+bool virtqueue_enable_cb(struct virtqueue *vq);
+
+void *virtqueue_detach_unused_buf(struct virtqueue *vq);
+struct virtqueue *vring_new_virtqueue(unsigned int num,
+				      unsigned int vring_align,
+				      struct virtio_device *vdev,
+				      void *pages,
+				      void (*notify)(struct virtqueue *vq),
+				      void (*callback)(struct virtqueue *vq),
+				      const char *name);
+void vring_del_virtqueue(struct virtqueue *vq);
+
+#endif
diff --git a/tools/virtio/vhost_test/Makefile b/tools/virtio/vhost_test/Makefile
new file mode 100644
index 0000000..a1d35b8
--- /dev/null
+++ b/tools/virtio/vhost_test/Makefile
@@ -0,0 +1,2 @@
+obj-m += vhost_test.o
+EXTRA_CFLAGS += -Idrivers/vhost
diff --git a/tools/virtio/vhost_test/vhost_test.c b/tools/virtio/vhost_test/vhost_test.c
new file mode 100644
index 0000000..1873518
--- /dev/null
+++ b/tools/virtio/vhost_test/vhost_test.c
@@ -0,0 +1 @@
+#include "test.c"
diff --git a/tools/virtio/virtio_test.c b/tools/virtio/virtio_test.c
new file mode 100644
index 0000000..808ae86
--- /dev/null
+++ b/tools/virtio/virtio_test.c
@@ -0,0 +1,248 @@
+#define _GNU_SOURCE
+#include <getopt.h>
+#include <string.h>
+#include <poll.h>
+#include <sys/eventfd.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <linux/vhost.h>
+#include <linux/virtio.h>
+#include <linux/virtio_ring.h>
+#include "../../drivers/vhost/test.h"
+
+struct vq_info {
+	int kick;
+	int call;
+	int num;
+	int idx;
+	void *ring;
+	/* copy used for control */
+	struct vring vring;
+	struct virtqueue *vq;
+};
+
+struct vdev_info {
+	struct virtio_device vdev;
+	int control;
+	struct pollfd fds[1];
+	struct vq_info vqs[1];
+	int nvqs;
+	void *buf;
+	size_t buf_size;
+	struct vhost_memory *mem;
+};
+
+void vq_notify(struct virtqueue *vq)
+{
+	struct vq_info *info = vq->priv;
+	unsigned long long v = 1;
+	int r;
+	r = write(info->kick, &v, sizeof v);
+	assert(r == sizeof v);
+}
+
+void vq_callback(struct virtqueue *vq)
+{
+}
+
+
+void vhost_vq_setup(struct vdev_info *dev, struct vq_info *info)
+{
+	struct vhost_vring_state state = { .index = info->idx };
+	struct vhost_vring_file file = { .index = info->idx };
+	unsigned long long features = dev->vdev.features[0];
+	struct vhost_vring_addr addr = {
+		.index = info->idx,
+		.desc_user_addr = (uint64_t)(unsigned long)info->vring.desc,
+		.avail_user_addr = (uint64_t)(unsigned long)info->vring.avail,
+		.used_user_addr = (uint64_t)(unsigned long)info->vring.used,
+	};
+	int r;
+	r = ioctl(dev->control, VHOST_SET_FEATURES, &features);
+	assert(r >= 0);
+	state.num = info->vring.num;
+	r = ioctl(dev->control, VHOST_SET_VRING_NUM, &state);
+	assert(r >= 0);
+	state.num = 0;
+	r = ioctl(dev->control, VHOST_SET_VRING_BASE, &state);
+	assert(r >= 0);
+	r = ioctl(dev->control, VHOST_SET_VRING_ADDR, &addr);
+	assert(r >= 0);
+	file.fd = info->kick;
+	r = ioctl(dev->control, VHOST_SET_VRING_KICK, &file);
+	assert(r >= 0);
+	file.fd = info->call;
+	r = ioctl(dev->control, VHOST_SET_VRING_CALL, &file);
+	assert(r >= 0);
+}
+
+static void vq_info_add(struct vdev_info *dev, int num)
+{
+	struct vq_info *info = &dev->vqs[dev->nvqs];
+	int r;
+	info->idx = dev->nvqs;
+	info->kick = eventfd(0, EFD_NONBLOCK);
+	info->call = eventfd(0, EFD_NONBLOCK);
+	r = posix_memalign(&info->ring, 4096, vring_size(num, 4096));
+	assert(r >= 0);
+	memset(info->ring, 0, vring_size(num, 4096));
+	vring_init(&info->vring, num, info->ring, 4096);
+	info->vq = vring_new_virtqueue(info->vring.num, 4096, &dev->vdev, info->ring,
+				       vq_notify, vq_callback, "test");
+	assert(info->vq);
+	info->vq->priv = info;
+	vhost_vq_setup(dev, info);
+	dev->fds[info->idx].fd = info->call;
+	dev->fds[info->idx].events = POLLIN;
+	dev->nvqs++;
+}
+
+static void vdev_info_init(struct vdev_info* dev, unsigned long long features)
+{
+	int r;
+	memset(dev, 0, sizeof *dev);
+	dev->vdev.features[0] = features;
+	dev->vdev.features[1] = features >> 32;
+	dev->buf_size = 1024;
+	dev->buf = malloc(dev->buf_size);
+	assert(dev->buf);
+        dev->control = open("/dev/vhost-test", O_RDWR);
+	assert(dev->control >= 0);
+	r = ioctl(dev->control, VHOST_SET_OWNER, NULL);
+	assert(r >= 0);
+	dev->mem = malloc(offsetof(struct vhost_memory, regions) +
+			  sizeof dev->mem->regions[0]);
+	assert(dev->mem);
+	memset(dev->mem, 0, offsetof(struct vhost_memory, regions) +
+                          sizeof dev->mem->regions[0]);
+	dev->mem->nregions = 1;
+	dev->mem->regions[0].guest_phys_addr = (long)dev->buf;
+	dev->mem->regions[0].userspace_addr = (long)dev->buf;
+	dev->mem->regions[0].memory_size = dev->buf_size;
+	r = ioctl(dev->control, VHOST_SET_MEM_TABLE, dev->mem);
+	assert(r >= 0);
+}
+
+/* TODO: this is pretty bad: we get a cache line bounce
+ * for the wait queue on poll and another one on read,
+ * plus the read which is there just to clear the
+ * current state. */
+static void wait_for_interrupt(struct vdev_info *dev)
+{
+	int i;
+	unsigned long long val;
+	poll(dev->fds, dev->nvqs, -1);
+	for (i = 0; i < dev->nvqs; ++i)
+		if (dev->fds[i].revents & POLLIN) {
+			read(dev->fds[i].fd, &val, sizeof val);
+		}
+}
+
+static void run_test(struct vdev_info *dev, struct vq_info *vq, int bufs)
+{
+	struct scatterlist sl;
+	long started = 0, completed = 0;
+	long completed_before;
+	int r, test = 1;
+	unsigned len;
+	long long spurious = 0;
+	r = ioctl(dev->control, VHOST_TEST_RUN, &test);
+	assert(r >= 0);
+	for (;;) {
+		virtqueue_disable_cb(vq->vq);
+		completed_before = completed;
+		do {
+			if (started < bufs) {
+				sg_init_one(&sl, dev->buf, dev->buf_size);
+				r = virtqueue_add_buf(vq->vq, &sl, 1, 0,
+						      dev->buf + started);
+				if (likely(r >= 0)) {
+					++started;
+					virtqueue_kick(vq->vq);
+				}
+			} else
+				r = -1;
+
+			/* Flush out completed bufs if any */
+			if (virtqueue_get_buf(vq->vq, &len)) {
+				++completed;
+				r = 0;
+			}
+			
+		} while (r >= 0);
+		if (completed == completed_before)
+			++spurious;
+		assert(completed <= bufs);
+		assert(started <= bufs);
+		if (completed == bufs)
+			break;
+		if (virtqueue_enable_cb(vq->vq)) {
+			wait_for_interrupt(dev);
+		}
+	}
+	test = 0;
+	r = ioctl(dev->control, VHOST_TEST_RUN, &test);
+	assert(r >= 0);
+	fprintf(stderr, "spurious wakeus: 0x%llx\n", spurious);
+}
+
+const char optstring[] = "h";
+const struct option longopts[] = {
+	{
+		.name = "help",
+		.val = 'h',
+	},
+	{
+		.name = "indirect",
+		.val = 'I',
+	},
+	{
+		.name = "no-indirect",
+		.val = 'i',
+	},
+	{
+	}
+};
+
+static void help()
+{
+	fprintf(stderr, "Usage: virtio_test [--help] [--no-indirect]\n");
+}
+
+int main(int argc, char **argv)
+{
+	struct vdev_info dev;
+	unsigned long long features = 1ULL << VIRTIO_RING_F_INDIRECT_DESC;
+	int o;
+
+	for (;;) {
+		o = getopt_long(argc, argv, optstring, longopts, NULL);
+		switch (o) {
+		case -1:
+			goto done;
+		case '?':
+			help();
+			exit(2);
+		case 'h':
+			help();
+			goto done;
+		case 'i':
+			features &= ~(1ULL << VIRTIO_RING_F_INDIRECT_DESC);
+			break;
+		default:
+			assert(0);
+			break;
+		}
+	}
+
+done:
+	vdev_info_init(&dev, features);
+	vq_info_add(&dev, 256);
+	run_test(&dev, &dev.vqs[0], 0x100000);
+	return 0;
+}

^ permalink raw reply related

* Re: [PATCH 2/3]: An Implementation of HyperV KVP functionality
From: Ky Srinivasan @ 2010-11-29 18:26 UTC (permalink / raw)
  To: Evgeniy Polyakov
  Cc: devel, Virtualization, Haiyang Zhang, Greg KH, Stephen Hemminger
In-Reply-To: <20101124145617.GA11133@ioremap.net>



>>> On 11/24/2010 at  9:56 AM, in message <20101124145617.GA11133@ioremap.net>,
Evgeniy Polyakov <zbr@ioremap.net> wrote: 
> Hi.
> 
> I will ack connector part of course, but this hunk is actually quite
Thank you.
> bad.
> 
> 
>> +static void shutdown_onchannelcallback(void *context)
>> +{
>> +	struct vmbus_channel *channel = context;
>> +	u8 *buf;
>> +	u32 buflen, recvlen;
>> +	u64 requestid;
>> +	u8  execute_shutdown = false;
>> +
>> +	struct shutdown_msg_data *shutdown_msg;
>> +
>> +	struct icmsg_hdr *icmsghdrp;
>> +	struct icmsg_negotiate *negop = NULL;
>> +
>> +	buflen = PAGE_SIZE;
>> +	buf = kmalloc(buflen, GFP_ATOMIC);
>> +
>> +	vmbus_recvpacket(channel, buf, buflen, &recvlen, &requestid);
> 
> Boom. I did not read further, since this function returns void and thus
> can not propagate error, which is likely not a good idea.

Hank and Haiyang (both copied here) are the authors of this code. My contribution to this code (in this patch) has been to change the name of the file! I will let Hank and Haiyang comment on your feedback.

Regards,

K. Y 

^ permalink raw reply

* ICAC2011 CFP (Submission site is open)
From: Ming Zhao @ 2010-12-01  3:10 UTC (permalink / raw)


========================================================================
                           Call for Papers
       The 8th International Conference on Autonomic Computing
                              ICAC 2011
                     http://icac2011.cs.fiu.edu

               June 14-18th, 2011  Karlsruhe, Germany
========================================================================

Update:
-------

* Submission site is open: https://www.softconf.com/b/icac2011/


Scope:
------

ICAC is the leading conference on autonomic computing applications,
technology and foundations. Autonomic computing refers to methods and
means for reducing the human burden of managing computing systems.
Systems introducing new autonomic features are becoming increasingly
prevalent, motivating research that spans a variety of areas, from
computer systems, architecture, databases and networks to machine
learning, control theory, and bio-inspired computing. ICAC brings
together researchers and practitioners across these disciplines to
address the multiple facets of adaptation and self-management in
computing systems and applications from different perspectives.
Autonomic computing solutions are sought for grids, clouds, enterprise
software, data centers, Internet services, embedded systems, and sensor
networks, where resources and applications must be managed to maximize
performance and minimize cost, while maintaining predictable and
reliable behavior in the face of varying workloads, failures, and
malicious threats. Papers are solicited from all areas of autonomic
computing, along three main thrusts:

* Applications of autonomic computing: Systems contributions and
experiences are sought with prototyped or deployed systems and
applications that focus on advancing system independence and increasing
system ability to adapt to an unpredictable environment. Application
areas include but are not limited to:
- Enterprise applications
- Clouds and grids
- Internet services
- Data center or large-scale system management
- Embedded and mobile systems
- Energy management
- Sensor networks, especially issues related to autonomous, distributed
management
- Internet of things
- Other applications of autonomic computing to real problems in science,
engineering, business and society.

* Autonomic computing components and services: Papers are sought that
describe protocols, system-level support, services, or application
components that enhance aspects of system autonomy, self-management,
self-tuning, self-configuration, self-diagnosis, and self-healing, or
improve adaptive capabilities. Examples include:
- Autonomic management of resources, workloads, faults, power/thermal,
and other challenges.
- Management of quality of service, including security and dependability
- Self-managing components, such as servers, storage, network protocols,
or specific application elements
- Monitoring systems for autonomic computing
- Virtual machine, operating systems, hardware or application support
for autonomic computing
- Novel human interfaces for monitoring and controlling autonomic
systems
- Management topics, such as specification and modeling of service-level
agreements, behavior enforcement and tie-in with IT governance.
- Toolkits, frameworks, principles and architectures, from software
engineering practices and experimental methodologies to agent-based
techniques and virtualization.

* Algorithms, theory and foundations of autonomic computing: Analytic
foundations are solicited for building efficient autonomic systems,
predicting their behavior, quantifying their performance, analyzing
their stability, guaranteeing their specifications, or optimizing their
efficacy. These include:
- Decision and analysis techniques and their use, such as machine
learning, control theory, predictive methods, emergent behavior, self-
organizing networks, rule-based systems and bio-inspired techniques
- Fundamental science and theory of self-managing systems:
understanding, controlling or exploiting system behaviors to enforce
autonomic properties
- Algorithms, analysis and theory for performance guarantees
- Foundations of self-diagnostic systems

Papers will be judged on originality, significance, interest,
correctness, clarity and relevance to the broader community. Papers in
the first two thrusts should report on experiences, measurements, user
studies, or other evaluations, as appropriate. Evaluations of a
prototype or large-scale deployment of autonomic systems and
applications is expected. Papers in the third thrust should provide new
fundamental insights into relevant autonomic computing problems.

Full papers (a maximum of 10 pages) and posters (2 pages) are invited on
a wide variety of topics relating to autonomic computing. Submitted
papers must be original work, and may not be under consideration for
another conference or journal. Complete formatting and submission
instructions can be found on the conference web site. Accepted papers
and posters will appear in proceedings distributed at the conference
and available electronically. Authors of accepted papers and posters
are expected to present their work at the conference.



Important dates:
----------------

* Submission Deadline: January 8th, 2011
* Notification Deadline: March 15th, 2011
* FFinal Manuscript: April 4th, 2011
* Workshop Proposals: October 15th, 2010



Organization:
-------------

* General Chair:
  o Hartmut Schmeck, KIT

* Program Chair:
  o Joseph Hellerstein, Google
  o Tarek Abdelzaher, UIUC

* Industry Chair:
  o Eno Thereska, Microsoft Research

* Workshops Chair:
  o Tom Holvoet, KU Leuven

* Posters/Demo/Exhibits Chair:
  o Michael Beigl, KIT

* Publicity Chair:
  o Ming Zhao, Florida International University

* Program Committee:
  o Michael Beigl, KIT, Germany
  o Umesh Bellur, IIT, India
  o Fabian Bustamante, Northwestern University, USA
  o Lucy Cherkasova, HP Labs, USA
  o Chita Das, Penn State University, USA
  o Yixin Diao, IBM Research, USA
  o Indranil Gupta, UIUC, USA
  o David Hutchison, Lancaster University, UK
  o Ravi Iyer, UIUC, USA
  o Vana Kalogeraki, Athens University of Economics and Business, Greece
  o Jeff Kephart, IBM, USA
  o Emre Kiciman, Microsoft Research, USA
  o Charles Lefurgy, IBM Research, USA
  o Yunhao Liu, HKUST, HK
  o Pedro Marron, Duisburg, Germany
  o Milan Milenkovic, Intel, US
  o Dejan Milojicic, HP Labs, USA
  o Priya Narasimhan, CMU, USA
  o Manish Parashar, Rutgers University, USA
  o Ana Radovanovic, Google, USA
  o Anders Robertsson, Lund, Sweden
  o Masoud Sadjadi, Florida International University, USA
  o Karsten Schwan, Georgia Institute of Technology, USA
  o Onn Shehory, IBM Haifa Research Lab, Israel
  o Prashant Shenoy, University of Massachusetts, USA
  o Sharad Singhal, HP Labs, USA
  o Mani Srivastava, UCLA, USA
  o Neeraj Suri, TU Darmstadt, Germany
  o Eno Thereska, Microsoft Research, UK
  o Thiemo Voigt, SICS, Sweden
  o Adam Wolisz, TU Berlin, Germany
  o Dongyan Xu, Purdue University, USA
  o Xiaoyun Zhu, VMware, USA



For more information:
---------------------
Web: http://icac2011.cs.fiu.edu
Email: icac2011@cs.fiu.edu





-- 
Ming Zhao, Assistant Professor
School of Computing and Information Sciences
Florida International University
Tel: (305) 348-2034, Fax: (305) 348-3549
Web: http://visa.cs.fiu.edu/ming

^ permalink raw reply

* Re: [PATCH 1/2] vhost test module
From: Paul E. McKenney @ 2010-12-02 19:00 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: linux-kernel, kvm, virtualization
In-Reply-To: <20101129170901.GB4027@redhat.com>

On Mon, Nov 29, 2010 at 07:09:01PM +0200, Michael S. Tsirkin wrote:
> This adds a test module for vhost infrastructure.
> Intentionally not tied to kbuild to prevent people
> from installing and loading it accidentally.
> 
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

On question below.

> ---
> 
> diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
> new file mode 100644
> index 0000000..099f302
> --- /dev/null
> +++ b/drivers/vhost/test.c
> @@ -0,0 +1,320 @@
> +/* Copyright (C) 2009 Red Hat, Inc.
> + * Author: Michael S. Tsirkin <mst@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2.
> + *
> + * test virtio server in host kernel.
> + */
> +
> +#include <linux/compat.h>
> +#include <linux/eventfd.h>
> +#include <linux/vhost.h>
> +#include <linux/miscdevice.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/workqueue.h>
> +#include <linux/rcupdate.h>
> +#include <linux/file.h>
> +#include <linux/slab.h>
> +
> +#include "test.h"
> +#include "vhost.c"
> +
> +/* Max number of bytes transferred before requeueing the job.
> + * Using this limit prevents one virtqueue from starving others. */
> +#define VHOST_TEST_WEIGHT 0x80000
> +
> +enum {
> +	VHOST_TEST_VQ = 0,
> +	VHOST_TEST_VQ_MAX = 1,
> +};
> +
> +struct vhost_test {
> +	struct vhost_dev dev;
> +	struct vhost_virtqueue vqs[VHOST_TEST_VQ_MAX];
> +};
> +
> +/* Expects to be always run from workqueue - which acts as
> + * read-size critical section for our kind of RCU. */
> +static void handle_vq(struct vhost_test *n)
> +{
> +	struct vhost_virtqueue *vq = &n->dev.vqs[VHOST_TEST_VQ];
> +	unsigned out, in;
> +	int head;
> +	size_t len, total_len = 0;
> +	void *private;
> +
> +	private = rcu_dereference_check(vq->private_data, 1);

Any chance of a check for running in a workqueue?  If I remember correctly,
the ->lockdep_map field in the work_struct structure allows you to create
the required lockdep expression.

							Thanx, Paul

> +	if (!private)
> +		return;
> +
> +	mutex_lock(&vq->mutex);
> +	vhost_disable_notify(vq);
> +
> +	for (;;) {
> +		head = vhost_get_vq_desc(&n->dev, vq, vq->iov,
> +					 ARRAY_SIZE(vq->iov),
> +					 &out, &in,
> +					 NULL, NULL);
> +		/* On error, stop handling until the next kick. */
> +		if (unlikely(head < 0))
> +			break;
> +		/* Nothing new?  Wait for eventfd to tell us they refilled. */
> +		if (head == vq->num) {
> +			if (unlikely(vhost_enable_notify(vq))) {
> +				vhost_disable_notify(vq);
> +				continue;
> +			}
> +			break;
> +		}
> +		if (in) {
> +			vq_err(vq, "Unexpected descriptor format for TX: "
> +			       "out %d, int %d\n", out, in);
> +			break;
> +		}
> +		len = iov_length(vq->iov, out);
> +		/* Sanity check */
> +		if (!len) {
> +			vq_err(vq, "Unexpected 0 len for TX\n");
> +			break;
> +		}
> +		vhost_add_used_and_signal(&n->dev, vq, head, 0);
> +		total_len += len;
> +		if (unlikely(total_len >= VHOST_TEST_WEIGHT)) {
> +			vhost_poll_queue(&vq->poll);
> +			break;
> +		}
> +	}
> +
> +	mutex_unlock(&vq->mutex);
> +}
> +
> +static void handle_vq_kick(struct vhost_work *work)
> +{
> +	struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue,
> +						  poll.work);
> +	struct vhost_test *n = container_of(vq->dev, struct vhost_test, dev);
> +
> +	handle_vq(n);
> +}
> +
> +static int vhost_test_open(struct inode *inode, struct file *f)
> +{
> +	struct vhost_test *n = kmalloc(sizeof *n, GFP_KERNEL);
> +	struct vhost_dev *dev;
> +	int r;
> +
> +	if (!n)
> +		return -ENOMEM;
> +
> +	dev = &n->dev;
> +	n->vqs[VHOST_TEST_VQ].handle_kick = handle_vq_kick;
> +	r = vhost_dev_init(dev, n->vqs, VHOST_TEST_VQ_MAX);
> +	if (r < 0) {
> +		kfree(n);
> +		return r;
> +	}
> +
> +	f->private_data = n;
> +
> +	return 0;
> +}
> +
> +static void *vhost_test_stop_vq(struct vhost_test *n,
> +				struct vhost_virtqueue *vq)
> +{
> +	void *private;
> +
> +	mutex_lock(&vq->mutex);
> +	private = rcu_dereference_protected(vq->private_data,
> +					 lockdep_is_held(&vq->mutex));
> +	rcu_assign_pointer(vq->private_data, NULL);
> +	mutex_unlock(&vq->mutex);
> +	return private;
> +}
> +
> +static void vhost_test_stop(struct vhost_test *n, void **privatep)
> +{
> +	*privatep = vhost_test_stop_vq(n, n->vqs + VHOST_TEST_VQ);
> +}
> +
> +static void vhost_test_flush_vq(struct vhost_test *n, int index)
> +{
> +	vhost_poll_flush(&n->dev.vqs[index].poll);
> +}
> +
> +static void vhost_test_flush(struct vhost_test *n)
> +{
> +	vhost_test_flush_vq(n, VHOST_TEST_VQ);
> +}
> +
> +static int vhost_test_release(struct inode *inode, struct file *f)
> +{
> +	struct vhost_test *n = f->private_data;
> +	void  *private;
> +
> +	vhost_test_stop(n, &private);
> +	vhost_test_flush(n);
> +	vhost_dev_cleanup(&n->dev);
> +	/* We do an extra flush before freeing memory,
> +	 * since jobs can re-queue themselves. */
> +	vhost_test_flush(n);
> +	kfree(n);
> +	return 0;
> +}
> +
> +static long vhost_test_run(struct vhost_test *n, int test)
> +{
> +	void *priv, *oldpriv;
> +	struct vhost_virtqueue *vq;
> +	int r, index;
> +
> +	if (test < 0 || test > 1)
> +		return -EINVAL;
> +
> +	mutex_lock(&n->dev.mutex);
> +	r = vhost_dev_check_owner(&n->dev);
> +	if (r)
> +		goto err;
> +
> +	for (index = 0; index < n->dev.nvqs; ++index) {
> +		/* Verify that ring has been setup correctly. */
> +		if (!vhost_vq_access_ok(&n->vqs[index])) {
> +			r = -EFAULT;
> +			goto err;
> +		}
> +	}
> +
> +	for (index = 0; index < n->dev.nvqs; ++index) {
> +		vq = n->vqs + index;
> +		mutex_lock(&vq->mutex);
> +		priv = test ? n : NULL;
> +
> +		/* start polling new socket */
> +		oldpriv = rcu_dereference_protected(vq->private_data,
> +						    lockdep_is_held(&vq->mutex));
> +		rcu_assign_pointer(vq->private_data, priv);
> +
> +		mutex_unlock(&vq->mutex);
> +
> +		if (oldpriv) {
> +			vhost_test_flush_vq(n, index);
> +		}
> +	}
> +
> +	mutex_unlock(&n->dev.mutex);
> +	return 0;
> +
> +err:
> +	mutex_unlock(&n->dev.mutex);
> +	return r;
> +}
> +
> +static long vhost_test_reset_owner(struct vhost_test *n)
> +{
> +	void *priv = NULL;
> +	long err;
> +	mutex_lock(&n->dev.mutex);
> +	err = vhost_dev_check_owner(&n->dev);
> +	if (err)
> +		goto done;
> +	vhost_test_stop(n, &priv);
> +	vhost_test_flush(n);
> +	err = vhost_dev_reset_owner(&n->dev);
> +done:
> +	mutex_unlock(&n->dev.mutex);
> +	return err;
> +}
> +
> +static int vhost_test_set_features(struct vhost_test *n, u64 features)
> +{
> +	mutex_lock(&n->dev.mutex);
> +	if ((features & (1 << VHOST_F_LOG_ALL)) &&
> +	    !vhost_log_access_ok(&n->dev)) {
> +		mutex_unlock(&n->dev.mutex);
> +		return -EFAULT;
> +	}
> +	n->dev.acked_features = features;
> +	smp_wmb();
> +	vhost_test_flush(n);
> +	mutex_unlock(&n->dev.mutex);
> +	return 0;
> +}
> +
> +static long vhost_test_ioctl(struct file *f, unsigned int ioctl,
> +			     unsigned long arg)
> +{
> +	struct vhost_test *n = f->private_data;
> +	void __user *argp = (void __user *)arg;
> +	u64 __user *featurep = argp;
> +	int test;
> +	u64 features;
> +	int r;
> +	switch (ioctl) {
> +	case VHOST_TEST_RUN:
> +		if (copy_from_user(&test, argp, sizeof test))
> +			return -EFAULT;
> +		return vhost_test_run(n, test);
> +	case VHOST_GET_FEATURES:
> +		features = VHOST_FEATURES;
> +		if (copy_to_user(featurep, &features, sizeof features))
> +			return -EFAULT;
> +		return 0;
> +	case VHOST_SET_FEATURES:
> +		if (copy_from_user(&features, featurep, sizeof features))
> +			return -EFAULT;
> +		if (features & ~VHOST_FEATURES)
> +			return -EOPNOTSUPP;
> +		return vhost_test_set_features(n, features);
> +	case VHOST_RESET_OWNER:
> +		return vhost_test_reset_owner(n);
> +	default:
> +		mutex_lock(&n->dev.mutex);
> +		r = vhost_dev_ioctl(&n->dev, ioctl, arg);
> +		vhost_test_flush(n);
> +		mutex_unlock(&n->dev.mutex);
> +		return r;
> +	}
> +}
> +
> +#ifdef CONFIG_COMPAT
> +static long vhost_test_compat_ioctl(struct file *f, unsigned int ioctl,
> +				   unsigned long arg)
> +{
> +	return vhost_test_ioctl(f, ioctl, (unsigned long)compat_ptr(arg));
> +}
> +#endif
> +
> +static const struct file_operations vhost_test_fops = {
> +	.owner          = THIS_MODULE,
> +	.release        = vhost_test_release,
> +	.unlocked_ioctl = vhost_test_ioctl,
> +#ifdef CONFIG_COMPAT
> +	.compat_ioctl   = vhost_test_compat_ioctl,
> +#endif
> +	.open           = vhost_test_open,
> +	.llseek		= noop_llseek,
> +};
> +
> +static struct miscdevice vhost_test_misc = {
> +	MISC_DYNAMIC_MINOR,
> +	"vhost-test",
> +	&vhost_test_fops,
> +};
> +
> +static int vhost_test_init(void)
> +{
> +	return misc_register(&vhost_test_misc);
> +}
> +module_init(vhost_test_init);
> +
> +static void vhost_test_exit(void)
> +{
> +	misc_deregister(&vhost_test_misc);
> +}
> +module_exit(vhost_test_exit);
> +
> +MODULE_VERSION("0.0.1");
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("Michael S. Tsirkin");
> +MODULE_DESCRIPTION("Host kernel side for virtio simulator");
> diff --git a/drivers/vhost/test.h b/drivers/vhost/test.h
> new file mode 100644
> index 0000000..1fef5df
> --- /dev/null
> +++ b/drivers/vhost/test.h
> @@ -0,0 +1,7 @@
> +#ifndef LINUX_VHOST_TEST_H
> +#define LINUX_VHOST_TEST_H
> +
> +/* Start a given test on the virtio null device. 0 stops all tests. */
> +#define VHOST_TEST_RUN _IOW(VHOST_VIRTIO, 0x31, int)
> +
> +#endif
> diff --git a/tools/virtio/vhost_test/Makefile b/tools/virtio/vhost_test/Makefile
> new file mode 100644
> index 0000000..a1d35b8
> --- /dev/null
> +++ b/tools/virtio/vhost_test/Makefile
> @@ -0,0 +1,2 @@
> +obj-m += vhost_test.o
> +EXTRA_CFLAGS += -Idrivers/vhost
> diff --git a/tools/virtio/vhost_test/vhost_test.c b/tools/virtio/vhost_test/vhost_test.c
> new file mode 100644
> index 0000000..1873518
> --- /dev/null
> +++ b/tools/virtio/vhost_test/vhost_test.c
> @@ -0,0 +1 @@
> +#include "test.c"
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* Re: [PATCH 1/2] vhost test module
From: Michael S. Tsirkin @ 2010-12-02 19:11 UTC (permalink / raw)
  To: Paul E. McKenney; +Cc: linux-kernel, kvm, virtualization
In-Reply-To: <20101202190037.GH2085@linux.vnet.ibm.com>

On Thu, Dec 02, 2010 at 11:00:37AM -0800, Paul E. McKenney wrote:
> On Mon, Nov 29, 2010 at 07:09:01PM +0200, Michael S. Tsirkin wrote:
> > This adds a test module for vhost infrastructure.
> > Intentionally not tied to kbuild to prevent people
> > from installing and loading it accidentally.
> > 
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> 
> On question below.
> 
> > ---
> > 
> > diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
> > new file mode 100644
> > index 0000000..099f302
> > --- /dev/null
> > +++ b/drivers/vhost/test.c
> > @@ -0,0 +1,320 @@
> > +/* Copyright (C) 2009 Red Hat, Inc.
> > + * Author: Michael S. Tsirkin <mst@redhat.com>
> > + *
> > + * This work is licensed under the terms of the GNU GPL, version 2.
> > + *
> > + * test virtio server in host kernel.
> > + */
> > +
> > +#include <linux/compat.h>
> > +#include <linux/eventfd.h>
> > +#include <linux/vhost.h>
> > +#include <linux/miscdevice.h>
> > +#include <linux/module.h>
> > +#include <linux/mutex.h>
> > +#include <linux/workqueue.h>
> > +#include <linux/rcupdate.h>
> > +#include <linux/file.h>
> > +#include <linux/slab.h>
> > +
> > +#include "test.h"
> > +#include "vhost.c"
> > +
> > +/* Max number of bytes transferred before requeueing the job.
> > + * Using this limit prevents one virtqueue from starving others. */
> > +#define VHOST_TEST_WEIGHT 0x80000
> > +
> > +enum {
> > +	VHOST_TEST_VQ = 0,
> > +	VHOST_TEST_VQ_MAX = 1,
> > +};
> > +
> > +struct vhost_test {
> > +	struct vhost_dev dev;
> > +	struct vhost_virtqueue vqs[VHOST_TEST_VQ_MAX];
> > +};
> > +
> > +/* Expects to be always run from workqueue - which acts as
> > + * read-size critical section for our kind of RCU. */
> > +static void handle_vq(struct vhost_test *n)
> > +{
> > +	struct vhost_virtqueue *vq = &n->dev.vqs[VHOST_TEST_VQ];
> > +	unsigned out, in;
> > +	int head;
> > +	size_t len, total_len = 0;
> > +	void *private;
> > +
> > +	private = rcu_dereference_check(vq->private_data, 1);
> 
> Any chance of a check for running in a workqueue?  If I remember correctly,
> the ->lockdep_map field in the work_struct structure allows you to create
> the required lockdep expression.
> 
> 							Thanx, Paul

We moved away from using the workqueue to a custom kernel thread
implementation though.


> > +	if (!private)
> > +		return;
> > +
> > +	mutex_lock(&vq->mutex);
> > +	vhost_disable_notify(vq);
> > +
> > +	for (;;) {
> > +		head = vhost_get_vq_desc(&n->dev, vq, vq->iov,
> > +					 ARRAY_SIZE(vq->iov),
> > +					 &out, &in,
> > +					 NULL, NULL);
> > +		/* On error, stop handling until the next kick. */
> > +		if (unlikely(head < 0))
> > +			break;
> > +		/* Nothing new?  Wait for eventfd to tell us they refilled. */
> > +		if (head == vq->num) {
> > +			if (unlikely(vhost_enable_notify(vq))) {
> > +				vhost_disable_notify(vq);
> > +				continue;
> > +			}
> > +			break;
> > +		}
> > +		if (in) {
> > +			vq_err(vq, "Unexpected descriptor format for TX: "
> > +			       "out %d, int %d\n", out, in);
> > +			break;
> > +		}
> > +		len = iov_length(vq->iov, out);
> > +		/* Sanity check */
> > +		if (!len) {
> > +			vq_err(vq, "Unexpected 0 len for TX\n");
> > +			break;
> > +		}
> > +		vhost_add_used_and_signal(&n->dev, vq, head, 0);
> > +		total_len += len;
> > +		if (unlikely(total_len >= VHOST_TEST_WEIGHT)) {
> > +			vhost_poll_queue(&vq->poll);
> > +			break;
> > +		}
> > +	}
> > +
> > +	mutex_unlock(&vq->mutex);
> > +}
> > +
> > +static void handle_vq_kick(struct vhost_work *work)
> > +{
> > +	struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue,
> > +						  poll.work);
> > +	struct vhost_test *n = container_of(vq->dev, struct vhost_test, dev);
> > +
> > +	handle_vq(n);
> > +}
> > +
> > +static int vhost_test_open(struct inode *inode, struct file *f)
> > +{
> > +	struct vhost_test *n = kmalloc(sizeof *n, GFP_KERNEL);
> > +	struct vhost_dev *dev;
> > +	int r;
> > +
> > +	if (!n)
> > +		return -ENOMEM;
> > +
> > +	dev = &n->dev;
> > +	n->vqs[VHOST_TEST_VQ].handle_kick = handle_vq_kick;
> > +	r = vhost_dev_init(dev, n->vqs, VHOST_TEST_VQ_MAX);
> > +	if (r < 0) {
> > +		kfree(n);
> > +		return r;
> > +	}
> > +
> > +	f->private_data = n;
> > +
> > +	return 0;
> > +}
> > +
> > +static void *vhost_test_stop_vq(struct vhost_test *n,
> > +				struct vhost_virtqueue *vq)
> > +{
> > +	void *private;
> > +
> > +	mutex_lock(&vq->mutex);
> > +	private = rcu_dereference_protected(vq->private_data,
> > +					 lockdep_is_held(&vq->mutex));
> > +	rcu_assign_pointer(vq->private_data, NULL);
> > +	mutex_unlock(&vq->mutex);
> > +	return private;
> > +}
> > +
> > +static void vhost_test_stop(struct vhost_test *n, void **privatep)
> > +{
> > +	*privatep = vhost_test_stop_vq(n, n->vqs + VHOST_TEST_VQ);
> > +}
> > +
> > +static void vhost_test_flush_vq(struct vhost_test *n, int index)
> > +{
> > +	vhost_poll_flush(&n->dev.vqs[index].poll);
> > +}
> > +
> > +static void vhost_test_flush(struct vhost_test *n)
> > +{
> > +	vhost_test_flush_vq(n, VHOST_TEST_VQ);
> > +}
> > +
> > +static int vhost_test_release(struct inode *inode, struct file *f)
> > +{
> > +	struct vhost_test *n = f->private_data;
> > +	void  *private;
> > +
> > +	vhost_test_stop(n, &private);
> > +	vhost_test_flush(n);
> > +	vhost_dev_cleanup(&n->dev);
> > +	/* We do an extra flush before freeing memory,
> > +	 * since jobs can re-queue themselves. */
> > +	vhost_test_flush(n);
> > +	kfree(n);
> > +	return 0;
> > +}
> > +
> > +static long vhost_test_run(struct vhost_test *n, int test)
> > +{
> > +	void *priv, *oldpriv;
> > +	struct vhost_virtqueue *vq;
> > +	int r, index;
> > +
> > +	if (test < 0 || test > 1)
> > +		return -EINVAL;
> > +
> > +	mutex_lock(&n->dev.mutex);
> > +	r = vhost_dev_check_owner(&n->dev);
> > +	if (r)
> > +		goto err;
> > +
> > +	for (index = 0; index < n->dev.nvqs; ++index) {
> > +		/* Verify that ring has been setup correctly. */
> > +		if (!vhost_vq_access_ok(&n->vqs[index])) {
> > +			r = -EFAULT;
> > +			goto err;
> > +		}
> > +	}
> > +
> > +	for (index = 0; index < n->dev.nvqs; ++index) {
> > +		vq = n->vqs + index;
> > +		mutex_lock(&vq->mutex);
> > +		priv = test ? n : NULL;
> > +
> > +		/* start polling new socket */
> > +		oldpriv = rcu_dereference_protected(vq->private_data,
> > +						    lockdep_is_held(&vq->mutex));
> > +		rcu_assign_pointer(vq->private_data, priv);
> > +
> > +		mutex_unlock(&vq->mutex);
> > +
> > +		if (oldpriv) {
> > +			vhost_test_flush_vq(n, index);
> > +		}
> > +	}
> > +
> > +	mutex_unlock(&n->dev.mutex);
> > +	return 0;
> > +
> > +err:
> > +	mutex_unlock(&n->dev.mutex);
> > +	return r;
> > +}
> > +
> > +static long vhost_test_reset_owner(struct vhost_test *n)
> > +{
> > +	void *priv = NULL;
> > +	long err;
> > +	mutex_lock(&n->dev.mutex);
> > +	err = vhost_dev_check_owner(&n->dev);
> > +	if (err)
> > +		goto done;
> > +	vhost_test_stop(n, &priv);
> > +	vhost_test_flush(n);
> > +	err = vhost_dev_reset_owner(&n->dev);
> > +done:
> > +	mutex_unlock(&n->dev.mutex);
> > +	return err;
> > +}
> > +
> > +static int vhost_test_set_features(struct vhost_test *n, u64 features)
> > +{
> > +	mutex_lock(&n->dev.mutex);
> > +	if ((features & (1 << VHOST_F_LOG_ALL)) &&
> > +	    !vhost_log_access_ok(&n->dev)) {
> > +		mutex_unlock(&n->dev.mutex);
> > +		return -EFAULT;
> > +	}
> > +	n->dev.acked_features = features;
> > +	smp_wmb();
> > +	vhost_test_flush(n);
> > +	mutex_unlock(&n->dev.mutex);
> > +	return 0;
> > +}
> > +
> > +static long vhost_test_ioctl(struct file *f, unsigned int ioctl,
> > +			     unsigned long arg)
> > +{
> > +	struct vhost_test *n = f->private_data;
> > +	void __user *argp = (void __user *)arg;
> > +	u64 __user *featurep = argp;
> > +	int test;
> > +	u64 features;
> > +	int r;
> > +	switch (ioctl) {
> > +	case VHOST_TEST_RUN:
> > +		if (copy_from_user(&test, argp, sizeof test))
> > +			return -EFAULT;
> > +		return vhost_test_run(n, test);
> > +	case VHOST_GET_FEATURES:
> > +		features = VHOST_FEATURES;
> > +		if (copy_to_user(featurep, &features, sizeof features))
> > +			return -EFAULT;
> > +		return 0;
> > +	case VHOST_SET_FEATURES:
> > +		if (copy_from_user(&features, featurep, sizeof features))
> > +			return -EFAULT;
> > +		if (features & ~VHOST_FEATURES)
> > +			return -EOPNOTSUPP;
> > +		return vhost_test_set_features(n, features);
> > +	case VHOST_RESET_OWNER:
> > +		return vhost_test_reset_owner(n);
> > +	default:
> > +		mutex_lock(&n->dev.mutex);
> > +		r = vhost_dev_ioctl(&n->dev, ioctl, arg);
> > +		vhost_test_flush(n);
> > +		mutex_unlock(&n->dev.mutex);
> > +		return r;
> > +	}
> > +}
> > +
> > +#ifdef CONFIG_COMPAT
> > +static long vhost_test_compat_ioctl(struct file *f, unsigned int ioctl,
> > +				   unsigned long arg)
> > +{
> > +	return vhost_test_ioctl(f, ioctl, (unsigned long)compat_ptr(arg));
> > +}
> > +#endif
> > +
> > +static const struct file_operations vhost_test_fops = {
> > +	.owner          = THIS_MODULE,
> > +	.release        = vhost_test_release,
> > +	.unlocked_ioctl = vhost_test_ioctl,
> > +#ifdef CONFIG_COMPAT
> > +	.compat_ioctl   = vhost_test_compat_ioctl,
> > +#endif
> > +	.open           = vhost_test_open,
> > +	.llseek		= noop_llseek,
> > +};
> > +
> > +static struct miscdevice vhost_test_misc = {
> > +	MISC_DYNAMIC_MINOR,
> > +	"vhost-test",
> > +	&vhost_test_fops,
> > +};
> > +
> > +static int vhost_test_init(void)
> > +{
> > +	return misc_register(&vhost_test_misc);
> > +}
> > +module_init(vhost_test_init);
> > +
> > +static void vhost_test_exit(void)
> > +{
> > +	misc_deregister(&vhost_test_misc);
> > +}
> > +module_exit(vhost_test_exit);
> > +
> > +MODULE_VERSION("0.0.1");
> > +MODULE_LICENSE("GPL v2");
> > +MODULE_AUTHOR("Michael S. Tsirkin");
> > +MODULE_DESCRIPTION("Host kernel side for virtio simulator");
> > diff --git a/drivers/vhost/test.h b/drivers/vhost/test.h
> > new file mode 100644
> > index 0000000..1fef5df
> > --- /dev/null
> > +++ b/drivers/vhost/test.h
> > @@ -0,0 +1,7 @@
> > +#ifndef LINUX_VHOST_TEST_H
> > +#define LINUX_VHOST_TEST_H
> > +
> > +/* Start a given test on the virtio null device. 0 stops all tests. */
> > +#define VHOST_TEST_RUN _IOW(VHOST_VIRTIO, 0x31, int)
> > +
> > +#endif
> > diff --git a/tools/virtio/vhost_test/Makefile b/tools/virtio/vhost_test/Makefile
> > new file mode 100644
> > index 0000000..a1d35b8
> > --- /dev/null
> > +++ b/tools/virtio/vhost_test/Makefile
> > @@ -0,0 +1,2 @@
> > +obj-m += vhost_test.o
> > +EXTRA_CFLAGS += -Idrivers/vhost
> > diff --git a/tools/virtio/vhost_test/vhost_test.c b/tools/virtio/vhost_test/vhost_test.c
> > new file mode 100644
> > index 0000000..1873518
> > --- /dev/null
> > +++ b/tools/virtio/vhost_test/vhost_test.c
> > @@ -0,0 +1 @@
> > +#include "test.c"
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* Re: [PATCH 1/2] vhost test module
From: Paul E. McKenney @ 2010-12-02 19:26 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: linux-kernel, kvm, virtualization
In-Reply-To: <20101202191130.GA8092@redhat.com>

On Thu, Dec 02, 2010 at 09:11:30PM +0200, Michael S. Tsirkin wrote:
> On Thu, Dec 02, 2010 at 11:00:37AM -0800, Paul E. McKenney wrote:
> > On Mon, Nov 29, 2010 at 07:09:01PM +0200, Michael S. Tsirkin wrote:
> > > This adds a test module for vhost infrastructure.
> > > Intentionally not tied to kbuild to prevent people
> > > from installing and loading it accidentally.
> > > 
> > > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > 
> > On question below.
> > 
> > > ---
> > > 
> > > diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
> > > new file mode 100644
> > > index 0000000..099f302
> > > --- /dev/null
> > > +++ b/drivers/vhost/test.c
> > > @@ -0,0 +1,320 @@
> > > +/* Copyright (C) 2009 Red Hat, Inc.
> > > + * Author: Michael S. Tsirkin <mst@redhat.com>
> > > + *
> > > + * This work is licensed under the terms of the GNU GPL, version 2.
> > > + *
> > > + * test virtio server in host kernel.
> > > + */
> > > +
> > > +#include <linux/compat.h>
> > > +#include <linux/eventfd.h>
> > > +#include <linux/vhost.h>
> > > +#include <linux/miscdevice.h>
> > > +#include <linux/module.h>
> > > +#include <linux/mutex.h>
> > > +#include <linux/workqueue.h>
> > > +#include <linux/rcupdate.h>
> > > +#include <linux/file.h>
> > > +#include <linux/slab.h>
> > > +
> > > +#include "test.h"
> > > +#include "vhost.c"
> > > +
> > > +/* Max number of bytes transferred before requeueing the job.
> > > + * Using this limit prevents one virtqueue from starving others. */
> > > +#define VHOST_TEST_WEIGHT 0x80000
> > > +
> > > +enum {
> > > +	VHOST_TEST_VQ = 0,
> > > +	VHOST_TEST_VQ_MAX = 1,
> > > +};
> > > +
> > > +struct vhost_test {
> > > +	struct vhost_dev dev;
> > > +	struct vhost_virtqueue vqs[VHOST_TEST_VQ_MAX];
> > > +};
> > > +
> > > +/* Expects to be always run from workqueue - which acts as
> > > + * read-size critical section for our kind of RCU. */
> > > +static void handle_vq(struct vhost_test *n)
> > > +{
> > > +	struct vhost_virtqueue *vq = &n->dev.vqs[VHOST_TEST_VQ];
> > > +	unsigned out, in;
> > > +	int head;
> > > +	size_t len, total_len = 0;
> > > +	void *private;
> > > +
> > > +	private = rcu_dereference_check(vq->private_data, 1);
> > 
> > Any chance of a check for running in a workqueue?  If I remember correctly,
> > the ->lockdep_map field in the work_struct structure allows you to create
> > the required lockdep expression.
> 
> We moved away from using the workqueue to a custom kernel thread
> implementation though.

OK, then could you please add a check for "current == custom_kernel_thread"
or some such?

							Thanx, Paul

> > > +	if (!private)
> > > +		return;
> > > +
> > > +	mutex_lock(&vq->mutex);
> > > +	vhost_disable_notify(vq);
> > > +
> > > +	for (;;) {
> > > +		head = vhost_get_vq_desc(&n->dev, vq, vq->iov,
> > > +					 ARRAY_SIZE(vq->iov),
> > > +					 &out, &in,
> > > +					 NULL, NULL);
> > > +		/* On error, stop handling until the next kick. */
> > > +		if (unlikely(head < 0))
> > > +			break;
> > > +		/* Nothing new?  Wait for eventfd to tell us they refilled. */
> > > +		if (head == vq->num) {
> > > +			if (unlikely(vhost_enable_notify(vq))) {
> > > +				vhost_disable_notify(vq);
> > > +				continue;
> > > +			}
> > > +			break;
> > > +		}
> > > +		if (in) {
> > > +			vq_err(vq, "Unexpected descriptor format for TX: "
> > > +			       "out %d, int %d\n", out, in);
> > > +			break;
> > > +		}
> > > +		len = iov_length(vq->iov, out);
> > > +		/* Sanity check */
> > > +		if (!len) {
> > > +			vq_err(vq, "Unexpected 0 len for TX\n");
> > > +			break;
> > > +		}
> > > +		vhost_add_used_and_signal(&n->dev, vq, head, 0);
> > > +		total_len += len;
> > > +		if (unlikely(total_len >= VHOST_TEST_WEIGHT)) {
> > > +			vhost_poll_queue(&vq->poll);
> > > +			break;
> > > +		}
> > > +	}
> > > +
> > > +	mutex_unlock(&vq->mutex);
> > > +}
> > > +
> > > +static void handle_vq_kick(struct vhost_work *work)
> > > +{
> > > +	struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue,
> > > +						  poll.work);
> > > +	struct vhost_test *n = container_of(vq->dev, struct vhost_test, dev);
> > > +
> > > +	handle_vq(n);
> > > +}
> > > +
> > > +static int vhost_test_open(struct inode *inode, struct file *f)
> > > +{
> > > +	struct vhost_test *n = kmalloc(sizeof *n, GFP_KERNEL);
> > > +	struct vhost_dev *dev;
> > > +	int r;
> > > +
> > > +	if (!n)
> > > +		return -ENOMEM;
> > > +
> > > +	dev = &n->dev;
> > > +	n->vqs[VHOST_TEST_VQ].handle_kick = handle_vq_kick;
> > > +	r = vhost_dev_init(dev, n->vqs, VHOST_TEST_VQ_MAX);
> > > +	if (r < 0) {
> > > +		kfree(n);
> > > +		return r;
> > > +	}
> > > +
> > > +	f->private_data = n;
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static void *vhost_test_stop_vq(struct vhost_test *n,
> > > +				struct vhost_virtqueue *vq)
> > > +{
> > > +	void *private;
> > > +
> > > +	mutex_lock(&vq->mutex);
> > > +	private = rcu_dereference_protected(vq->private_data,
> > > +					 lockdep_is_held(&vq->mutex));
> > > +	rcu_assign_pointer(vq->private_data, NULL);
> > > +	mutex_unlock(&vq->mutex);
> > > +	return private;
> > > +}
> > > +
> > > +static void vhost_test_stop(struct vhost_test *n, void **privatep)
> > > +{
> > > +	*privatep = vhost_test_stop_vq(n, n->vqs + VHOST_TEST_VQ);
> > > +}
> > > +
> > > +static void vhost_test_flush_vq(struct vhost_test *n, int index)
> > > +{
> > > +	vhost_poll_flush(&n->dev.vqs[index].poll);
> > > +}
> > > +
> > > +static void vhost_test_flush(struct vhost_test *n)
> > > +{
> > > +	vhost_test_flush_vq(n, VHOST_TEST_VQ);
> > > +}
> > > +
> > > +static int vhost_test_release(struct inode *inode, struct file *f)
> > > +{
> > > +	struct vhost_test *n = f->private_data;
> > > +	void  *private;
> > > +
> > > +	vhost_test_stop(n, &private);
> > > +	vhost_test_flush(n);
> > > +	vhost_dev_cleanup(&n->dev);
> > > +	/* We do an extra flush before freeing memory,
> > > +	 * since jobs can re-queue themselves. */
> > > +	vhost_test_flush(n);
> > > +	kfree(n);
> > > +	return 0;
> > > +}
> > > +
> > > +static long vhost_test_run(struct vhost_test *n, int test)
> > > +{
> > > +	void *priv, *oldpriv;
> > > +	struct vhost_virtqueue *vq;
> > > +	int r, index;
> > > +
> > > +	if (test < 0 || test > 1)
> > > +		return -EINVAL;
> > > +
> > > +	mutex_lock(&n->dev.mutex);
> > > +	r = vhost_dev_check_owner(&n->dev);
> > > +	if (r)
> > > +		goto err;
> > > +
> > > +	for (index = 0; index < n->dev.nvqs; ++index) {
> > > +		/* Verify that ring has been setup correctly. */
> > > +		if (!vhost_vq_access_ok(&n->vqs[index])) {
> > > +			r = -EFAULT;
> > > +			goto err;
> > > +		}
> > > +	}
> > > +
> > > +	for (index = 0; index < n->dev.nvqs; ++index) {
> > > +		vq = n->vqs + index;
> > > +		mutex_lock(&vq->mutex);
> > > +		priv = test ? n : NULL;
> > > +
> > > +		/* start polling new socket */
> > > +		oldpriv = rcu_dereference_protected(vq->private_data,
> > > +						    lockdep_is_held(&vq->mutex));
> > > +		rcu_assign_pointer(vq->private_data, priv);
> > > +
> > > +		mutex_unlock(&vq->mutex);
> > > +
> > > +		if (oldpriv) {
> > > +			vhost_test_flush_vq(n, index);
> > > +		}
> > > +	}
> > > +
> > > +	mutex_unlock(&n->dev.mutex);
> > > +	return 0;
> > > +
> > > +err:
> > > +	mutex_unlock(&n->dev.mutex);
> > > +	return r;
> > > +}
> > > +
> > > +static long vhost_test_reset_owner(struct vhost_test *n)
> > > +{
> > > +	void *priv = NULL;
> > > +	long err;
> > > +	mutex_lock(&n->dev.mutex);
> > > +	err = vhost_dev_check_owner(&n->dev);
> > > +	if (err)
> > > +		goto done;
> > > +	vhost_test_stop(n, &priv);
> > > +	vhost_test_flush(n);
> > > +	err = vhost_dev_reset_owner(&n->dev);
> > > +done:
> > > +	mutex_unlock(&n->dev.mutex);
> > > +	return err;
> > > +}
> > > +
> > > +static int vhost_test_set_features(struct vhost_test *n, u64 features)
> > > +{
> > > +	mutex_lock(&n->dev.mutex);
> > > +	if ((features & (1 << VHOST_F_LOG_ALL)) &&
> > > +	    !vhost_log_access_ok(&n->dev)) {
> > > +		mutex_unlock(&n->dev.mutex);
> > > +		return -EFAULT;
> > > +	}
> > > +	n->dev.acked_features = features;
> > > +	smp_wmb();
> > > +	vhost_test_flush(n);
> > > +	mutex_unlock(&n->dev.mutex);
> > > +	return 0;
> > > +}
> > > +
> > > +static long vhost_test_ioctl(struct file *f, unsigned int ioctl,
> > > +			     unsigned long arg)
> > > +{
> > > +	struct vhost_test *n = f->private_data;
> > > +	void __user *argp = (void __user *)arg;
> > > +	u64 __user *featurep = argp;
> > > +	int test;
> > > +	u64 features;
> > > +	int r;
> > > +	switch (ioctl) {
> > > +	case VHOST_TEST_RUN:
> > > +		if (copy_from_user(&test, argp, sizeof test))
> > > +			return -EFAULT;
> > > +		return vhost_test_run(n, test);
> > > +	case VHOST_GET_FEATURES:
> > > +		features = VHOST_FEATURES;
> > > +		if (copy_to_user(featurep, &features, sizeof features))
> > > +			return -EFAULT;
> > > +		return 0;
> > > +	case VHOST_SET_FEATURES:
> > > +		if (copy_from_user(&features, featurep, sizeof features))
> > > +			return -EFAULT;
> > > +		if (features & ~VHOST_FEATURES)
> > > +			return -EOPNOTSUPP;
> > > +		return vhost_test_set_features(n, features);
> > > +	case VHOST_RESET_OWNER:
> > > +		return vhost_test_reset_owner(n);
> > > +	default:
> > > +		mutex_lock(&n->dev.mutex);
> > > +		r = vhost_dev_ioctl(&n->dev, ioctl, arg);
> > > +		vhost_test_flush(n);
> > > +		mutex_unlock(&n->dev.mutex);
> > > +		return r;
> > > +	}
> > > +}
> > > +
> > > +#ifdef CONFIG_COMPAT
> > > +static long vhost_test_compat_ioctl(struct file *f, unsigned int ioctl,
> > > +				   unsigned long arg)
> > > +{
> > > +	return vhost_test_ioctl(f, ioctl, (unsigned long)compat_ptr(arg));
> > > +}
> > > +#endif
> > > +
> > > +static const struct file_operations vhost_test_fops = {
> > > +	.owner          = THIS_MODULE,
> > > +	.release        = vhost_test_release,
> > > +	.unlocked_ioctl = vhost_test_ioctl,
> > > +#ifdef CONFIG_COMPAT
> > > +	.compat_ioctl   = vhost_test_compat_ioctl,
> > > +#endif
> > > +	.open           = vhost_test_open,
> > > +	.llseek		= noop_llseek,
> > > +};
> > > +
> > > +static struct miscdevice vhost_test_misc = {
> > > +	MISC_DYNAMIC_MINOR,
> > > +	"vhost-test",
> > > +	&vhost_test_fops,
> > > +};
> > > +
> > > +static int vhost_test_init(void)
> > > +{
> > > +	return misc_register(&vhost_test_misc);
> > > +}
> > > +module_init(vhost_test_init);
> > > +
> > > +static void vhost_test_exit(void)
> > > +{
> > > +	misc_deregister(&vhost_test_misc);
> > > +}
> > > +module_exit(vhost_test_exit);
> > > +
> > > +MODULE_VERSION("0.0.1");
> > > +MODULE_LICENSE("GPL v2");
> > > +MODULE_AUTHOR("Michael S. Tsirkin");
> > > +MODULE_DESCRIPTION("Host kernel side for virtio simulator");
> > > diff --git a/drivers/vhost/test.h b/drivers/vhost/test.h
> > > new file mode 100644
> > > index 0000000..1fef5df
> > > --- /dev/null
> > > +++ b/drivers/vhost/test.h
> > > @@ -0,0 +1,7 @@
> > > +#ifndef LINUX_VHOST_TEST_H
> > > +#define LINUX_VHOST_TEST_H
> > > +
> > > +/* Start a given test on the virtio null device. 0 stops all tests. */
> > > +#define VHOST_TEST_RUN _IOW(VHOST_VIRTIO, 0x31, int)
> > > +
> > > +#endif
> > > diff --git a/tools/virtio/vhost_test/Makefile b/tools/virtio/vhost_test/Makefile
> > > new file mode 100644
> > > index 0000000..a1d35b8
> > > --- /dev/null
> > > +++ b/tools/virtio/vhost_test/Makefile
> > > @@ -0,0 +1,2 @@
> > > +obj-m += vhost_test.o
> > > +EXTRA_CFLAGS += -Idrivers/vhost
> > > diff --git a/tools/virtio/vhost_test/vhost_test.c b/tools/virtio/vhost_test/vhost_test.c
> > > new file mode 100644
> > > index 0000000..1873518
> > > --- /dev/null
> > > +++ b/tools/virtio/vhost_test/vhost_test.c
> > > @@ -0,0 +1 @@
> > > +#include "test.c"
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > > the body of a message to majordomo@vger.kernel.org
> > > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > > Please read the FAQ at  http://www.tux.org/lkml/
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* Re: [PATCH 1/2] vhost test module
From: Michael S. Tsirkin @ 2010-12-02 19:47 UTC (permalink / raw)
  To: Paul E. McKenney; +Cc: linux-kernel, kvm, virtualization
In-Reply-To: <20101202192616.GL2085@linux.vnet.ibm.com>

On Thu, Dec 02, 2010 at 11:26:16AM -0800, Paul E. McKenney wrote:
> On Thu, Dec 02, 2010 at 09:11:30PM +0200, Michael S. Tsirkin wrote:
> > On Thu, Dec 02, 2010 at 11:00:37AM -0800, Paul E. McKenney wrote:
> > > On Mon, Nov 29, 2010 at 07:09:01PM +0200, Michael S. Tsirkin wrote:
> > > > This adds a test module for vhost infrastructure.
> > > > Intentionally not tied to kbuild to prevent people
> > > > from installing and loading it accidentally.
> > > > 
> > > > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > > 
> > > On question below.
> > > 
> > > > ---
> > > > 
> > > > diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
> > > > new file mode 100644
> > > > index 0000000..099f302
> > > > --- /dev/null
> > > > +++ b/drivers/vhost/test.c
> > > > @@ -0,0 +1,320 @@
> > > > +/* Copyright (C) 2009 Red Hat, Inc.
> > > > + * Author: Michael S. Tsirkin <mst@redhat.com>
> > > > + *
> > > > + * This work is licensed under the terms of the GNU GPL, version 2.
> > > > + *
> > > > + * test virtio server in host kernel.
> > > > + */
> > > > +
> > > > +#include <linux/compat.h>
> > > > +#include <linux/eventfd.h>
> > > > +#include <linux/vhost.h>
> > > > +#include <linux/miscdevice.h>
> > > > +#include <linux/module.h>
> > > > +#include <linux/mutex.h>
> > > > +#include <linux/workqueue.h>
> > > > +#include <linux/rcupdate.h>
> > > > +#include <linux/file.h>
> > > > +#include <linux/slab.h>
> > > > +
> > > > +#include "test.h"
> > > > +#include "vhost.c"
> > > > +
> > > > +/* Max number of bytes transferred before requeueing the job.
> > > > + * Using this limit prevents one virtqueue from starving others. */
> > > > +#define VHOST_TEST_WEIGHT 0x80000
> > > > +
> > > > +enum {
> > > > +	VHOST_TEST_VQ = 0,
> > > > +	VHOST_TEST_VQ_MAX = 1,
> > > > +};
> > > > +
> > > > +struct vhost_test {
> > > > +	struct vhost_dev dev;
> > > > +	struct vhost_virtqueue vqs[VHOST_TEST_VQ_MAX];
> > > > +};
> > > > +
> > > > +/* Expects to be always run from workqueue - which acts as
> > > > + * read-size critical section for our kind of RCU. */
> > > > +static void handle_vq(struct vhost_test *n)
> > > > +{
> > > > +	struct vhost_virtqueue *vq = &n->dev.vqs[VHOST_TEST_VQ];
> > > > +	unsigned out, in;
> > > > +	int head;
> > > > +	size_t len, total_len = 0;
> > > > +	void *private;
> > > > +
> > > > +	private = rcu_dereference_check(vq->private_data, 1);
> > > 
> > > Any chance of a check for running in a workqueue?  If I remember correctly,
> > > the ->lockdep_map field in the work_struct structure allows you to create
> > > the required lockdep expression.
> > 
> > We moved away from using the workqueue to a custom kernel thread
> > implementation though.
> 
> OK, then could you please add a check for "current == custom_kernel_thread"
> or some such?
> 
> 							Thanx, Paul

It's a bit tricky. The way we flush out things is by an analog of
flush_work. So just checking that we run from workqueue isn't
right need to check that we are running from one of the specific work
structures that we are careful to flush.

I can do this by passing the work structure pointer on to relevant
functions but I think this will add (very minor) overhead even when rcu
checks are disabled. Does it matter? Thoughts?

> > > > +	if (!private)
> > > > +		return;
> > > > +
> > > > +	mutex_lock(&vq->mutex);
> > > > +	vhost_disable_notify(vq);
> > > > +
> > > > +	for (;;) {
> > > > +		head = vhost_get_vq_desc(&n->dev, vq, vq->iov,
> > > > +					 ARRAY_SIZE(vq->iov),
> > > > +					 &out, &in,
> > > > +					 NULL, NULL);
> > > > +		/* On error, stop handling until the next kick. */
> > > > +		if (unlikely(head < 0))
> > > > +			break;
> > > > +		/* Nothing new?  Wait for eventfd to tell us they refilled. */
> > > > +		if (head == vq->num) {
> > > > +			if (unlikely(vhost_enable_notify(vq))) {
> > > > +				vhost_disable_notify(vq);
> > > > +				continue;
> > > > +			}
> > > > +			break;
> > > > +		}
> > > > +		if (in) {
> > > > +			vq_err(vq, "Unexpected descriptor format for TX: "
> > > > +			       "out %d, int %d\n", out, in);
> > > > +			break;
> > > > +		}
> > > > +		len = iov_length(vq->iov, out);
> > > > +		/* Sanity check */
> > > > +		if (!len) {
> > > > +			vq_err(vq, "Unexpected 0 len for TX\n");
> > > > +			break;
> > > > +		}
> > > > +		vhost_add_used_and_signal(&n->dev, vq, head, 0);
> > > > +		total_len += len;
> > > > +		if (unlikely(total_len >= VHOST_TEST_WEIGHT)) {
> > > > +			vhost_poll_queue(&vq->poll);
> > > > +			break;
> > > > +		}
> > > > +	}
> > > > +
> > > > +	mutex_unlock(&vq->mutex);
> > > > +}
> > > > +
> > > > +static void handle_vq_kick(struct vhost_work *work)
> > > > +{
> > > > +	struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue,
> > > > +						  poll.work);
> > > > +	struct vhost_test *n = container_of(vq->dev, struct vhost_test, dev);
> > > > +
> > > > +	handle_vq(n);
> > > > +}
> > > > +
> > > > +static int vhost_test_open(struct inode *inode, struct file *f)
> > > > +{
> > > > +	struct vhost_test *n = kmalloc(sizeof *n, GFP_KERNEL);
> > > > +	struct vhost_dev *dev;
> > > > +	int r;
> > > > +
> > > > +	if (!n)
> > > > +		return -ENOMEM;
> > > > +
> > > > +	dev = &n->dev;
> > > > +	n->vqs[VHOST_TEST_VQ].handle_kick = handle_vq_kick;
> > > > +	r = vhost_dev_init(dev, n->vqs, VHOST_TEST_VQ_MAX);
> > > > +	if (r < 0) {
> > > > +		kfree(n);
> > > > +		return r;
> > > > +	}
> > > > +
> > > > +	f->private_data = n;
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +static void *vhost_test_stop_vq(struct vhost_test *n,
> > > > +				struct vhost_virtqueue *vq)
> > > > +{
> > > > +	void *private;
> > > > +
> > > > +	mutex_lock(&vq->mutex);
> > > > +	private = rcu_dereference_protected(vq->private_data,
> > > > +					 lockdep_is_held(&vq->mutex));
> > > > +	rcu_assign_pointer(vq->private_data, NULL);
> > > > +	mutex_unlock(&vq->mutex);
> > > > +	return private;
> > > > +}
> > > > +
> > > > +static void vhost_test_stop(struct vhost_test *n, void **privatep)
> > > > +{
> > > > +	*privatep = vhost_test_stop_vq(n, n->vqs + VHOST_TEST_VQ);
> > > > +}
> > > > +
> > > > +static void vhost_test_flush_vq(struct vhost_test *n, int index)
> > > > +{
> > > > +	vhost_poll_flush(&n->dev.vqs[index].poll);
> > > > +}
> > > > +
> > > > +static void vhost_test_flush(struct vhost_test *n)
> > > > +{
> > > > +	vhost_test_flush_vq(n, VHOST_TEST_VQ);
> > > > +}
> > > > +
> > > > +static int vhost_test_release(struct inode *inode, struct file *f)
> > > > +{
> > > > +	struct vhost_test *n = f->private_data;
> > > > +	void  *private;
> > > > +
> > > > +	vhost_test_stop(n, &private);
> > > > +	vhost_test_flush(n);
> > > > +	vhost_dev_cleanup(&n->dev);
> > > > +	/* We do an extra flush before freeing memory,
> > > > +	 * since jobs can re-queue themselves. */
> > > > +	vhost_test_flush(n);
> > > > +	kfree(n);
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +static long vhost_test_run(struct vhost_test *n, int test)
> > > > +{
> > > > +	void *priv, *oldpriv;
> > > > +	struct vhost_virtqueue *vq;
> > > > +	int r, index;
> > > > +
> > > > +	if (test < 0 || test > 1)
> > > > +		return -EINVAL;
> > > > +
> > > > +	mutex_lock(&n->dev.mutex);
> > > > +	r = vhost_dev_check_owner(&n->dev);
> > > > +	if (r)
> > > > +		goto err;
> > > > +
> > > > +	for (index = 0; index < n->dev.nvqs; ++index) {
> > > > +		/* Verify that ring has been setup correctly. */
> > > > +		if (!vhost_vq_access_ok(&n->vqs[index])) {
> > > > +			r = -EFAULT;
> > > > +			goto err;
> > > > +		}
> > > > +	}
> > > > +
> > > > +	for (index = 0; index < n->dev.nvqs; ++index) {
> > > > +		vq = n->vqs + index;
> > > > +		mutex_lock(&vq->mutex);
> > > > +		priv = test ? n : NULL;
> > > > +
> > > > +		/* start polling new socket */
> > > > +		oldpriv = rcu_dereference_protected(vq->private_data,
> > > > +						    lockdep_is_held(&vq->mutex));
> > > > +		rcu_assign_pointer(vq->private_data, priv);
> > > > +
> > > > +		mutex_unlock(&vq->mutex);
> > > > +
> > > > +		if (oldpriv) {
> > > > +			vhost_test_flush_vq(n, index);
> > > > +		}
> > > > +	}
> > > > +
> > > > +	mutex_unlock(&n->dev.mutex);
> > > > +	return 0;
> > > > +
> > > > +err:
> > > > +	mutex_unlock(&n->dev.mutex);
> > > > +	return r;
> > > > +}
> > > > +
> > > > +static long vhost_test_reset_owner(struct vhost_test *n)
> > > > +{
> > > > +	void *priv = NULL;
> > > > +	long err;
> > > > +	mutex_lock(&n->dev.mutex);
> > > > +	err = vhost_dev_check_owner(&n->dev);
> > > > +	if (err)
> > > > +		goto done;
> > > > +	vhost_test_stop(n, &priv);
> > > > +	vhost_test_flush(n);
> > > > +	err = vhost_dev_reset_owner(&n->dev);
> > > > +done:
> > > > +	mutex_unlock(&n->dev.mutex);
> > > > +	return err;
> > > > +}
> > > > +
> > > > +static int vhost_test_set_features(struct vhost_test *n, u64 features)
> > > > +{
> > > > +	mutex_lock(&n->dev.mutex);
> > > > +	if ((features & (1 << VHOST_F_LOG_ALL)) &&
> > > > +	    !vhost_log_access_ok(&n->dev)) {
> > > > +		mutex_unlock(&n->dev.mutex);
> > > > +		return -EFAULT;
> > > > +	}
> > > > +	n->dev.acked_features = features;
> > > > +	smp_wmb();
> > > > +	vhost_test_flush(n);
> > > > +	mutex_unlock(&n->dev.mutex);
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +static long vhost_test_ioctl(struct file *f, unsigned int ioctl,
> > > > +			     unsigned long arg)
> > > > +{
> > > > +	struct vhost_test *n = f->private_data;
> > > > +	void __user *argp = (void __user *)arg;
> > > > +	u64 __user *featurep = argp;
> > > > +	int test;
> > > > +	u64 features;
> > > > +	int r;
> > > > +	switch (ioctl) {
> > > > +	case VHOST_TEST_RUN:
> > > > +		if (copy_from_user(&test, argp, sizeof test))
> > > > +			return -EFAULT;
> > > > +		return vhost_test_run(n, test);
> > > > +	case VHOST_GET_FEATURES:
> > > > +		features = VHOST_FEATURES;
> > > > +		if (copy_to_user(featurep, &features, sizeof features))
> > > > +			return -EFAULT;
> > > > +		return 0;
> > > > +	case VHOST_SET_FEATURES:
> > > > +		if (copy_from_user(&features, featurep, sizeof features))
> > > > +			return -EFAULT;
> > > > +		if (features & ~VHOST_FEATURES)
> > > > +			return -EOPNOTSUPP;
> > > > +		return vhost_test_set_features(n, features);
> > > > +	case VHOST_RESET_OWNER:
> > > > +		return vhost_test_reset_owner(n);
> > > > +	default:
> > > > +		mutex_lock(&n->dev.mutex);
> > > > +		r = vhost_dev_ioctl(&n->dev, ioctl, arg);
> > > > +		vhost_test_flush(n);
> > > > +		mutex_unlock(&n->dev.mutex);
> > > > +		return r;
> > > > +	}
> > > > +}
> > > > +
> > > > +#ifdef CONFIG_COMPAT
> > > > +static long vhost_test_compat_ioctl(struct file *f, unsigned int ioctl,
> > > > +				   unsigned long arg)
> > > > +{
> > > > +	return vhost_test_ioctl(f, ioctl, (unsigned long)compat_ptr(arg));
> > > > +}
> > > > +#endif
> > > > +
> > > > +static const struct file_operations vhost_test_fops = {
> > > > +	.owner          = THIS_MODULE,
> > > > +	.release        = vhost_test_release,
> > > > +	.unlocked_ioctl = vhost_test_ioctl,
> > > > +#ifdef CONFIG_COMPAT
> > > > +	.compat_ioctl   = vhost_test_compat_ioctl,
> > > > +#endif
> > > > +	.open           = vhost_test_open,
> > > > +	.llseek		= noop_llseek,
> > > > +};
> > > > +
> > > > +static struct miscdevice vhost_test_misc = {
> > > > +	MISC_DYNAMIC_MINOR,
> > > > +	"vhost-test",
> > > > +	&vhost_test_fops,
> > > > +};
> > > > +
> > > > +static int vhost_test_init(void)
> > > > +{
> > > > +	return misc_register(&vhost_test_misc);
> > > > +}
> > > > +module_init(vhost_test_init);
> > > > +
> > > > +static void vhost_test_exit(void)
> > > > +{
> > > > +	misc_deregister(&vhost_test_misc);
> > > > +}
> > > > +module_exit(vhost_test_exit);
> > > > +
> > > > +MODULE_VERSION("0.0.1");
> > > > +MODULE_LICENSE("GPL v2");
> > > > +MODULE_AUTHOR("Michael S. Tsirkin");
> > > > +MODULE_DESCRIPTION("Host kernel side for virtio simulator");
> > > > diff --git a/drivers/vhost/test.h b/drivers/vhost/test.h
> > > > new file mode 100644
> > > > index 0000000..1fef5df
> > > > --- /dev/null
> > > > +++ b/drivers/vhost/test.h
> > > > @@ -0,0 +1,7 @@
> > > > +#ifndef LINUX_VHOST_TEST_H
> > > > +#define LINUX_VHOST_TEST_H
> > > > +
> > > > +/* Start a given test on the virtio null device. 0 stops all tests. */
> > > > +#define VHOST_TEST_RUN _IOW(VHOST_VIRTIO, 0x31, int)
> > > > +
> > > > +#endif
> > > > diff --git a/tools/virtio/vhost_test/Makefile b/tools/virtio/vhost_test/Makefile
> > > > new file mode 100644
> > > > index 0000000..a1d35b8
> > > > --- /dev/null
> > > > +++ b/tools/virtio/vhost_test/Makefile
> > > > @@ -0,0 +1,2 @@
> > > > +obj-m += vhost_test.o
> > > > +EXTRA_CFLAGS += -Idrivers/vhost
> > > > diff --git a/tools/virtio/vhost_test/vhost_test.c b/tools/virtio/vhost_test/vhost_test.c
> > > > new file mode 100644
> > > > index 0000000..1873518
> > > > --- /dev/null
> > > > +++ b/tools/virtio/vhost_test/vhost_test.c
> > > > @@ -0,0 +1 @@
> > > > +#include "test.c"
> > > > --
> > > > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > > > the body of a message to majordomo@vger.kernel.org
> > > > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > > > Please read the FAQ at  http://www.tux.org/lkml/
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* Re: [PATCH 1/2] vhost test module
From: Paul E. McKenney @ 2010-12-02 23:13 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: linux-kernel, kvm, virtualization
In-Reply-To: <20101202194709.GA9081@redhat.com>

On Thu, Dec 02, 2010 at 09:47:09PM +0200, Michael S. Tsirkin wrote:
> On Thu, Dec 02, 2010 at 11:26:16AM -0800, Paul E. McKenney wrote:
> > On Thu, Dec 02, 2010 at 09:11:30PM +0200, Michael S. Tsirkin wrote:
> > > On Thu, Dec 02, 2010 at 11:00:37AM -0800, Paul E. McKenney wrote:
> > > > On Mon, Nov 29, 2010 at 07:09:01PM +0200, Michael S. Tsirkin wrote:
> > > > > This adds a test module for vhost infrastructure.
> > > > > Intentionally not tied to kbuild to prevent people
> > > > > from installing and loading it accidentally.
> > > > > 
> > > > > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > > > 
> > > > On question below.
> > > > 
> > > > > ---
> > > > > 
> > > > > diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
> > > > > new file mode 100644
> > > > > index 0000000..099f302
> > > > > --- /dev/null
> > > > > +++ b/drivers/vhost/test.c
> > > > > @@ -0,0 +1,320 @@
> > > > > +/* Copyright (C) 2009 Red Hat, Inc.
> > > > > + * Author: Michael S. Tsirkin <mst@redhat.com>
> > > > > + *
> > > > > + * This work is licensed under the terms of the GNU GPL, version 2.
> > > > > + *
> > > > > + * test virtio server in host kernel.
> > > > > + */
> > > > > +
> > > > > +#include <linux/compat.h>
> > > > > +#include <linux/eventfd.h>
> > > > > +#include <linux/vhost.h>
> > > > > +#include <linux/miscdevice.h>
> > > > > +#include <linux/module.h>
> > > > > +#include <linux/mutex.h>
> > > > > +#include <linux/workqueue.h>
> > > > > +#include <linux/rcupdate.h>
> > > > > +#include <linux/file.h>
> > > > > +#include <linux/slab.h>
> > > > > +
> > > > > +#include "test.h"
> > > > > +#include "vhost.c"
> > > > > +
> > > > > +/* Max number of bytes transferred before requeueing the job.
> > > > > + * Using this limit prevents one virtqueue from starving others. */
> > > > > +#define VHOST_TEST_WEIGHT 0x80000
> > > > > +
> > > > > +enum {
> > > > > +	VHOST_TEST_VQ = 0,
> > > > > +	VHOST_TEST_VQ_MAX = 1,
> > > > > +};
> > > > > +
> > > > > +struct vhost_test {
> > > > > +	struct vhost_dev dev;
> > > > > +	struct vhost_virtqueue vqs[VHOST_TEST_VQ_MAX];
> > > > > +};
> > > > > +
> > > > > +/* Expects to be always run from workqueue - which acts as
> > > > > + * read-size critical section for our kind of RCU. */
> > > > > +static void handle_vq(struct vhost_test *n)
> > > > > +{
> > > > > +	struct vhost_virtqueue *vq = &n->dev.vqs[VHOST_TEST_VQ];
> > > > > +	unsigned out, in;
> > > > > +	int head;
> > > > > +	size_t len, total_len = 0;
> > > > > +	void *private;
> > > > > +
> > > > > +	private = rcu_dereference_check(vq->private_data, 1);
> > > > 
> > > > Any chance of a check for running in a workqueue?  If I remember correctly,
> > > > the ->lockdep_map field in the work_struct structure allows you to create
> > > > the required lockdep expression.
> > > 
> > > We moved away from using the workqueue to a custom kernel thread
> > > implementation though.
> > 
> > OK, then could you please add a check for "current == custom_kernel_thread"
> > or some such?
> > 
> > 							Thanx, Paul
> 
> It's a bit tricky. The way we flush out things is by an analog of
> flush_work. So just checking that we run from workqueue isn't
> right need to check that we are running from one of the specific work
> structures that we are careful to flush.
> 
> I can do this by passing the work structure pointer on to relevant
> functions but I think this will add (very minor) overhead even when rcu
> checks are disabled. Does it matter? Thoughts?

Would it be possible to set up separate lockdep maps, in effect passing
the needed information via lockdep rather than via the function arguments?

							Thanx, Paul

> > > > > +	if (!private)
> > > > > +		return;
> > > > > +
> > > > > +	mutex_lock(&vq->mutex);
> > > > > +	vhost_disable_notify(vq);
> > > > > +
> > > > > +	for (;;) {
> > > > > +		head = vhost_get_vq_desc(&n->dev, vq, vq->iov,
> > > > > +					 ARRAY_SIZE(vq->iov),
> > > > > +					 &out, &in,
> > > > > +					 NULL, NULL);
> > > > > +		/* On error, stop handling until the next kick. */
> > > > > +		if (unlikely(head < 0))
> > > > > +			break;
> > > > > +		/* Nothing new?  Wait for eventfd to tell us they refilled. */
> > > > > +		if (head == vq->num) {
> > > > > +			if (unlikely(vhost_enable_notify(vq))) {
> > > > > +				vhost_disable_notify(vq);
> > > > > +				continue;
> > > > > +			}
> > > > > +			break;
> > > > > +		}
> > > > > +		if (in) {
> > > > > +			vq_err(vq, "Unexpected descriptor format for TX: "
> > > > > +			       "out %d, int %d\n", out, in);
> > > > > +			break;
> > > > > +		}
> > > > > +		len = iov_length(vq->iov, out);
> > > > > +		/* Sanity check */
> > > > > +		if (!len) {
> > > > > +			vq_err(vq, "Unexpected 0 len for TX\n");
> > > > > +			break;
> > > > > +		}
> > > > > +		vhost_add_used_and_signal(&n->dev, vq, head, 0);
> > > > > +		total_len += len;
> > > > > +		if (unlikely(total_len >= VHOST_TEST_WEIGHT)) {
> > > > > +			vhost_poll_queue(&vq->poll);
> > > > > +			break;
> > > > > +		}
> > > > > +	}
> > > > > +
> > > > > +	mutex_unlock(&vq->mutex);
> > > > > +}
> > > > > +
> > > > > +static void handle_vq_kick(struct vhost_work *work)
> > > > > +{
> > > > > +	struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue,
> > > > > +						  poll.work);
> > > > > +	struct vhost_test *n = container_of(vq->dev, struct vhost_test, dev);
> > > > > +
> > > > > +	handle_vq(n);
> > > > > +}
> > > > > +
> > > > > +static int vhost_test_open(struct inode *inode, struct file *f)
> > > > > +{
> > > > > +	struct vhost_test *n = kmalloc(sizeof *n, GFP_KERNEL);
> > > > > +	struct vhost_dev *dev;
> > > > > +	int r;
> > > > > +
> > > > > +	if (!n)
> > > > > +		return -ENOMEM;
> > > > > +
> > > > > +	dev = &n->dev;
> > > > > +	n->vqs[VHOST_TEST_VQ].handle_kick = handle_vq_kick;
> > > > > +	r = vhost_dev_init(dev, n->vqs, VHOST_TEST_VQ_MAX);
> > > > > +	if (r < 0) {
> > > > > +		kfree(n);
> > > > > +		return r;
> > > > > +	}
> > > > > +
> > > > > +	f->private_data = n;
> > > > > +
> > > > > +	return 0;
> > > > > +}
> > > > > +
> > > > > +static void *vhost_test_stop_vq(struct vhost_test *n,
> > > > > +				struct vhost_virtqueue *vq)
> > > > > +{
> > > > > +	void *private;
> > > > > +
> > > > > +	mutex_lock(&vq->mutex);
> > > > > +	private = rcu_dereference_protected(vq->private_data,
> > > > > +					 lockdep_is_held(&vq->mutex));
> > > > > +	rcu_assign_pointer(vq->private_data, NULL);
> > > > > +	mutex_unlock(&vq->mutex);
> > > > > +	return private;
> > > > > +}
> > > > > +
> > > > > +static void vhost_test_stop(struct vhost_test *n, void **privatep)
> > > > > +{
> > > > > +	*privatep = vhost_test_stop_vq(n, n->vqs + VHOST_TEST_VQ);
> > > > > +}
> > > > > +
> > > > > +static void vhost_test_flush_vq(struct vhost_test *n, int index)
> > > > > +{
> > > > > +	vhost_poll_flush(&n->dev.vqs[index].poll);
> > > > > +}
> > > > > +
> > > > > +static void vhost_test_flush(struct vhost_test *n)
> > > > > +{
> > > > > +	vhost_test_flush_vq(n, VHOST_TEST_VQ);
> > > > > +}
> > > > > +
> > > > > +static int vhost_test_release(struct inode *inode, struct file *f)
> > > > > +{
> > > > > +	struct vhost_test *n = f->private_data;
> > > > > +	void  *private;
> > > > > +
> > > > > +	vhost_test_stop(n, &private);
> > > > > +	vhost_test_flush(n);
> > > > > +	vhost_dev_cleanup(&n->dev);
> > > > > +	/* We do an extra flush before freeing memory,
> > > > > +	 * since jobs can re-queue themselves. */
> > > > > +	vhost_test_flush(n);
> > > > > +	kfree(n);
> > > > > +	return 0;
> > > > > +}
> > > > > +
> > > > > +static long vhost_test_run(struct vhost_test *n, int test)
> > > > > +{
> > > > > +	void *priv, *oldpriv;
> > > > > +	struct vhost_virtqueue *vq;
> > > > > +	int r, index;
> > > > > +
> > > > > +	if (test < 0 || test > 1)
> > > > > +		return -EINVAL;
> > > > > +
> > > > > +	mutex_lock(&n->dev.mutex);
> > > > > +	r = vhost_dev_check_owner(&n->dev);
> > > > > +	if (r)
> > > > > +		goto err;
> > > > > +
> > > > > +	for (index = 0; index < n->dev.nvqs; ++index) {
> > > > > +		/* Verify that ring has been setup correctly. */
> > > > > +		if (!vhost_vq_access_ok(&n->vqs[index])) {
> > > > > +			r = -EFAULT;
> > > > > +			goto err;
> > > > > +		}
> > > > > +	}
> > > > > +
> > > > > +	for (index = 0; index < n->dev.nvqs; ++index) {
> > > > > +		vq = n->vqs + index;
> > > > > +		mutex_lock(&vq->mutex);
> > > > > +		priv = test ? n : NULL;
> > > > > +
> > > > > +		/* start polling new socket */
> > > > > +		oldpriv = rcu_dereference_protected(vq->private_data,
> > > > > +						    lockdep_is_held(&vq->mutex));
> > > > > +		rcu_assign_pointer(vq->private_data, priv);
> > > > > +
> > > > > +		mutex_unlock(&vq->mutex);
> > > > > +
> > > > > +		if (oldpriv) {
> > > > > +			vhost_test_flush_vq(n, index);
> > > > > +		}
> > > > > +	}
> > > > > +
> > > > > +	mutex_unlock(&n->dev.mutex);
> > > > > +	return 0;
> > > > > +
> > > > > +err:
> > > > > +	mutex_unlock(&n->dev.mutex);
> > > > > +	return r;
> > > > > +}
> > > > > +
> > > > > +static long vhost_test_reset_owner(struct vhost_test *n)
> > > > > +{
> > > > > +	void *priv = NULL;
> > > > > +	long err;
> > > > > +	mutex_lock(&n->dev.mutex);
> > > > > +	err = vhost_dev_check_owner(&n->dev);
> > > > > +	if (err)
> > > > > +		goto done;
> > > > > +	vhost_test_stop(n, &priv);
> > > > > +	vhost_test_flush(n);
> > > > > +	err = vhost_dev_reset_owner(&n->dev);
> > > > > +done:
> > > > > +	mutex_unlock(&n->dev.mutex);
> > > > > +	return err;
> > > > > +}
> > > > > +
> > > > > +static int vhost_test_set_features(struct vhost_test *n, u64 features)
> > > > > +{
> > > > > +	mutex_lock(&n->dev.mutex);
> > > > > +	if ((features & (1 << VHOST_F_LOG_ALL)) &&
> > > > > +	    !vhost_log_access_ok(&n->dev)) {
> > > > > +		mutex_unlock(&n->dev.mutex);
> > > > > +		return -EFAULT;
> > > > > +	}
> > > > > +	n->dev.acked_features = features;
> > > > > +	smp_wmb();
> > > > > +	vhost_test_flush(n);
> > > > > +	mutex_unlock(&n->dev.mutex);
> > > > > +	return 0;
> > > > > +}
> > > > > +
> > > > > +static long vhost_test_ioctl(struct file *f, unsigned int ioctl,
> > > > > +			     unsigned long arg)
> > > > > +{
> > > > > +	struct vhost_test *n = f->private_data;
> > > > > +	void __user *argp = (void __user *)arg;
> > > > > +	u64 __user *featurep = argp;
> > > > > +	int test;
> > > > > +	u64 features;
> > > > > +	int r;
> > > > > +	switch (ioctl) {
> > > > > +	case VHOST_TEST_RUN:
> > > > > +		if (copy_from_user(&test, argp, sizeof test))
> > > > > +			return -EFAULT;
> > > > > +		return vhost_test_run(n, test);
> > > > > +	case VHOST_GET_FEATURES:
> > > > > +		features = VHOST_FEATURES;
> > > > > +		if (copy_to_user(featurep, &features, sizeof features))
> > > > > +			return -EFAULT;
> > > > > +		return 0;
> > > > > +	case VHOST_SET_FEATURES:
> > > > > +		if (copy_from_user(&features, featurep, sizeof features))
> > > > > +			return -EFAULT;
> > > > > +		if (features & ~VHOST_FEATURES)
> > > > > +			return -EOPNOTSUPP;
> > > > > +		return vhost_test_set_features(n, features);
> > > > > +	case VHOST_RESET_OWNER:
> > > > > +		return vhost_test_reset_owner(n);
> > > > > +	default:
> > > > > +		mutex_lock(&n->dev.mutex);
> > > > > +		r = vhost_dev_ioctl(&n->dev, ioctl, arg);
> > > > > +		vhost_test_flush(n);
> > > > > +		mutex_unlock(&n->dev.mutex);
> > > > > +		return r;
> > > > > +	}
> > > > > +}
> > > > > +
> > > > > +#ifdef CONFIG_COMPAT
> > > > > +static long vhost_test_compat_ioctl(struct file *f, unsigned int ioctl,
> > > > > +				   unsigned long arg)
> > > > > +{
> > > > > +	return vhost_test_ioctl(f, ioctl, (unsigned long)compat_ptr(arg));
> > > > > +}
> > > > > +#endif
> > > > > +
> > > > > +static const struct file_operations vhost_test_fops = {
> > > > > +	.owner          = THIS_MODULE,
> > > > > +	.release        = vhost_test_release,
> > > > > +	.unlocked_ioctl = vhost_test_ioctl,
> > > > > +#ifdef CONFIG_COMPAT
> > > > > +	.compat_ioctl   = vhost_test_compat_ioctl,
> > > > > +#endif
> > > > > +	.open           = vhost_test_open,
> > > > > +	.llseek		= noop_llseek,
> > > > > +};
> > > > > +
> > > > > +static struct miscdevice vhost_test_misc = {
> > > > > +	MISC_DYNAMIC_MINOR,
> > > > > +	"vhost-test",
> > > > > +	&vhost_test_fops,
> > > > > +};
> > > > > +
> > > > > +static int vhost_test_init(void)
> > > > > +{
> > > > > +	return misc_register(&vhost_test_misc);
> > > > > +}
> > > > > +module_init(vhost_test_init);
> > > > > +
> > > > > +static void vhost_test_exit(void)
> > > > > +{
> > > > > +	misc_deregister(&vhost_test_misc);
> > > > > +}
> > > > > +module_exit(vhost_test_exit);
> > > > > +
> > > > > +MODULE_VERSION("0.0.1");
> > > > > +MODULE_LICENSE("GPL v2");
> > > > > +MODULE_AUTHOR("Michael S. Tsirkin");
> > > > > +MODULE_DESCRIPTION("Host kernel side for virtio simulator");
> > > > > diff --git a/drivers/vhost/test.h b/drivers/vhost/test.h
> > > > > new file mode 100644
> > > > > index 0000000..1fef5df
> > > > > --- /dev/null
> > > > > +++ b/drivers/vhost/test.h
> > > > > @@ -0,0 +1,7 @@
> > > > > +#ifndef LINUX_VHOST_TEST_H
> > > > > +#define LINUX_VHOST_TEST_H
> > > > > +
> > > > > +/* Start a given test on the virtio null device. 0 stops all tests. */
> > > > > +#define VHOST_TEST_RUN _IOW(VHOST_VIRTIO, 0x31, int)
> > > > > +
> > > > > +#endif
> > > > > diff --git a/tools/virtio/vhost_test/Makefile b/tools/virtio/vhost_test/Makefile
> > > > > new file mode 100644
> > > > > index 0000000..a1d35b8
> > > > > --- /dev/null
> > > > > +++ b/tools/virtio/vhost_test/Makefile
> > > > > @@ -0,0 +1,2 @@
> > > > > +obj-m += vhost_test.o
> > > > > +EXTRA_CFLAGS += -Idrivers/vhost
> > > > > diff --git a/tools/virtio/vhost_test/vhost_test.c b/tools/virtio/vhost_test/vhost_test.c
> > > > > new file mode 100644
> > > > > index 0000000..1873518
> > > > > --- /dev/null
> > > > > +++ b/tools/virtio/vhost_test/vhost_test.c
> > > > > @@ -0,0 +1 @@
> > > > > +#include "test.c"
> > > > > --
> > > > > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > > > > the body of a message to majordomo@vger.kernel.org
> > > > > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > > > > Please read the FAQ at  http://www.tux.org/lkml/
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> > > the body of a message to majordomo@vger.kernel.org
> > > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> > > Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* Re: [PATCH 1/2] vhost test module
From: Michael S. Tsirkin @ 2010-12-02 23:18 UTC (permalink / raw)
  To: Paul E. McKenney; +Cc: linux-kernel, kvm, virtualization
In-Reply-To: <20101202231303.GS2085@linux.vnet.ibm.com>

On Thu, Dec 02, 2010 at 03:13:03PM -0800, Paul E. McKenney wrote:
> On Thu, Dec 02, 2010 at 09:47:09PM +0200, Michael S. Tsirkin wrote:
> > On Thu, Dec 02, 2010 at 11:26:16AM -0800, Paul E. McKenney wrote:
> > > On Thu, Dec 02, 2010 at 09:11:30PM +0200, Michael S. Tsirkin wrote:
> > > > On Thu, Dec 02, 2010 at 11:00:37AM -0800, Paul E. McKenney wrote:
> > > > > On Mon, Nov 29, 2010 at 07:09:01PM +0200, Michael S. Tsirkin wrote:
> > > > > > This adds a test module for vhost infrastructure.
> > > > > > Intentionally not tied to kbuild to prevent people
> > > > > > from installing and loading it accidentally.
> > > > > > 
> > > > > > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > > > > 
> > > > > On question below.
> > > > > 
> > > > > > ---
> > > > > > 
> > > > > > diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
> > > > > > new file mode 100644
> > > > > > index 0000000..099f302
> > > > > > --- /dev/null
> > > > > > +++ b/drivers/vhost/test.c
> > > > > > @@ -0,0 +1,320 @@
> > > > > > +/* Copyright (C) 2009 Red Hat, Inc.
> > > > > > + * Author: Michael S. Tsirkin <mst@redhat.com>
> > > > > > + *
> > > > > > + * This work is licensed under the terms of the GNU GPL, version 2.
> > > > > > + *
> > > > > > + * test virtio server in host kernel.
> > > > > > + */
> > > > > > +
> > > > > > +#include <linux/compat.h>
> > > > > > +#include <linux/eventfd.h>
> > > > > > +#include <linux/vhost.h>
> > > > > > +#include <linux/miscdevice.h>
> > > > > > +#include <linux/module.h>
> > > > > > +#include <linux/mutex.h>
> > > > > > +#include <linux/workqueue.h>
> > > > > > +#include <linux/rcupdate.h>
> > > > > > +#include <linux/file.h>
> > > > > > +#include <linux/slab.h>
> > > > > > +
> > > > > > +#include "test.h"
> > > > > > +#include "vhost.c"
> > > > > > +
> > > > > > +/* Max number of bytes transferred before requeueing the job.
> > > > > > + * Using this limit prevents one virtqueue from starving others. */
> > > > > > +#define VHOST_TEST_WEIGHT 0x80000
> > > > > > +
> > > > > > +enum {
> > > > > > +	VHOST_TEST_VQ = 0,
> > > > > > +	VHOST_TEST_VQ_MAX = 1,
> > > > > > +};
> > > > > > +
> > > > > > +struct vhost_test {
> > > > > > +	struct vhost_dev dev;
> > > > > > +	struct vhost_virtqueue vqs[VHOST_TEST_VQ_MAX];
> > > > > > +};
> > > > > > +
> > > > > > +/* Expects to be always run from workqueue - which acts as
> > > > > > + * read-size critical section for our kind of RCU. */
> > > > > > +static void handle_vq(struct vhost_test *n)
> > > > > > +{
> > > > > > +	struct vhost_virtqueue *vq = &n->dev.vqs[VHOST_TEST_VQ];
> > > > > > +	unsigned out, in;
> > > > > > +	int head;
> > > > > > +	size_t len, total_len = 0;
> > > > > > +	void *private;
> > > > > > +
> > > > > > +	private = rcu_dereference_check(vq->private_data, 1);
> > > > > 
> > > > > Any chance of a check for running in a workqueue?  If I remember correctly,
> > > > > the ->lockdep_map field in the work_struct structure allows you to create
> > > > > the required lockdep expression.
> > > > 
> > > > We moved away from using the workqueue to a custom kernel thread
> > > > implementation though.
> > > 
> > > OK, then could you please add a check for "current == custom_kernel_thread"
> > > or some such?
> > > 
> > > 							Thanx, Paul
> > 
> > It's a bit tricky. The way we flush out things is by an analog of
> > flush_work. So just checking that we run from workqueue isn't
> > right need to check that we are running from one of the specific work
> > structures that we are careful to flush.
> > 
> > I can do this by passing the work structure pointer on to relevant
> > functions but I think this will add (very minor) overhead even when rcu
> > checks are disabled. Does it matter? Thoughts?
> 
> Would it be possible to set up separate lockdep maps, in effect passing
> the needed information via lockdep rather than via the function arguments?
> 
> 							Thanx, Paul

Possibly, I don't know enough about this but will check.
Any examples to look at?

-- 
mST

^ permalink raw reply

* Re: [PATCH 1/2] vhost test module
From: Paul E. McKenney @ 2010-12-02 23:56 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: linux-kernel, kvm, virtualization
In-Reply-To: <20101202231818.GA12362@redhat.com>

On Fri, Dec 03, 2010 at 01:18:18AM +0200, Michael S. Tsirkin wrote:
> On Thu, Dec 02, 2010 at 03:13:03PM -0800, Paul E. McKenney wrote:
> > On Thu, Dec 02, 2010 at 09:47:09PM +0200, Michael S. Tsirkin wrote:
> > > On Thu, Dec 02, 2010 at 11:26:16AM -0800, Paul E. McKenney wrote:
> > > > On Thu, Dec 02, 2010 at 09:11:30PM +0200, Michael S. Tsirkin wrote:
> > > > > On Thu, Dec 02, 2010 at 11:00:37AM -0800, Paul E. McKenney wrote:
> > > > > > On Mon, Nov 29, 2010 at 07:09:01PM +0200, Michael S. Tsirkin wrote:
> > > > > > > This adds a test module for vhost infrastructure.
> > > > > > > Intentionally not tied to kbuild to prevent people
> > > > > > > from installing and loading it accidentally.
> > > > > > > 
> > > > > > > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > > > > > 
> > > > > > On question below.
> > > > > > 
> > > > > > > ---
> > > > > > > 
> > > > > > > diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
> > > > > > > new file mode 100644
> > > > > > > index 0000000..099f302
> > > > > > > --- /dev/null
> > > > > > > +++ b/drivers/vhost/test.c
> > > > > > > @@ -0,0 +1,320 @@
> > > > > > > +/* Copyright (C) 2009 Red Hat, Inc.
> > > > > > > + * Author: Michael S. Tsirkin <mst@redhat.com>
> > > > > > > + *
> > > > > > > + * This work is licensed under the terms of the GNU GPL, version 2.
> > > > > > > + *
> > > > > > > + * test virtio server in host kernel.
> > > > > > > + */
> > > > > > > +
> > > > > > > +#include <linux/compat.h>
> > > > > > > +#include <linux/eventfd.h>
> > > > > > > +#include <linux/vhost.h>
> > > > > > > +#include <linux/miscdevice.h>
> > > > > > > +#include <linux/module.h>
> > > > > > > +#include <linux/mutex.h>
> > > > > > > +#include <linux/workqueue.h>
> > > > > > > +#include <linux/rcupdate.h>
> > > > > > > +#include <linux/file.h>
> > > > > > > +#include <linux/slab.h>
> > > > > > > +
> > > > > > > +#include "test.h"
> > > > > > > +#include "vhost.c"
> > > > > > > +
> > > > > > > +/* Max number of bytes transferred before requeueing the job.
> > > > > > > + * Using this limit prevents one virtqueue from starving others. */
> > > > > > > +#define VHOST_TEST_WEIGHT 0x80000
> > > > > > > +
> > > > > > > +enum {
> > > > > > > +	VHOST_TEST_VQ = 0,
> > > > > > > +	VHOST_TEST_VQ_MAX = 1,
> > > > > > > +};
> > > > > > > +
> > > > > > > +struct vhost_test {
> > > > > > > +	struct vhost_dev dev;
> > > > > > > +	struct vhost_virtqueue vqs[VHOST_TEST_VQ_MAX];
> > > > > > > +};
> > > > > > > +
> > > > > > > +/* Expects to be always run from workqueue - which acts as
> > > > > > > + * read-size critical section for our kind of RCU. */
> > > > > > > +static void handle_vq(struct vhost_test *n)
> > > > > > > +{
> > > > > > > +	struct vhost_virtqueue *vq = &n->dev.vqs[VHOST_TEST_VQ];
> > > > > > > +	unsigned out, in;
> > > > > > > +	int head;
> > > > > > > +	size_t len, total_len = 0;
> > > > > > > +	void *private;
> > > > > > > +
> > > > > > > +	private = rcu_dereference_check(vq->private_data, 1);
> > > > > > 
> > > > > > Any chance of a check for running in a workqueue?  If I remember correctly,
> > > > > > the ->lockdep_map field in the work_struct structure allows you to create
> > > > > > the required lockdep expression.
> > > > > 
> > > > > We moved away from using the workqueue to a custom kernel thread
> > > > > implementation though.
> > > > 
> > > > OK, then could you please add a check for "current == custom_kernel_thread"
> > > > or some such?
> > > > 
> > > > 							Thanx, Paul
> > > 
> > > It's a bit tricky. The way we flush out things is by an analog of
> > > flush_work. So just checking that we run from workqueue isn't
> > > right need to check that we are running from one of the specific work
> > > structures that we are careful to flush.
> > > 
> > > I can do this by passing the work structure pointer on to relevant
> > > functions but I think this will add (very minor) overhead even when rcu
> > > checks are disabled. Does it matter? Thoughts?
> > 
> > Would it be possible to set up separate lockdep maps, in effect passing
> > the needed information via lockdep rather than via the function arguments?
> 
> Possibly, I don't know enough about this but will check.
> Any examples to look at?

I would suggest the workqueue example in include/linux/workqueue.h and
kernel/workqueue.c.  You will need a struct lockdep_map for each of the
specific work structures, sort of like the one in struct workqueue_struct.

You can then use lock_map_acquire() and lock_map_release() to flag the
fact that your kernel thread is running and not, and then you can pass
lock_is_held() to rcu_dereference_check().  Each of lock_map_acquire(),
lock_map_release(), and lock_is_held() takes a struct lockdep_map as
sole argument.  The rcu_lock_map definition shows an example of a global
lockdep_map variable.  If you need to do runtime initialization of your
lockdep_map structure, you can use lockdep_init_map().

Seem reasonable?

							Thanx, Paul

^ permalink raw reply

* Re: [PATCH 1/2] vhost test module
From: Paul E. McKenney @ 2010-12-04 18:03 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: linux-kernel, kvm, virtualization
In-Reply-To: <20101202235656.GT2085@linux.vnet.ibm.com>

On Thu, Dec 02, 2010 at 03:56:56PM -0800, Paul E. McKenney wrote:
> On Fri, Dec 03, 2010 at 01:18:18AM +0200, Michael S. Tsirkin wrote:
> > On Thu, Dec 02, 2010 at 03:13:03PM -0800, Paul E. McKenney wrote:
> > > On Thu, Dec 02, 2010 at 09:47:09PM +0200, Michael S. Tsirkin wrote:
> > > > On Thu, Dec 02, 2010 at 11:26:16AM -0800, Paul E. McKenney wrote:
> > > > > On Thu, Dec 02, 2010 at 09:11:30PM +0200, Michael S. Tsirkin wrote:
> > > > > > On Thu, Dec 02, 2010 at 11:00:37AM -0800, Paul E. McKenney wrote:
> > > > > > > On Mon, Nov 29, 2010 at 07:09:01PM +0200, Michael S. Tsirkin wrote:
> > > > > > > > This adds a test module for vhost infrastructure.
> > > > > > > > Intentionally not tied to kbuild to prevent people
> > > > > > > > from installing and loading it accidentally.
> > > > > > > > 
> > > > > > > > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> > > > > > > 
> > > > > > > On question below.
> > > > > > > 
> > > > > > > > ---
> > > > > > > > 
> > > > > > > > diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
> > > > > > > > new file mode 100644
> > > > > > > > index 0000000..099f302
> > > > > > > > --- /dev/null
> > > > > > > > +++ b/drivers/vhost/test.c
> > > > > > > > @@ -0,0 +1,320 @@
> > > > > > > > +/* Copyright (C) 2009 Red Hat, Inc.
> > > > > > > > + * Author: Michael S. Tsirkin <mst@redhat.com>
> > > > > > > > + *
> > > > > > > > + * This work is licensed under the terms of the GNU GPL, version 2.
> > > > > > > > + *
> > > > > > > > + * test virtio server in host kernel.
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +#include <linux/compat.h>
> > > > > > > > +#include <linux/eventfd.h>
> > > > > > > > +#include <linux/vhost.h>
> > > > > > > > +#include <linux/miscdevice.h>
> > > > > > > > +#include <linux/module.h>
> > > > > > > > +#include <linux/mutex.h>
> > > > > > > > +#include <linux/workqueue.h>
> > > > > > > > +#include <linux/rcupdate.h>
> > > > > > > > +#include <linux/file.h>
> > > > > > > > +#include <linux/slab.h>
> > > > > > > > +
> > > > > > > > +#include "test.h"
> > > > > > > > +#include "vhost.c"
> > > > > > > > +
> > > > > > > > +/* Max number of bytes transferred before requeueing the job.
> > > > > > > > + * Using this limit prevents one virtqueue from starving others. */
> > > > > > > > +#define VHOST_TEST_WEIGHT 0x80000
> > > > > > > > +
> > > > > > > > +enum {
> > > > > > > > +	VHOST_TEST_VQ = 0,
> > > > > > > > +	VHOST_TEST_VQ_MAX = 1,
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +struct vhost_test {
> > > > > > > > +	struct vhost_dev dev;
> > > > > > > > +	struct vhost_virtqueue vqs[VHOST_TEST_VQ_MAX];
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +/* Expects to be always run from workqueue - which acts as
> > > > > > > > + * read-size critical section for our kind of RCU. */
> > > > > > > > +static void handle_vq(struct vhost_test *n)
> > > > > > > > +{
> > > > > > > > +	struct vhost_virtqueue *vq = &n->dev.vqs[VHOST_TEST_VQ];
> > > > > > > > +	unsigned out, in;
> > > > > > > > +	int head;
> > > > > > > > +	size_t len, total_len = 0;
> > > > > > > > +	void *private;
> > > > > > > > +
> > > > > > > > +	private = rcu_dereference_check(vq->private_data, 1);
> > > > > > > 
> > > > > > > Any chance of a check for running in a workqueue?  If I remember correctly,
> > > > > > > the ->lockdep_map field in the work_struct structure allows you to create
> > > > > > > the required lockdep expression.
> > > > > > 
> > > > > > We moved away from using the workqueue to a custom kernel thread
> > > > > > implementation though.
> > > > > 
> > > > > OK, then could you please add a check for "current == custom_kernel_thread"
> > > > > or some such?
> > > > > 
> > > > > 							Thanx, Paul
> > > > 
> > > > It's a bit tricky. The way we flush out things is by an analog of
> > > > flush_work. So just checking that we run from workqueue isn't
> > > > right need to check that we are running from one of the specific work
> > > > structures that we are careful to flush.
> > > > 
> > > > I can do this by passing the work structure pointer on to relevant
> > > > functions but I think this will add (very minor) overhead even when rcu
> > > > checks are disabled. Does it matter? Thoughts?
> > > 
> > > Would it be possible to set up separate lockdep maps, in effect passing
> > > the needed information via lockdep rather than via the function arguments?
> > 
> > Possibly, I don't know enough about this but will check.
> > Any examples to look at?
> 
> I would suggest the workqueue example in include/linux/workqueue.h and
> kernel/workqueue.c.  You will need a struct lockdep_map for each of the
> specific work structures, sort of like the one in struct workqueue_struct.
> 
> You can then use lock_map_acquire() and lock_map_release() to flag the
> fact that your kernel thread is running and not, and then you can pass
> lock_is_held() to rcu_dereference_check().  Each of lock_map_acquire(),
> lock_map_release(), and lock_is_held() takes a struct lockdep_map as
> sole argument.  The rcu_lock_map definition shows an example of a global
> lockdep_map variable.  If you need to do runtime initialization of your
> lockdep_map structure, you can use lockdep_init_map().
> 
> Seem reasonable?

PS to previous...

Suppose that there are many work structures, and several of them use
this same function, but the function has no indication of which one it
is working on.  Then one reasonable approach is to share a lockdep_map
structure among them.  Although this does not allow you to validate
one-to-one from structure to function invocation, it -does- allow the
code to defend itself against an incorrect direct call into the from
some inappropriate context.

							Thanx, Paul

^ permalink raw reply

* Re: [PATCH 2/2] tools/virtio: virtio_test tool
From: Rusty Russell @ 2010-12-06  4:53 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: linux-kernel, kvm, virtualization
In-Reply-To: <20101129171637.GC4027@redhat.com>

On Tue, 30 Nov 2010 03:46:37 am Michael S. Tsirkin wrote:
> This is the userspace part of the tool: it includes a bunch of stubs for
> linux APIs, somewhat simular to linuxsched. This makes it possible to
> recompile the ring code in userspace.
> 
> A small test example is implemented combining this with vhost_test
> module.
> 
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

Hi Michael,

  I'm not sure what the point is of this work?  You'll still need to
benchmark on real systems, but it's not low-level enough to measure
things like cache misses.

I'm assuming you're thinking of playing with layout to measure cache
behaviour.  I was thinking of a complete userspace implementation where
either it was run under cachegrind, or each access was wrapped to allow
tracking of cachelines to give an exact measure of cache movement under
various scenarios (esp. ring mostly empty, ring in steady state, ring
mostly full).

Cheers,
Rusty.

^ permalink raw reply

* Re: [PATCH 2/2] tools/virtio: virtio_test tool
From: Thiago Farina @ 2010-12-06 16:37 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: linux-kernel, kvm, virtualization
In-Reply-To: <20101129171637.GC4027@redhat.com>

On Mon, Nov 29, 2010 at 3:16 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> +#define container_of(ptr, type, member) ({                     \
> +       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
> +       (type *)( (char *)__mptr - offsetof(type,member) );})
> +
> +#define uninitialized_var(x) x = x
> +
> +# ifndef likely
> +#  define likely(x)    (__builtin_expect(!!(x), 1))
> +# endif
> +# ifndef unlikely
> +#  define unlikely(x)  (__builtin_expect(!!(x), 0))
> +# endif

It seems you are not using these macros. Do you really need them here?
Can't you include the right linux header files for these macros
instead?
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/virtualization

^ permalink raw reply

* [PATCH 1/8] staging: hv: Convert camel case struct fields in vstorage.h to lowercase
From: Hank Janssen @ 2010-12-06 20:26 UTC (permalink / raw)
  To: hjanssen, gregkh, linux-kernel, devel, virtualization
  Cc: Haiyang Zhang, Abhishek Kane

From: Hank Janssen <hjanssen@microsoft.com>

Convert camel case struct fields in vstorage.h to lowercase

Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>

---
 drivers/staging/hv/storvsc.c  |  133 +++++++++++++++++++++--------------------
 drivers/staging/hv/vstorage.h |  106 ++++++++++++++++----------------
 2 files changed, 120 insertions(+), 119 deletions(-)

diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index 525c8ee..96b4ed9 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -204,8 +204,8 @@ static int StorVscChannelInit(struct hv_device *Device)
 		goto nomem;
 	}
 
-	vstorPacket->Operation = VStorOperationBeginInitialization;
-	vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
+	vstorPacket->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION;
+	vstorPacket->flags = REQUEST_COMPLETION_FLAG;
 
 	/*SpinlockAcquire(gDriverExt.packetListLock);
 	INSERT_TAIL_LIST(&gDriverExt.packetList, &packet->listEntry.entry);
@@ -226,11 +226,11 @@ static int StorVscChannelInit(struct hv_device *Device)
 
 	osd_waitevent_wait(request->WaitEvent);
 
-	if (vstorPacket->Operation != VStorOperationCompleteIo ||
-	    vstorPacket->Status != 0) {
+	if (vstorPacket->operation != VSTOR_OPERATION_COMPLETE_IO ||
+	    vstorPacket->status != 0) {
 		DPRINT_ERR(STORVSC, "BEGIN_INITIALIZATION_OPERATION failed "
 			   "(op %d status 0x%x)",
-			   vstorPacket->Operation, vstorPacket->Status);
+			   vstorPacket->operation, vstorPacket->status);
 		goto Cleanup;
 	}
 
@@ -238,11 +238,11 @@ static int StorVscChannelInit(struct hv_device *Device)
 
 	/* reuse the packet for version range supported */
 	memset(vstorPacket, 0, sizeof(struct vstor_packet));
-	vstorPacket->Operation = VStorOperationQueryProtocolVersion;
-	vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
+	vstorPacket->operation = VSTOR_OPERATION_QUERY_PROTOCOL_VERSION;
+	vstorPacket->flags = REQUEST_COMPLETION_FLAG;
 
-	vstorPacket->Version.MajorMinor = VMSTOR_PROTOCOL_VERSION_CURRENT;
-	FILL_VMSTOR_REVISION(vstorPacket->Version.Revision);
+	vstorPacket->version.major_minor = VMSTOR_PROTOCOL_VERSION_CURRENT;
+	FILL_VMSTOR_REVISION(vstorPacket->version.revision);
 
 	ret = vmbus_sendpacket(Device->channel, vstorPacket,
 			       sizeof(struct vstor_packet),
@@ -258,11 +258,11 @@ static int StorVscChannelInit(struct hv_device *Device)
 	osd_waitevent_wait(request->WaitEvent);
 
 	/* TODO: Check returned version */
-	if (vstorPacket->Operation != VStorOperationCompleteIo ||
-	    vstorPacket->Status != 0) {
+	if (vstorPacket->operation != VSTOR_OPERATION_COMPLETE_IO ||
+	    vstorPacket->status != 0) {
 		DPRINT_ERR(STORVSC, "QUERY_PROTOCOL_VERSION_OPERATION failed "
 			   "(op %d status 0x%x)",
-			   vstorPacket->Operation, vstorPacket->Status);
+			   vstorPacket->operation, vstorPacket->status);
 		goto Cleanup;
 	}
 
@@ -270,9 +270,9 @@ static int StorVscChannelInit(struct hv_device *Device)
 	DPRINT_INFO(STORVSC, "QUERY_PROPERTIES_OPERATION...");
 
 	memset(vstorPacket, 0, sizeof(struct vstor_packet));
-	vstorPacket->Operation = VStorOperationQueryProperties;
-	vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
-	vstorPacket->StorageChannelProperties.PortNumber =
+	vstorPacket->operation = VSTOR_OPERATION_QUERY_PROPERTIES;
+	vstorPacket->flags = REQUEST_COMPLETION_FLAG;
+	vstorPacket->storage_channel_properties.port_number =
 					storDevice->PortNumber;
 
 	ret = vmbus_sendpacket(Device->channel, vstorPacket,
@@ -290,26 +290,27 @@ static int StorVscChannelInit(struct hv_device *Device)
 	osd_waitevent_wait(request->WaitEvent);
 
 	/* TODO: Check returned version */
-	if (vstorPacket->Operation != VStorOperationCompleteIo ||
-	    vstorPacket->Status != 0) {
+	if (vstorPacket->operation != VSTOR_OPERATION_COMPLETE_IO ||
+	    vstorPacket->status != 0) {
 		DPRINT_ERR(STORVSC, "QUERY_PROPERTIES_OPERATION failed "
 			   "(op %d status 0x%x)",
-			   vstorPacket->Operation, vstorPacket->Status);
+			   vstorPacket->operation, vstorPacket->status);
 		goto Cleanup;
 	}
 
-	storDevice->PathId = vstorPacket->StorageChannelProperties.PathId;
-	storDevice->TargetId = vstorPacket->StorageChannelProperties.TargetId;
+	storDevice->PathId = vstorPacket->storage_channel_properties.path_id;
+	storDevice->TargetId
+		= vstorPacket->storage_channel_properties.target_id;
 
 	DPRINT_DBG(STORVSC, "channel flag 0x%x, max xfer len 0x%x",
-		   vstorPacket->StorageChannelProperties.Flags,
-		   vstorPacket->StorageChannelProperties.MaxTransferBytes);
+		   vstorPacket->storage_channel_properties.flags,
+		   vstorPacket->storage_channel_properties.max_transfer_bytes);
 
 	DPRINT_INFO(STORVSC, "END_INITIALIZATION_OPERATION...");
 
 	memset(vstorPacket, 0, sizeof(struct vstor_packet));
-	vstorPacket->Operation = VStorOperationEndInitialization;
-	vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
+	vstorPacket->operation = VSTOR_OPERATION_END_INITIALIZATION;
+	vstorPacket->flags = REQUEST_COMPLETION_FLAG;
 
 	ret = vmbus_sendpacket(Device->channel, vstorPacket,
 			       sizeof(struct vstor_packet),
@@ -325,11 +326,11 @@ static int StorVscChannelInit(struct hv_device *Device)
 
 	osd_waitevent_wait(request->WaitEvent);
 
-	if (vstorPacket->Operation != VStorOperationCompleteIo ||
-	    vstorPacket->Status != 0) {
+	if (vstorPacket->operation != VSTOR_OPERATION_COMPLETE_IO ||
+	    vstorPacket->status != 0) {
 		DPRINT_ERR(STORVSC, "END_INITIALIZATION_OPERATION failed "
 			   "(op %d status 0x%x)",
-			   vstorPacket->Operation, vstorPacket->Status);
+			   vstorPacket->operation, vstorPacket->status);
 		goto Cleanup;
 	}
 
@@ -359,7 +360,7 @@ static void StorVscOnIOCompletion(struct hv_device *Device,
 
 	DPRINT_DBG(STORVSC, "IO_COMPLETE_OPERATION - request extension %p "
 		   "completed bytes xfer %u", RequestExt,
-		   VStorPacket->VmSrb.DataTransferLength);
+		   VStorPacket->vm_srb.data_transfer_length);
 
 	/* ASSERT(RequestExt != NULL); */
 	/* ASSERT(RequestExt->Request != NULL); */
@@ -369,36 +370,36 @@ static void StorVscOnIOCompletion(struct hv_device *Device,
 	/* ASSERT(request->OnIOCompletion != NULL); */
 
 	/* Copy over the status...etc */
-	request->Status = VStorPacket->VmSrb.ScsiStatus;
+	request->Status = VStorPacket->vm_srb.scsi_status;
 
-	if (request->Status != 0 || VStorPacket->VmSrb.SrbStatus != 1) {
+	if (request->Status != 0 || VStorPacket->vm_srb.srb_status != 1) {
 		DPRINT_WARN(STORVSC,
 			    "cmd 0x%x scsi status 0x%x srb status 0x%x\n",
-			    request->Cdb[0], VStorPacket->VmSrb.ScsiStatus,
-			    VStorPacket->VmSrb.SrbStatus);
+			    request->Cdb[0], VStorPacket->vm_srb.scsi_status,
+			    VStorPacket->vm_srb.srb_status);
 	}
 
 	if ((request->Status & 0xFF) == 0x02) {
 		/* CHECK_CONDITION */
-		if (VStorPacket->VmSrb.SrbStatus & 0x80) {
+		if (VStorPacket->vm_srb.srb_status & 0x80) {
 			/* autosense data available */
 			DPRINT_WARN(STORVSC, "storvsc pkt %p autosense data "
 				    "valid - len %d\n", RequestExt,
-				    VStorPacket->VmSrb.SenseInfoLength);
+				    VStorPacket->vm_srb.sense_info_length);
 
-			/* ASSERT(VStorPacket->VmSrb.SenseInfoLength <= */
+			/* ASSERT(VStorPacket->vm_srb.sense_info_length <= */
 			/* 	request->SenseBufferSize); */
 			memcpy(request->SenseBuffer,
-			       VStorPacket->VmSrb.SenseData,
-			       VStorPacket->VmSrb.SenseInfoLength);
+			       VStorPacket->vm_srb.sense_data,
+			       VStorPacket->vm_srb.sense_info_length);
 
 			request->SenseBufferSize =
-					VStorPacket->VmSrb.SenseInfoLength;
+					VStorPacket->vm_srb.sense_info_length;
 		}
 	}
 
 	/* TODO: */
-	request->BytesXfer = VStorPacket->VmSrb.DataTransferLength;
+	request->BytesXfer = VStorPacket->vm_srb.data_transfer_length;
 
 	request->OnIOCompletion(request);
 
@@ -411,19 +412,19 @@ static void StorVscOnReceive(struct hv_device *Device,
 			     struct vstor_packet *VStorPacket,
 			     struct storvsc_request_extension *RequestExt)
 {
-	switch (VStorPacket->Operation) {
-	case VStorOperationCompleteIo:
+	switch (VStorPacket->operation) {
+	case VSTOR_OPERATION_COMPLETE_IO:
 		DPRINT_DBG(STORVSC, "IO_COMPLETE_OPERATION");
 		StorVscOnIOCompletion(Device, VStorPacket, RequestExt);
 		break;
-	case VStorOperationRemoveDevice:
+	case VSTOR_OPERATION_REMOVE_DEVICE:
 		DPRINT_INFO(STORVSC, "REMOVE_DEVICE_OPERATION");
 		/* TODO: */
 		break;
 
 	default:
 		DPRINT_INFO(STORVSC, "Unknown operation received - %d",
-			    VStorPacket->Operation);
+			    VStorPacket->operation);
 		break;
 	}
 }
@@ -506,7 +507,7 @@ static int StorVscConnectToVsp(struct hv_device *Device)
 			 StorVscOnChannelCallback, Device);
 
 	DPRINT_DBG(STORVSC, "storage props: path id %d, tgt id %d, max xfer %d",
-		   props.PathId, props.TargetId, props.MaxTransferBytes);
+		   props.path_id, props.target_id, props.max_transfer_bytes);
 
 	if (ret != 0) {
 		DPRINT_ERR(STORVSC, "unable to open channel: %d", ret);
@@ -628,9 +629,9 @@ int StorVscOnHostReset(struct hv_device *Device)
 		goto Cleanup;
 	}
 
-	vstorPacket->Operation = VStorOperationResetBus;
-	vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
-	vstorPacket->VmSrb.PathId = storDevice->PathId;
+	vstorPacket->operation = VSTOR_OPERATION_RESET_BUS;
+	vstorPacket->flags = REQUEST_COMPLETION_FLAG;
+	vstorPacket->vm_srb.path_id = storDevice->PathId;
 
 	ret = vmbus_sendpacket(Device->channel, vstorPacket,
 			       sizeof(struct vstor_packet),
@@ -697,35 +698,35 @@ static int StorVscOnIORequest(struct hv_device *Device,
 
 	memset(vstorPacket, 0 , sizeof(struct vstor_packet));
 
-	vstorPacket->Flags |= REQUEST_COMPLETION_FLAG;
+	vstorPacket->flags |= REQUEST_COMPLETION_FLAG;
 
-	vstorPacket->VmSrb.Length = sizeof(struct vmscsi_request);
+	vstorPacket->vm_srb.length = sizeof(struct vmscsi_request);
 
-	vstorPacket->VmSrb.PortNumber = Request->Host;
-	vstorPacket->VmSrb.PathId = Request->Bus;
-	vstorPacket->VmSrb.TargetId = Request->TargetId;
-	vstorPacket->VmSrb.Lun = Request->LunId;
+	vstorPacket->vm_srb.port_number = Request->Host;
+	vstorPacket->vm_srb.path_id = Request->Bus;
+	vstorPacket->vm_srb.target_id = Request->TargetId;
+	vstorPacket->vm_srb.lun = Request->LunId;
 
-	vstorPacket->VmSrb.SenseInfoLength = SENSE_BUFFER_SIZE;
+	vstorPacket->vm_srb.sense_info_length = SENSE_BUFFER_SIZE;
 
 	/* Copy over the scsi command descriptor block */
-	vstorPacket->VmSrb.CdbLength = Request->CdbLen;
-	memcpy(&vstorPacket->VmSrb.Cdb, Request->Cdb, Request->CdbLen);
+	vstorPacket->vm_srb.cdb_length = Request->CdbLen;
+	memcpy(&vstorPacket->vm_srb.cdb, Request->Cdb, Request->CdbLen);
 
-	vstorPacket->VmSrb.DataIn = Request->Type;
-	vstorPacket->VmSrb.DataTransferLength = Request->DataBuffer.Length;
+	vstorPacket->vm_srb.data_in = Request->Type;
+	vstorPacket->vm_srb.data_transfer_length = Request->DataBuffer.Length;
 
-	vstorPacket->Operation = VStorOperationExecuteSRB;
+	vstorPacket->operation = VSTOR_OPERATION_EXECUTE_SRB;
 
 	DPRINT_DBG(STORVSC, "srb - len %d port %d, path %d, target %d, "
 		   "lun %d senselen %d cdblen %d",
-		   vstorPacket->VmSrb.Length,
-		   vstorPacket->VmSrb.PortNumber,
-		   vstorPacket->VmSrb.PathId,
-		   vstorPacket->VmSrb.TargetId,
-		   vstorPacket->VmSrb.Lun,
-		   vstorPacket->VmSrb.SenseInfoLength,
-		   vstorPacket->VmSrb.CdbLength);
+		   vstorPacket->vm_srb.length,
+		   vstorPacket->vm_srb.port_number,
+		   vstorPacket->vm_srb.path_id,
+		   vstorPacket->vm_srb.target_id,
+		   vstorPacket->vm_srb.lun,
+		   vstorPacket->vm_srb.sense_info_length,
+		   vstorPacket->vm_srb.cdb_length);
 
 	if (requestExtension->Request->DataBuffer.Length) {
 		ret = vmbus_sendpacket_multipagebuffer(Device->channel,
diff --git a/drivers/staging/hv/vstorage.h b/drivers/staging/hv/vstorage.h
index 4ea597d..ae8be84 100644
--- a/drivers/staging/hv/vstorage.h
+++ b/drivers/staging/hv/vstorage.h
@@ -27,15 +27,17 @@
 
 #define REVISION_STRING(REVISION_) #REVISION_
 #define FILL_VMSTOR_REVISION(RESULT_LVALUE_)				\
-{									\
-	char *revisionString = REVISION_STRING($Revision : 6 $) + 11;	\
-	RESULT_LVALUE_ = 0;						\
-	while (*revisionString >= '0' && *revisionString <= '9') {	\
-		RESULT_LVALUE_ *= 10;					\
-		RESULT_LVALUE_ += *revisionString - '0';		\
-		revisionString++;					\
-	}								\
-}
+	do {								\
+		char *revision_string					\
+			= REVISION_STRING($Rev : 6 $) + 6;		\
+		RESULT_LVALUE_ = 0;					\
+		while (*revision_string >= '0'				\
+			&& *revision_string <= '9') {			\
+			RESULT_LVALUE_ *= 10;				\
+			RESULT_LVALUE_ += *revision_string - '0';	\
+			revision_string++;				\
+		}							\
+	} while (0)
 
 /* Major/minor macros.  Minor version is in LSB, meaning that earlier flat */
 /* version numbers will be interpreted as "0.x" (i.e., 1 becomes 0.1). */
@@ -65,17 +67,17 @@
 
 /*  Packet structure describing virtual storage requests. */
 enum vstor_packet_operation {
-	VStorOperationCompleteIo            = 1,
-	VStorOperationRemoveDevice          = 2,
-	VStorOperationExecuteSRB            = 3,
-	VStorOperationResetLun              = 4,
-	VStorOperationResetAdapter          = 5,
-	VStorOperationResetBus              = 6,
-	VStorOperationBeginInitialization   = 7,
-	VStorOperationEndInitialization     = 8,
-	VStorOperationQueryProtocolVersion  = 9,
-	VStorOperationQueryProperties       = 10,
-	VStorOperationMaximum               = 10
+	VSTOR_OPERATION_COMPLETE_IO		= 1,
+	VSTOR_OPERATION_REMOVE_DEVICE		= 2,
+	VSTOR_OPERATION_EXECUTE_SRB		= 3,
+	VSTOR_OPERATION_RESET_LUN		= 4,
+	VSTOR_OPERATION_RESET_ADAPTER		= 5,
+	VSTOR_OPERATION_RESET_BUS		= 6,
+	VSTOR_OPERATION_BEGIN_INITIALIZATION	= 7,
+	VSTOR_OPERATION_END_INITIALIZATION	= 8,
+	VSTOR_OPERATION_QUERY_PROTOCOL_VERSION	= 9,
+	VSTOR_OPERATION_QUERY_PROPERTIES	= 10,
+	VSTOR_OPERATION_MAXIMUM			= 10
 };
 
 /*
@@ -89,31 +91,29 @@ enum vstor_packet_operation {
 #define SENSE_BUFFER_SIZE			0x12
 #endif
 
-#define MAX_DATA_BUFFER_LENGTH_WITH_PADDING	0x14
+#define MAX_DATA_BUF_LEN_WITH_PADDING		0x14
 
 struct vmscsi_request {
-	unsigned short Length;
-	unsigned char SrbStatus;
-	unsigned char ScsiStatus;
+	unsigned short length;
+	unsigned char srb_status;
+	unsigned char scsi_status;
 
-	unsigned char PortNumber;
-	unsigned char PathId;
-	unsigned char TargetId;
-	unsigned char Lun;
+	unsigned char port_number;
+	unsigned char path_id;
+	unsigned char target_id;
+	unsigned char lun;
 
-	unsigned char CdbLength;
-	unsigned char SenseInfoLength;
-	unsigned char DataIn;
-	unsigned char Reserved;
+	unsigned char cdb_length;
+	unsigned char sense_info_length;
+	unsigned char data_in;
+	unsigned char reserved;
 
-	unsigned int DataTransferLength;
+	unsigned int data_transfer_length;
 
 	union {
-	unsigned char Cdb[CDB16GENERIC_LENGTH];
-
-	unsigned char SenseData[SENSE_BUFFER_SIZE];
-
-	unsigned char ReservedArray[MAX_DATA_BUFFER_LENGTH_WITH_PADDING];
+		unsigned char cdb[CDB16GENERIC_LENGTH];
+		unsigned char sense_data[SENSE_BUFFER_SIZE];
+		unsigned char reserved_array[MAX_DATA_BUF_LEN_WITH_PADDING];
 	};
 } __attribute((packed));
 
@@ -123,24 +123,24 @@ struct vmscsi_request {
  * properties of the channel.
  */
 struct vmstorage_channel_properties {
-	unsigned short ProtocolVersion;
-	unsigned char  PathId;
-	unsigned char  TargetId;
+	unsigned short protocol_version;
+	unsigned char path_id;
+	unsigned char target_id;
 
 	/* Note: port number is only really known on the client side */
-	unsigned int  PortNumber;
-	unsigned int  Flags;
-	unsigned int  MaxTransferBytes;
+	unsigned int port_number;
+	unsigned int flags;
+	unsigned int max_transfer_bytes;
 
 	/*  This id is unique for each channel and will correspond with */
 	/*  vendor specific data in the inquirydata */
-	unsigned long long UniqueId;
+	unsigned long long unique_id;
 } __attribute__((packed));
 
 /*  This structure is sent during the storage protocol negotiations. */
 struct vmstorage_protocol_version {
 	/* Major (MSW) and minor (LSW) version numbers. */
-	unsigned short MajorMinor;
+	unsigned short major_minor;
 
 	/*
 	 * Revision number is auto-incremented whenever this file is changed
@@ -148,7 +148,7 @@ struct vmstorage_protocol_version {
 	 * definitely indicate incompatibility--but it does indicate mismatched
 	 * builds.
 	 */
-	unsigned short Revision;
+	unsigned short revision;
 } __attribute__((packed));
 
 /* Channel Property Flags */
@@ -157,13 +157,13 @@ struct vmstorage_protocol_version {
 
 struct vstor_packet {
 	/* Requested operation type */
-	enum vstor_packet_operation Operation;
+	enum vstor_packet_operation operation;
 
 	/*  Flags - see below for values */
-	unsigned int     Flags;
+	unsigned int flags;
 
 	/* Status of the request returned from the server side. */
-	unsigned int     Status;
+	unsigned int status;
 
 	/* Data payload area */
 	union {
@@ -171,13 +171,13 @@ struct vstor_packet {
 		 * Structure used to forward SCSI commands from the
 		 * client to the server.
 		 */
-		struct vmscsi_request VmSrb;
+		struct vmscsi_request vm_srb;
 
 		/* Structure used to query channel properties. */
-		struct vmstorage_channel_properties StorageChannelProperties;
+		struct vmstorage_channel_properties storage_channel_properties;
 
 		/* Used during version negotiations. */
-		struct vmstorage_protocol_version Version;
+		struct vmstorage_protocol_version version;
 	};
 } __attribute__((packed));
 
-- 
1.6.0.2

^ permalink raw reply related

* [PATCH 2/8] staging: hv: Convert camel case struct fields in storvsc_api.h to lowercase
From: Hank Janssen @ 2010-12-06 20:26 UTC (permalink / raw)
  To: hjanssen, gregkh, linux-kernel, devel, virtualization
  Cc: Haiyang Zhang, Abhishek Kane
In-Reply-To: <1291667211-1865-1-git-send-email-hjanssen@microsoft.com>

From: Hank Janssen <hjanssen@microsoft.com> 

Convert camel case struct fields in vstorage.h to lowercase

Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>

---
 drivers/staging/hv/blkvsc.c      |   20 +++---
 drivers/staging/hv/blkvsc_drv.c  |  115 ++++++++++++++++++++------------------
 drivers/staging/hv/storvsc.c     |   67 +++++++++++-----------
 drivers/staging/hv/storvsc_api.h |   50 ++++++++--------
 drivers/staging/hv/storvsc_drv.c |   91 +++++++++++++++---------------
 5 files changed, 175 insertions(+), 168 deletions(-)

diff --git a/drivers/staging/hv/blkvsc.c b/drivers/staging/hv/blkvsc.c
index d5b0abd..9ac04c3 100644
--- a/drivers/staging/hv/blkvsc.c
+++ b/drivers/staging/hv/blkvsc.c
@@ -51,12 +51,12 @@ static int BlkVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo)
 	 * id. For IDE devices, the device instance id is formatted as
 	 * <bus id> * - <device id> - 8899 - 000000000000.
 	 */
-	deviceInfo->PathId = Device->deviceInstance.data[3] << 24 |
+	deviceInfo->path_id = Device->deviceInstance.data[3] << 24 |
 			     Device->deviceInstance.data[2] << 16 |
 			     Device->deviceInstance.data[1] << 8  |
 			     Device->deviceInstance.data[0];
 
-	deviceInfo->TargetId = Device->deviceInstance.data[5] << 8 |
+	deviceInfo->target_id = Device->deviceInstance.data[5] << 8 |
 			       Device->deviceInstance.data[4];
 
 	return ret;
@@ -75,7 +75,7 @@ int BlkVscInitialize(struct hv_driver *Driver)
 	Driver->name = gBlkDriverName;
 	memcpy(&Driver->deviceType, &gBlkVscDeviceType, sizeof(struct hv_guid));
 
-	storDriver->RequestExtSize = sizeof(struct storvsc_request_extension);
+	storDriver->request_ext_size = sizeof(struct storvsc_request_extension);
 
 	/*
 	 * Divide the ring buffer data size (which is 1 page less than the ring
@@ -83,20 +83,20 @@ int BlkVscInitialize(struct hv_driver *Driver)
 	 * by the max request size (which is
 	 * vmbus_channel_packet_multipage_buffer + struct vstor_packet + u64)
 	 */
-	storDriver->MaxOutstandingRequestsPerChannel =
-		((storDriver->RingBufferSize - PAGE_SIZE) /
+	storDriver->max_outstanding_req_per_channel =
+		((storDriver->ring_buffer_size - PAGE_SIZE) /
 		  ALIGN_UP(MAX_MULTIPAGE_BUFFER_PACKET +
 			   sizeof(struct vstor_packet) + sizeof(u64),
 			   sizeof(u64)));
 
 	DPRINT_INFO(BLKVSC, "max io outstd %u",
-		    storDriver->MaxOutstandingRequestsPerChannel);
+		    storDriver->max_outstanding_req_per_channel);
 
 	/* Setup the dispatch table */
-	storDriver->Base.OnDeviceAdd = BlkVscOnDeviceAdd;
-	storDriver->Base.OnDeviceRemove = StorVscOnDeviceRemove;
-	storDriver->Base.OnCleanup = StorVscOnCleanup;
-	storDriver->OnIORequest	= StorVscOnIORequest;
+	storDriver->base.OnDeviceAdd = BlkVscOnDeviceAdd;
+	storDriver->base.OnDeviceRemove = StorVscOnDeviceRemove;
+	storDriver->base.OnCleanup = StorVscOnCleanup;
+	storDriver->on_io_request = StorVscOnIORequest;
 
 	return ret;
 }
diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
index 3f81ca5..d65d69e 100644
--- a/drivers/staging/hv/blkvsc_drv.c
+++ b/drivers/staging/hv/blkvsc_drv.c
@@ -177,13 +177,13 @@ static int blkvsc_drv_init(int (*drv_init)(struct hv_driver *drv))
 	struct driver_context *drv_ctx = &g_blkvsc_drv.drv_ctx;
 	int ret;
 
-	storvsc_drv_obj->RingBufferSize = blkvsc_ringbuffer_size;
+	storvsc_drv_obj->ring_buffer_size = blkvsc_ringbuffer_size;
 
 	/* Callback to client driver to complete the initialization */
-	drv_init(&storvsc_drv_obj->Base);
+	drv_init(&storvsc_drv_obj->base);
 
-	drv_ctx->driver.name = storvsc_drv_obj->Base.name;
-	memcpy(&drv_ctx->class_id, &storvsc_drv_obj->Base.deviceType,
+	drv_ctx->driver.name = storvsc_drv_obj->base.name;
+	memcpy(&drv_ctx->class_id, &storvsc_drv_obj->base.deviceType,
 	       sizeof(struct hv_guid));
 
 	drv_ctx->probe = blkvsc_probe;
@@ -230,8 +230,8 @@ static void blkvsc_drv_exit(void)
 		device_unregister(current_dev);
 	}
 
-	if (storvsc_drv_obj->Base.OnCleanup)
-		storvsc_drv_obj->Base.OnCleanup(&storvsc_drv_obj->Base);
+	if (storvsc_drv_obj->base.OnCleanup)
+		storvsc_drv_obj->base.OnCleanup(&storvsc_drv_obj->base);
 
 	vmbus_child_driver_unregister(drv_ctx);
 
@@ -262,7 +262,7 @@ static int blkvsc_probe(struct device *device)
 
 	DPRINT_DBG(BLKVSC_DRV, "blkvsc_probe - enter");
 
-	if (!storvsc_drv_obj->Base.OnDeviceAdd) {
+	if (!storvsc_drv_obj->base.OnDeviceAdd) {
 		DPRINT_ERR(BLKVSC_DRV, "OnDeviceAdd() not set");
 		ret = -1;
 		goto Cleanup;
@@ -284,7 +284,7 @@ static int blkvsc_probe(struct device *device)
 
 	blkdev->request_pool = kmem_cache_create(dev_name(&device_ctx->device),
 					sizeof(struct blkvsc_request) +
-					storvsc_drv_obj->RequestExtSize, 0,
+					storvsc_drv_obj->request_ext_size, 0,
 					SLAB_HWCACHE_ALIGN, NULL);
 	if (!blkdev->request_pool) {
 		ret = -ENOMEM;
@@ -293,7 +293,7 @@ static int blkvsc_probe(struct device *device)
 
 
 	/* Call to the vsc driver to add the device */
-	ret = storvsc_drv_obj->Base.OnDeviceAdd(device_obj, &device_info);
+	ret = storvsc_drv_obj->base.OnDeviceAdd(device_obj, &device_info);
 	if (ret != 0) {
 		DPRINT_ERR(BLKVSC_DRV, "unable to add blkvsc device");
 		goto Cleanup;
@@ -301,9 +301,9 @@ static int blkvsc_probe(struct device *device)
 
 	blkdev->device_ctx = device_ctx;
 	/* this identified the device 0 or 1 */
-	blkdev->target = device_info.TargetId;
+	blkdev->target = device_info.target_id;
 	/* this identified the ide ctrl 0 or 1 */
-	blkdev->path = device_info.PathId;
+	blkdev->path = device_info.path_id;
 
 	dev_set_drvdata(device, blkdev);
 
@@ -391,7 +391,7 @@ static int blkvsc_probe(struct device *device)
 	return ret;
 
 Remove:
-	storvsc_drv_obj->Base.OnDeviceRemove(device_obj);
+	storvsc_drv_obj->base.OnDeviceRemove(device_obj);
 
 Cleanup:
 	if (blkdev) {
@@ -459,9 +459,9 @@ static int blkvsc_do_flush(struct block_device_context *blkdev)
 	blkvsc_req->req = NULL;
 	blkvsc_req->write = 0;
 
-	blkvsc_req->request.DataBuffer.PfnArray[0] = 0;
-	blkvsc_req->request.DataBuffer.Offset = 0;
-	blkvsc_req->request.DataBuffer.Length = 0;
+	blkvsc_req->request.data_buffer.PfnArray[0] = 0;
+	blkvsc_req->request.data_buffer.Offset = 0;
+	blkvsc_req->request.data_buffer.Length = 0;
 
 	blkvsc_req->cmnd[0] = SYNCHRONIZE_CACHE;
 	blkvsc_req->cmd_len = 10;
@@ -506,9 +506,9 @@ static int blkvsc_do_inquiry(struct block_device_context *blkdev)
 	blkvsc_req->req = NULL;
 	blkvsc_req->write = 0;
 
-	blkvsc_req->request.DataBuffer.PfnArray[0] = page_to_pfn(page_buf);
-	blkvsc_req->request.DataBuffer.Offset = 0;
-	blkvsc_req->request.DataBuffer.Length = 64;
+	blkvsc_req->request.data_buffer.PfnArray[0] = page_to_pfn(page_buf);
+	blkvsc_req->request.data_buffer.Offset = 0;
+	blkvsc_req->request.data_buffer.Length = 64;
 
 	blkvsc_req->cmnd[0] = INQUIRY;
 	blkvsc_req->cmnd[1] = 0x1;		/* Get product data */
@@ -593,9 +593,9 @@ static int blkvsc_do_read_capacity(struct block_device_context *blkdev)
 	blkvsc_req->req = NULL;
 	blkvsc_req->write = 0;
 
-	blkvsc_req->request.DataBuffer.PfnArray[0] = page_to_pfn(page_buf);
-	blkvsc_req->request.DataBuffer.Offset = 0;
-	blkvsc_req->request.DataBuffer.Length = 8;
+	blkvsc_req->request.data_buffer.PfnArray[0] = page_to_pfn(page_buf);
+	blkvsc_req->request.data_buffer.Offset = 0;
+	blkvsc_req->request.data_buffer.Length = 8;
 
 	blkvsc_req->cmnd[0] = READ_CAPACITY;
 	blkvsc_req->cmd_len = 16;
@@ -614,7 +614,7 @@ static int blkvsc_do_read_capacity(struct block_device_context *blkdev)
 	wait_event_interruptible(blkvsc_req->wevent, blkvsc_req->cond);
 
 	/* check error */
-	if (blkvsc_req->request.Status) {
+	if (blkvsc_req->request.status) {
 		scsi_normalize_sense(blkvsc_req->sense_buffer,
 				     SCSI_SENSE_BUFFERSIZE, &sense_hdr);
 
@@ -670,9 +670,9 @@ static int blkvsc_do_read_capacity16(struct block_device_context *blkdev)
 	blkvsc_req->req = NULL;
 	blkvsc_req->write = 0;
 
-	blkvsc_req->request.DataBuffer.PfnArray[0] = page_to_pfn(page_buf);
-	blkvsc_req->request.DataBuffer.Offset = 0;
-	blkvsc_req->request.DataBuffer.Length = 12;
+	blkvsc_req->request.data_buffer.PfnArray[0] = page_to_pfn(page_buf);
+	blkvsc_req->request.data_buffer.Offset = 0;
+	blkvsc_req->request.data_buffer.Length = 12;
 
 	blkvsc_req->cmnd[0] = 0x9E; /* READ_CAPACITY16; */
 	blkvsc_req->cmd_len = 16;
@@ -691,7 +691,7 @@ static int blkvsc_do_read_capacity16(struct block_device_context *blkdev)
 	wait_event_interruptible(blkvsc_req->wevent, blkvsc_req->cond);
 
 	/* check error */
-	if (blkvsc_req->request.Status) {
+	if (blkvsc_req->request.status) {
 		scsi_normalize_sense(blkvsc_req->sense_buffer,
 				     SCSI_SENSE_BUFFERSIZE, &sense_hdr);
 		if (sense_hdr.asc == 0x3A) {
@@ -741,14 +741,14 @@ static int blkvsc_remove(struct device *device)
 
 	DPRINT_DBG(BLKVSC_DRV, "blkvsc_remove()\n");
 
-	if (!storvsc_drv_obj->Base.OnDeviceRemove)
+	if (!storvsc_drv_obj->base.OnDeviceRemove)
 		return -1;
 
 	/*
 	 * Call to the vsc driver to let it know that the device is being
 	 * removed
 	 */
-	ret = storvsc_drv_obj->Base.OnDeviceRemove(device_obj);
+	ret = storvsc_drv_obj->base.OnDeviceRemove(device_obj);
 	if (ret != 0) {
 		/* TODO: */
 		DPRINT_ERR(BLKVSC_DRV,
@@ -865,38 +865,38 @@ static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req,
 		   (blkvsc_req->write) ? "WRITE" : "READ",
 		   (unsigned long) blkvsc_req->sector_start,
 		   blkvsc_req->sector_count,
-		   blkvsc_req->request.DataBuffer.Offset,
-		   blkvsc_req->request.DataBuffer.Length);
+		   blkvsc_req->request.data_buffer.Offset,
+		   blkvsc_req->request.data_buffer.Length);
 #if 0
-	for (i = 0; i < (blkvsc_req->request.DataBuffer.Length >> 12); i++) {
+	for (i = 0; i < (blkvsc_req->request.data_buffer.Length >> 12); i++) {
 		DPRINT_DBG(BLKVSC_DRV, "blkvsc_submit_request() - "
 			   "req %p pfn[%d] %llx\n",
 			   blkvsc_req, i,
-			   blkvsc_req->request.DataBuffer.PfnArray[i]);
+			   blkvsc_req->request.data_buffer.PfnArray[i]);
 	}
 #endif
 
 	storvsc_req = &blkvsc_req->request;
-	storvsc_req->Extension = (void *)((unsigned long)blkvsc_req +
+	storvsc_req->extension = (void *)((unsigned long)blkvsc_req +
 					  sizeof(struct blkvsc_request));
 
-	storvsc_req->Type = blkvsc_req->write ? WRITE_TYPE : READ_TYPE;
+	storvsc_req->type = blkvsc_req->write ? WRITE_TYPE : READ_TYPE;
 
-	storvsc_req->OnIOCompletion = request_completion;
-	storvsc_req->Context = blkvsc_req;
+	storvsc_req->on_io_completion = request_completion;
+	storvsc_req->context = blkvsc_req;
 
-	storvsc_req->Host = blkdev->port;
-	storvsc_req->Bus = blkdev->path;
-	storvsc_req->TargetId = blkdev->target;
-	storvsc_req->LunId = 0;	 /* this is not really used at all */
+	storvsc_req->host = blkdev->port;
+	storvsc_req->bus = blkdev->path;
+	storvsc_req->target_id = blkdev->target;
+	storvsc_req->lun_id = 0;	 /* this is not really used at all */
 
-	storvsc_req->CdbLen = blkvsc_req->cmd_len;
-	storvsc_req->Cdb = blkvsc_req->cmnd;
+	storvsc_req->cdb_len = blkvsc_req->cmd_len;
+	storvsc_req->cdb = blkvsc_req->cmnd;
 
-	storvsc_req->SenseBuffer = blkvsc_req->sense_buffer;
-	storvsc_req->SenseBufferSize = SCSI_SENSE_BUFFERSIZE;
+	storvsc_req->sense_buffer = blkvsc_req->sense_buffer;
+	storvsc_req->sense_buffer_size = SCSI_SENSE_BUFFERSIZE;
 
-	ret = storvsc_drv_obj->OnIORequest(&blkdev->device_ctx->device_obj,
+	ret = storvsc_drv_obj->on_io_request(&blkdev->device_ctx->device_obj,
 					   &blkvsc_req->request);
 	if (ret == 0)
 		blkdev->num_outstanding_reqs++;
@@ -992,8 +992,10 @@ static int blkvsc_do_request(struct block_device_context *blkdev,
 
 					blkvsc_req->dev = blkdev;
 					blkvsc_req->req = req;
-					blkvsc_req->request.DataBuffer.Offset = bvec->bv_offset;
-					blkvsc_req->request.DataBuffer.Length = 0;
+					blkvsc_req->request.data_buffer.Offset
+						= bvec->bv_offset;
+					blkvsc_req->request.data_buffer.Length
+						= 0;
 
 					/* Add to the group */
 					blkvsc_req->group = group;
@@ -1007,8 +1009,11 @@ static int blkvsc_do_request(struct block_device_context *blkdev,
 				}
 
 				/* Add the curr bvec/segment to the curr blkvsc_req */
-				blkvsc_req->request.DataBuffer.PfnArray[databuf_idx] = page_to_pfn(bvec->bv_page);
-				blkvsc_req->request.DataBuffer.Length += bvec->bv_len;
+				blkvsc_req->request.data_buffer.
+					PfnArray[databuf_idx]
+						= page_to_pfn(bvec->bv_page);
+				blkvsc_req->request.data_buffer.Length
+					+= bvec->bv_len;
 
 				prev_bvec = bvec;
 
@@ -1073,7 +1078,7 @@ static int blkvsc_do_request(struct block_device_context *blkdev,
 static void blkvsc_cmd_completion(struct hv_storvsc_request *request)
 {
 	struct blkvsc_request *blkvsc_req =
-			(struct blkvsc_request *)request->Context;
+			(struct blkvsc_request *)request->context;
 	struct block_device_context *blkdev =
 			(struct block_device_context *)blkvsc_req->dev;
 	struct scsi_sense_hdr sense_hdr;
@@ -1083,7 +1088,7 @@ static void blkvsc_cmd_completion(struct hv_storvsc_request *request)
 
 	blkdev->num_outstanding_reqs--;
 
-	if (blkvsc_req->request.Status)
+	if (blkvsc_req->request.status)
 		if (scsi_normalize_sense(blkvsc_req->sense_buffer,
 					 SCSI_SENSE_BUFFERSIZE, &sense_hdr))
 			scsi_print_sense_hdr("blkvsc", &sense_hdr);
@@ -1095,7 +1100,7 @@ static void blkvsc_cmd_completion(struct hv_storvsc_request *request)
 static void blkvsc_request_completion(struct hv_storvsc_request *request)
 {
 	struct blkvsc_request *blkvsc_req =
-			(struct blkvsc_request *)request->Context;
+			(struct blkvsc_request *)request->context;
 	struct block_device_context *blkdev =
 			(struct block_device_context *)blkvsc_req->dev;
 	unsigned long flags;
@@ -1110,7 +1115,7 @@ static void blkvsc_request_completion(struct hv_storvsc_request *request)
 		   (blkvsc_req->write) ? "WRITE" : "READ",
 		   (unsigned long)blkvsc_req->sector_start,
 		   blkvsc_req->sector_count,
-		   blkvsc_req->request.DataBuffer.Length,
+		   blkvsc_req->request.data_buffer.Length,
 		   blkvsc_req->group->outstanding,
 		   blkdev->num_outstanding_reqs);
 
@@ -1137,7 +1142,7 @@ static void blkvsc_request_completion(struct hv_storvsc_request *request)
 			list_del(&comp_req->req_entry);
 
 			if (!__blk_end_request(comp_req->req,
-				(!comp_req->request.Status ? 0 : -EIO),
+				(!comp_req->request.status ? 0 : -EIO),
 				comp_req->sector_count * blkdev->sector_size)) {
 				/*
 				 * All the sectors have been xferred ie the
@@ -1195,7 +1200,7 @@ static int blkvsc_cancel_pending_reqs(struct block_device_context *blkdev)
 
 			if (comp_req->req) {
 				ret = __blk_end_request(comp_req->req,
-					(!comp_req->request.Status ? 0 : -EIO),
+					(!comp_req->request.status ? 0 : -EIO),
 					comp_req->sector_count *
 					blkdev->sector_size);
 
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index 96b4ed9..c4346c6 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -370,16 +370,16 @@ static void StorVscOnIOCompletion(struct hv_device *Device,
 	/* ASSERT(request->OnIOCompletion != NULL); */
 
 	/* Copy over the status...etc */
-	request->Status = VStorPacket->vm_srb.scsi_status;
+	request->status = VStorPacket->vm_srb.scsi_status;
 
-	if (request->Status != 0 || VStorPacket->vm_srb.srb_status != 1) {
+	if (request->status != 0 || VStorPacket->vm_srb.srb_status != 1) {
 		DPRINT_WARN(STORVSC,
 			    "cmd 0x%x scsi status 0x%x srb status 0x%x\n",
-			    request->Cdb[0], VStorPacket->vm_srb.scsi_status,
+			    request->cdb[0], VStorPacket->vm_srb.scsi_status,
 			    VStorPacket->vm_srb.srb_status);
 	}
 
-	if ((request->Status & 0xFF) == 0x02) {
+	if ((request->status & 0xFF) == 0x02) {
 		/* CHECK_CONDITION */
 		if (VStorPacket->vm_srb.srb_status & 0x80) {
 			/* autosense data available */
@@ -389,19 +389,19 @@ static void StorVscOnIOCompletion(struct hv_device *Device,
 
 			/* ASSERT(VStorPacket->vm_srb.sense_info_length <= */
 			/* 	request->SenseBufferSize); */
-			memcpy(request->SenseBuffer,
+			memcpy(request->sense_buffer,
 			       VStorPacket->vm_srb.sense_data,
 			       VStorPacket->vm_srb.sense_info_length);
 
-			request->SenseBufferSize =
+			request->sense_buffer_size =
 					VStorPacket->vm_srb.sense_info_length;
 		}
 	}
 
 	/* TODO: */
-	request->BytesXfer = VStorPacket->vm_srb.data_transfer_length;
+	request->bytes_xfer = VStorPacket->vm_srb.data_transfer_length;
 
-	request->OnIOCompletion(request);
+	request->on_io_completion(request);
 
 	atomic_dec(&storDevice->NumOutstandingRequests);
 
@@ -501,7 +501,8 @@ static int StorVscConnectToVsp(struct hv_device *Device)
 
 	/* Open the channel */
 	ret = vmbus_open(Device->channel,
-			 storDriver->RingBufferSize, storDriver->RingBufferSize,
+			 storDriver->ring_buffer_size,
+			 storDriver->ring_buffer_size,
 			 (void *)&props,
 			 sizeof(struct vmstorage_channel_properties),
 			 StorVscOnChannelCallback, Device);
@@ -551,13 +552,13 @@ static int StorVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo)
 	storChannel->PathId = props->PathId;
 	storChannel->TargetId = props->TargetId; */
 
-	storDevice->PortNumber = deviceInfo->PortNumber;
+	storDevice->PortNumber = deviceInfo->port_number;
 	/* Send it back up */
 	ret = StorVscConnectToVsp(Device);
 
 	/* deviceInfo->PortNumber = storDevice->PortNumber; */
-	deviceInfo->PathId = storDevice->PathId;
-	deviceInfo->TargetId = storDevice->TargetId;
+	deviceInfo->path_id = storDevice->PathId;
+	deviceInfo->target_id = storDevice->TargetId;
 
 	DPRINT_DBG(STORVSC, "assigned port %u, path %u target %u\n",
 		   storDevice->PortNumber, storDevice->PathId,
@@ -672,7 +673,7 @@ static int StorVscOnIORequest(struct hv_device *Device,
 	int ret = 0;
 
 	requestExtension =
-		(struct storvsc_request_extension *)Request->Extension;
+		(struct storvsc_request_extension *)Request->extension;
 	vstorPacket = &requestExtension->VStorPacket;
 	storDevice = GetStorDevice(Device);
 
@@ -681,8 +682,8 @@ static int StorVscOnIORequest(struct hv_device *Device,
 		   requestExtension);
 
 	DPRINT_DBG(STORVSC, "req %p len %d bus %d, target %d, lun %d cdblen %d",
-		   Request, Request->DataBuffer.Length, Request->Bus,
-		   Request->TargetId, Request->LunId, Request->CdbLen);
+		   Request, Request->data_buffer.Length, Request->bus,
+		   Request->target_id, Request->lun_id, Request->cdb_len);
 
 	if (!storDevice) {
 		DPRINT_ERR(STORVSC, "unable to get stor device..."
@@ -702,19 +703,19 @@ static int StorVscOnIORequest(struct hv_device *Device,
 
 	vstorPacket->vm_srb.length = sizeof(struct vmscsi_request);
 
-	vstorPacket->vm_srb.port_number = Request->Host;
-	vstorPacket->vm_srb.path_id = Request->Bus;
-	vstorPacket->vm_srb.target_id = Request->TargetId;
-	vstorPacket->vm_srb.lun = Request->LunId;
+	vstorPacket->vm_srb.port_number = Request->host;
+	vstorPacket->vm_srb.path_id = Request->bus;
+	vstorPacket->vm_srb.target_id = Request->target_id;
+	vstorPacket->vm_srb.lun = Request->lun_id;
 
 	vstorPacket->vm_srb.sense_info_length = SENSE_BUFFER_SIZE;
 
 	/* Copy over the scsi command descriptor block */
-	vstorPacket->vm_srb.cdb_length = Request->CdbLen;
-	memcpy(&vstorPacket->vm_srb.cdb, Request->Cdb, Request->CdbLen);
+	vstorPacket->vm_srb.cdb_length = Request->cdb_len;
+	memcpy(&vstorPacket->vm_srb.cdb, Request->cdb, Request->cdb_len);
 
-	vstorPacket->vm_srb.data_in = Request->Type;
-	vstorPacket->vm_srb.data_transfer_length = Request->DataBuffer.Length;
+	vstorPacket->vm_srb.data_in = Request->type;
+	vstorPacket->vm_srb.data_transfer_length = Request->data_buffer.Length;
 
 	vstorPacket->operation = VSTOR_OPERATION_EXECUTE_SRB;
 
@@ -728,9 +729,9 @@ static int StorVscOnIORequest(struct hv_device *Device,
 		   vstorPacket->vm_srb.sense_info_length,
 		   vstorPacket->vm_srb.cdb_length);
 
-	if (requestExtension->Request->DataBuffer.Length) {
+	if (requestExtension->Request->data_buffer.Length) {
 		ret = vmbus_sendpacket_multipagebuffer(Device->channel,
-				&requestExtension->Request->DataBuffer,
+				&requestExtension->Request->data_buffer,
 				vstorPacket,
 				sizeof(struct vstor_packet),
 				(unsigned long)requestExtension);
@@ -785,7 +786,7 @@ int StorVscInitialize(struct hv_driver *Driver)
 	memcpy(&Driver->deviceType, &gStorVscDeviceType,
 	       sizeof(struct hv_guid));
 
-	storDriver->RequestExtSize = sizeof(struct storvsc_request_extension);
+	storDriver->request_ext_size = sizeof(struct storvsc_request_extension);
 
 	/*
 	 * Divide the ring buffer data size (which is 1 page less
@@ -793,22 +794,22 @@ int StorVscInitialize(struct hv_driver *Driver)
 	 * the ring buffer indices) by the max request size (which is
 	 * vmbus_channel_packet_multipage_buffer + struct vstor_packet + u64)
 	 */
-	storDriver->MaxOutstandingRequestsPerChannel =
-		((storDriver->RingBufferSize - PAGE_SIZE) /
+	storDriver->max_outstanding_req_per_channel =
+		((storDriver->ring_buffer_size - PAGE_SIZE) /
 		  ALIGN_UP(MAX_MULTIPAGE_BUFFER_PACKET +
 			   sizeof(struct vstor_packet) + sizeof(u64),
 			   sizeof(u64)));
 
 	DPRINT_INFO(STORVSC, "max io %u, currently %u\n",
-		    storDriver->MaxOutstandingRequestsPerChannel,
+		    storDriver->max_outstanding_req_per_channel,
 		    STORVSC_MAX_IO_REQUESTS);
 
 	/* Setup the dispatch table */
-	storDriver->Base.OnDeviceAdd	= StorVscOnDeviceAdd;
-	storDriver->Base.OnDeviceRemove	= StorVscOnDeviceRemove;
-	storDriver->Base.OnCleanup	= StorVscOnCleanup;
+	storDriver->base.OnDeviceAdd	= StorVscOnDeviceAdd;
+	storDriver->base.OnDeviceRemove	= StorVscOnDeviceRemove;
+	storDriver->base.OnCleanup	= StorVscOnCleanup;
 
-	storDriver->OnIORequest		= StorVscOnIORequest;
+	storDriver->on_io_request	= StorVscOnIORequest;
 
 	return 0;
 }
diff --git a/drivers/staging/hv/storvsc_api.h b/drivers/staging/hv/storvsc_api.h
index 8505a1c..46f031e 100644
--- a/drivers/staging/hv/storvsc_api.h
+++ b/drivers/staging/hv/storvsc_api.h
@@ -53,58 +53,58 @@ enum storvsc_request_type{
 };
 
 struct hv_storvsc_request {
-	enum storvsc_request_type Type;
-	u32 Host;
-	u32 Bus;
-	u32 TargetId;
-	u32 LunId;
-	u8 *Cdb;
-	u32 CdbLen;
-	u32 Status;
-	u32 BytesXfer;
+	enum storvsc_request_type type;
+	u32 host;
+	u32 bus;
+	u32 target_id;
+	u32 lun_id;
+	u8 *cdb;
+	u32 cdb_len;
+	u32 status;
+	u32 bytes_xfer;
 
-	unsigned char *SenseBuffer;
-	u32 SenseBufferSize;
+	unsigned char *sense_buffer;
+	u32 sense_buffer_size;
 
-	void *Context;
+	void *context;
 
-	void (*OnIOCompletion)(struct hv_storvsc_request *Request);
+	void (*on_io_completion)(struct hv_storvsc_request *request);
 
 	/* This points to the memory after DataBuffer */
-	void *Extension;
+	void *extension;
 
-	struct hv_multipage_buffer DataBuffer;
+	struct hv_multipage_buffer data_buffer;
 };
 
 /* Represents the block vsc driver */
 struct storvsc_driver_object {
 	/* Must be the first field */
 	/* Which is a bug FIXME! */
-	struct hv_driver Base;
+	struct hv_driver base;
 
 	/* Set by caller (in bytes) */
-	u32 RingBufferSize;
+	u32 ring_buffer_size;
 
 	/* Allocate this much private extension for each I/O request */
-	u32 RequestExtSize;
+	u32 request_ext_size;
 
 	/* Maximum # of requests in flight per channel/device */
-	u32 MaxOutstandingRequestsPerChannel;
+	u32 max_outstanding_req_per_channel;
 
 	/* Specific to this driver */
-	int (*OnIORequest)(struct hv_device *Device,
-			   struct hv_storvsc_request *Request);
+	int (*on_io_request)(struct hv_device *device,
+			   struct hv_storvsc_request *request);
 };
 
 struct storvsc_device_info {
-	unsigned int PortNumber;
-	unsigned char PathId;
-	unsigned char TargetId;
+	unsigned int port_number;
+	unsigned char path_id;
+	unsigned char target_id;
 };
 
 /* Interface */
 int StorVscInitialize(struct hv_driver *driver);
-int StorVscOnHostReset(struct hv_device *Device);
+int StorVscOnHostReset(struct hv_device *device);
 int BlkVscInitialize(struct hv_driver *driver);
 
 #endif /* _STORVSC_API_H_ */
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index defc34a..03695ce 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -141,28 +141,28 @@ static int storvsc_drv_init(int (*drv_init)(struct hv_driver *drv))
 	struct storvsc_driver_object *storvsc_drv_obj = &g_storvsc_drv.drv_obj;
 	struct driver_context *drv_ctx = &g_storvsc_drv.drv_ctx;
 
-	storvsc_drv_obj->RingBufferSize = storvsc_ringbuffer_size;
+	storvsc_drv_obj->ring_buffer_size = storvsc_ringbuffer_size;
 
 	/* Callback to client driver to complete the initialization */
-	drv_init(&storvsc_drv_obj->Base);
+	drv_init(&storvsc_drv_obj->base);
 
 	DPRINT_INFO(STORVSC_DRV,
 		    "request extension size %u, max outstanding reqs %u",
-		    storvsc_drv_obj->RequestExtSize,
-		    storvsc_drv_obj->MaxOutstandingRequestsPerChannel);
+		    storvsc_drv_obj->request_ext_size,
+		    storvsc_drv_obj->max_outstanding_req_per_channel);
 
-	if (storvsc_drv_obj->MaxOutstandingRequestsPerChannel <
+	if (storvsc_drv_obj->max_outstanding_req_per_channel <
 	    STORVSC_MAX_IO_REQUESTS) {
 		DPRINT_ERR(STORVSC_DRV,
 			   "The number of outstanding io requests (%d) "
 			   "is larger than that supported (%d) internally.",
 			   STORVSC_MAX_IO_REQUESTS,
-			   storvsc_drv_obj->MaxOutstandingRequestsPerChannel);
+			   storvsc_drv_obj->max_outstanding_req_per_channel);
 		return -1;
 	}
 
-	drv_ctx->driver.name = storvsc_drv_obj->Base.name;
-	memcpy(&drv_ctx->class_id, &storvsc_drv_obj->Base.deviceType,
+	drv_ctx->driver.name = storvsc_drv_obj->base.name;
+	memcpy(&drv_ctx->class_id, &storvsc_drv_obj->base.deviceType,
 	       sizeof(struct hv_guid));
 
 	drv_ctx->probe = storvsc_probe;
@@ -207,8 +207,8 @@ static void storvsc_drv_exit(void)
 		device_unregister(current_dev);
 	}
 
-	if (storvsc_drv_obj->Base.OnCleanup)
-		storvsc_drv_obj->Base.OnCleanup(&storvsc_drv_obj->Base);
+	if (storvsc_drv_obj->base.OnCleanup)
+		storvsc_drv_obj->base.OnCleanup(&storvsc_drv_obj->base);
 
 	vmbus_child_driver_unregister(drv_ctx);
 	return;
@@ -232,7 +232,7 @@ static int storvsc_probe(struct device *device)
 	struct host_device_context *host_device_ctx;
 	struct storvsc_device_info device_info;
 
-	if (!storvsc_drv_obj->Base.OnDeviceAdd)
+	if (!storvsc_drv_obj->base.OnDeviceAdd)
 		return -1;
 
 	host = scsi_host_alloc(&scsi_driver,
@@ -253,7 +253,7 @@ static int storvsc_probe(struct device *device)
 	host_device_ctx->request_pool =
 				kmem_cache_create(dev_name(&device_ctx->device),
 					sizeof(struct storvsc_cmd_request) +
-					storvsc_drv_obj->RequestExtSize, 0,
+					storvsc_drv_obj->request_ext_size, 0,
 					SLAB_HWCACHE_ALIGN, NULL);
 
 	if (!host_device_ctx->request_pool) {
@@ -261,9 +261,9 @@ static int storvsc_probe(struct device *device)
 		return -ENOMEM;
 	}
 
-	device_info.PortNumber = host->host_no;
+	device_info.port_number = host->host_no;
 	/* Call to the vsc driver to add the device */
-	ret = storvsc_drv_obj->Base.OnDeviceAdd(device_obj,
+	ret = storvsc_drv_obj->base.OnDeviceAdd(device_obj,
 						(void *)&device_info);
 	if (ret != 0) {
 		DPRINT_ERR(STORVSC_DRV, "unable to add scsi vsc device");
@@ -273,8 +273,8 @@ static int storvsc_probe(struct device *device)
 	}
 
 	/* host_device_ctx->port = device_info.PortNumber; */
-	host_device_ctx->path = device_info.PathId;
-	host_device_ctx->target = device_info.TargetId;
+	host_device_ctx->path = device_info.path_id;
+	host_device_ctx->target = device_info.target_id;
 
 	/* max # of devices per target */
 	host->max_lun = STORVSC_MAX_LUNS_PER_TARGET;
@@ -288,7 +288,7 @@ static int storvsc_probe(struct device *device)
 	if (ret != 0) {
 		DPRINT_ERR(STORVSC_DRV, "unable to add scsi host device");
 
-		storvsc_drv_obj->Base.OnDeviceRemove(device_obj);
+		storvsc_drv_obj->base.OnDeviceRemove(device_obj);
 
 		kmem_cache_destroy(host_device_ctx->request_pool);
 		scsi_host_put(host);
@@ -318,14 +318,14 @@ static int storvsc_remove(struct device *device)
 			(struct host_device_context *)host->hostdata;
 
 
-	if (!storvsc_drv_obj->Base.OnDeviceRemove)
+	if (!storvsc_drv_obj->base.OnDeviceRemove)
 		return -1;
 
 	/*
 	 * Call to the vsc driver to let it know that the device is being
 	 * removed
 	 */
-	ret = storvsc_drv_obj->Base.OnDeviceRemove(device_obj);
+	ret = storvsc_drv_obj->base.OnDeviceRemove(device_obj);
 	if (ret != 0) {
 		/* TODO: */
 		DPRINT_ERR(STORVSC, "unable to remove vsc device (ret %d)",
@@ -351,7 +351,7 @@ static int storvsc_remove(struct device *device)
 static void storvsc_commmand_completion(struct hv_storvsc_request *request)
 {
 	struct storvsc_cmd_request *cmd_request =
-		(struct storvsc_cmd_request *)request->Context;
+		(struct storvsc_cmd_request *)request->context;
 	struct scsi_cmnd *scmnd = cmd_request->cmd;
 	struct host_device_context *host_device_ctx =
 		(struct host_device_context *)scmnd->device->host->hostdata;
@@ -376,16 +376,17 @@ static void storvsc_commmand_completion(struct hv_storvsc_request *request)
 				      cmd_request->bounce_sgl_count);
 	}
 
-	scmnd->result = request->Status;
+	scmnd->result = request->status;
 
 	if (scmnd->result) {
 		if (scsi_normalize_sense(scmnd->sense_buffer,
-					 request->SenseBufferSize, &sense_hdr))
+				request->sense_buffer_size, &sense_hdr))
 			scsi_print_sense_hdr("storvsc", &sense_hdr);
 	}
 
-	/* ASSERT(request->BytesXfer <= request->DataBuffer.Length); */
-	scsi_set_resid(scmnd, request->DataBuffer.Length - request->BytesXfer);
+	/* ASSERT(request->BytesXfer <= request->data_buffer.Length); */
+	scsi_set_resid(scmnd,
+		request->data_buffer.Length - request->bytes_xfer);
 
 	scsi_done_fn = scmnd->scsi_done;
 
@@ -658,42 +659,42 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
 
 	request = &cmd_request->request;
 
-	request->Extension =
+	request->extension =
 		(void *)((unsigned long)cmd_request + request_size);
 	DPRINT_DBG(STORVSC_DRV, "req %p size %d ext %d", request, request_size,
-		   storvsc_drv_obj->RequestExtSize);
+		   storvsc_drv_obj->request_ext_size);
 
 	/* Build the SRB */
 	switch (scmnd->sc_data_direction) {
 	case DMA_TO_DEVICE:
-		request->Type = WRITE_TYPE;
+		request->type = WRITE_TYPE;
 		break;
 	case DMA_FROM_DEVICE:
-		request->Type = READ_TYPE;
+		request->type = READ_TYPE;
 		break;
 	default:
-		request->Type = UNKNOWN_TYPE;
+		request->type = UNKNOWN_TYPE;
 		break;
 	}
 
-	request->OnIOCompletion = storvsc_commmand_completion;
-	request->Context = cmd_request;/* scmnd; */
+	request->on_io_completion = storvsc_commmand_completion;
+	request->context = cmd_request;/* scmnd; */
 
 	/* request->PortId = scmnd->device->channel; */
-	request->Host = host_device_ctx->port;
-	request->Bus = scmnd->device->channel;
-	request->TargetId = scmnd->device->id;
-	request->LunId = scmnd->device->lun;
+	request->host = host_device_ctx->port;
+	request->bus = scmnd->device->channel;
+	request->target_id = scmnd->device->id;
+	request->lun_id = scmnd->device->lun;
 
 	/* ASSERT(scmnd->cmd_len <= 16); */
-	request->CdbLen = scmnd->cmd_len;
-	request->Cdb = scmnd->cmnd;
+	request->cdb_len = scmnd->cmd_len;
+	request->cdb = scmnd->cmnd;
 
-	request->SenseBuffer = scmnd->sense_buffer;
-	request->SenseBufferSize = SCSI_SENSE_BUFFERSIZE;
+	request->sense_buffer = scmnd->sense_buffer;
+	request->sense_buffer_size = SCSI_SENSE_BUFFERSIZE;
 
 
-	request->DataBuffer.Length = scsi_bufflen(scmnd);
+	request->data_buffer.Length = scsi_bufflen(scmnd);
 	if (scsi_sg_count(scmnd)) {
 		sgl = (struct scatterlist *)scsi_sglist(scmnd);
 		sg_count = scsi_sg_count(scmnd);
@@ -734,25 +735,25 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
 			sg_count = cmd_request->bounce_sgl_count;
 		}
 
-		request->DataBuffer.Offset = sgl[0].offset;
+		request->data_buffer.Offset = sgl[0].offset;
 
 		for (i = 0; i < sg_count; i++) {
 			DPRINT_DBG(STORVSC_DRV, "sgl[%d] len %d offset %d\n",
 				   i, sgl[i].length, sgl[i].offset);
-			request->DataBuffer.PfnArray[i] =
+			request->data_buffer.PfnArray[i] =
 				page_to_pfn(sg_page((&sgl[i])));
 		}
 	} else if (scsi_sglist(scmnd)) {
 		/* ASSERT(scsi_bufflen(scmnd) <= PAGE_SIZE); */
-		request->DataBuffer.Offset =
+		request->data_buffer.Offset =
 			virt_to_phys(scsi_sglist(scmnd)) & (PAGE_SIZE-1);
-		request->DataBuffer.PfnArray[0] =
+		request->data_buffer.PfnArray[0] =
 			virt_to_phys(scsi_sglist(scmnd)) >> PAGE_SHIFT;
 	}
 
 retry_request:
 	/* Invokes the vsc to start an IO */
-	ret = storvsc_drv_obj->OnIORequest(&device_ctx->device_obj,
+	ret = storvsc_drv_obj->on_io_request(&device_ctx->device_obj,
 					   &cmd_request->request);
 	if (ret == -1) {
 		/* no more space */
-- 
1.6.0.2

^ permalink raw reply related

* [PATCH 3/8] staging: hv: Convert camel case functions in storvsc_api.h to lowercase
From: Hank Janssen @ 2010-12-06 20:26 UTC (permalink / raw)
  To: hjanssen, gregkh, linux-kernel, devel, virtualization
  Cc: Haiyang Zhang, Abhishek Kane
In-Reply-To: <1291667211-1865-2-git-send-email-hjanssen@microsoft.com>

From: Hank Janssen <hjanssen@microsoft.com> 

Convert camel case functions in storvsc_api.h to lowercase

Signed-off-by: Abhishek Kane <v-abkane@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>

---
 drivers/staging/hv/blkvsc.c      |    2 +-
 drivers/staging/hv/blkvsc_drv.c  |    2 +-
 drivers/staging/hv/storvsc.c     |    6 +++---
 drivers/staging/hv/storvsc_api.h |    6 +++---
 drivers/staging/hv/storvsc_drv.c |    4 ++--
 5 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/staging/hv/blkvsc.c b/drivers/staging/hv/blkvsc.c
index 9ac04c3..e62c922 100644
--- a/drivers/staging/hv/blkvsc.c
+++ b/drivers/staging/hv/blkvsc.c
@@ -62,7 +62,7 @@ static int BlkVscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo)
 	return ret;
 }
 
-int BlkVscInitialize(struct hv_driver *Driver)
+int blk_vsc_initialize(struct hv_driver *Driver)
 {
 	struct storvsc_driver_object *storDriver;
 	int ret = 0;
diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
index d65d69e..b3d05fc 100644
--- a/drivers/staging/hv/blkvsc_drv.c
+++ b/drivers/staging/hv/blkvsc_drv.c
@@ -1487,7 +1487,7 @@ static int __init blkvsc_init(void)
 
 	DPRINT_INFO(BLKVSC_DRV, "Blkvsc initializing....");
 
-	ret = blkvsc_drv_init(BlkVscInitialize);
+	ret = blkvsc_drv_init(blk_vsc_initialize);
 
 	return ret;
 }
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index c4346c6..7704131 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -605,7 +605,7 @@ static int StorVscOnDeviceRemove(struct hv_device *Device)
 	return 0;
 }
 
-int StorVscOnHostReset(struct hv_device *Device)
+int stor_vsc_on_host_reset(struct hv_device *Device)
 {
 	struct storvsc_device *storDevice;
 	struct storvsc_request_extension *request;
@@ -762,9 +762,9 @@ static void StorVscOnCleanup(struct hv_driver *Driver)
 }
 
 /*
- * StorVscInitialize - Main entry point
+ * stor_vsc_initialize - Main entry point
  */
-int StorVscInitialize(struct hv_driver *Driver)
+int stor_vsc_initialize(struct hv_driver *Driver)
 {
 	struct storvsc_driver_object *storDriver;
 
diff --git a/drivers/staging/hv/storvsc_api.h b/drivers/staging/hv/storvsc_api.h
index 46f031e..fbf5755 100644
--- a/drivers/staging/hv/storvsc_api.h
+++ b/drivers/staging/hv/storvsc_api.h
@@ -103,8 +103,8 @@ struct storvsc_device_info {
 };
 
 /* Interface */
-int StorVscInitialize(struct hv_driver *driver);
-int StorVscOnHostReset(struct hv_device *device);
-int BlkVscInitialize(struct hv_driver *driver);
+int stor_vsc_initialize(struct hv_driver *driver);
+int stor_vsc_on_host_reset(struct hv_device *device);
+int blk_vsc_initialize(struct hv_driver *driver);
 
 #endif /* _STORVSC_API_H_ */
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 03695ce..0d96878 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -846,7 +846,7 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
 		    scmnd->device, &device_ctx->device_obj);
 
 	/* Invokes the vsc to reset the host/bus */
-	ret = StorVscOnHostReset(&device_ctx->device_obj);
+	ret = stor_vsc_on_host_reset(&device_ctx->device_obj);
 	if (ret != 0)
 		return ret;
 
@@ -941,7 +941,7 @@ static int __init storvsc_init(void)
 	int ret;
 
 	DPRINT_INFO(STORVSC_DRV, "Storvsc initializing....");
-	ret = storvsc_drv_init(StorVscInitialize);
+	ret = storvsc_drv_init(stor_vsc_initialize);
 	return ret;
 }
 
-- 
1.6.0.2

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox