* Re: [PATCH] virtio-pci: add softlinks between virtio and pci
From: Michael S. Tsirkin @ 2011-01-05 21:15 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Jamie Lokier, Thomas Weber, linux-kernel, virtualization
In-Reply-To: <4D24CFC1.9020305@codemonkey.ws>
On Wed, Jan 05, 2011 at 02:08:33PM -0600, Anthony Liguori wrote:
> On 01/05/2011 02:05 PM, Michael S. Tsirkin wrote:
> >On Wed, Jan 05, 2011 at 01:28:34PM -0600, Anthony Liguori wrote:
> >>On 01/05/2011 01:17 PM, Michael S. Tsirkin wrote:
> >>>We sometimes need to map between the virtio device and
> >>>the given pci device. One such use is OS installer that
> >>>gets the boot pci device from BIOS and needs to
> >>>find the relevant block device. Since it can't,
> >>>installation fails.
> >>I have no objection to this patch but I'm a tad confused by the description.
> >>
> >>I assume you mean the installer is querying the boot device via
> >>int13 get driver parameters such that it returns the pci address of
> >>the device?
> >>
> >>Or is it querying geometry information and then trying to find the
> >>best match block device?
> >>
> >>If it's the former, I don't really understand the need for a
> >>backlink since the PCI address gives you a link to the block device.
> >>OTOH, if it's the later, it would make sense but then your
> >>description doesn't really make much sense.
> >>
> >>At any rate, a better commit message would be helpful in explaining
> >>the need for this.
> >>
> >>Regards,
> >>
> >>Anthony Liguori
> >OK just to clarify: we get pci address from BIOS
> >and need the virtio device to get at the linux device
> >(e.g. block) in the end. Thus the link from pci to virtio.
> >I also added a backlink since I thought it's handy.
> >
> >Does this answer the questions?
> >
> >Rusty rewrites my commit logs anyway, he has better style :)
>
> It helps. The real reason this is needed is because in a normal
> device, there is only one struct device whereas with virtio-pci, the
> virtio-pci device has a struct device and then the actual virtio
> device has another one.
I like how it works with e.g. net devices:
$ ls -l /sys/class/net/eth1
lrwxrwxrwx 1 root root 0 Jan 5 23:10 /sys/class/net/eth1 -> ../../devices/pci0000:00/0000:00:19.0/net/eth1
We maybe could have had
lrwxrwxrwx 1 root root 0 Jan 5 23:10 /sys/bus/virtio/virtio0 -> ../../devices/pci0000:00/0000:00:19.0/virtio/virtio0
This is pretty and would preserve the compatibility, but I am not sure how to implement this:
bus seems to want to have real kobjs behind it, not softlinks.
Ideas?
> There's probably a better way to handle
> this in sysfs making virtio-pci a proper bus with only a single
> device as a child or something like that.
I admit I'm just confused by all these buses.
>
> But the links are probably an easier solution.
>
> Regards,
>
> Anthony Liguori
>
> >>>Supply softlinks between these to make it possible.
> >>>
> >>>Signed-off-by: Michael S. Tsirkin<mst@redhat.com>
> >>>---
> >>>
> >>>Gleb, could you please ack that this patch below
> >>>will be enough to fix the installer issue that
> >>>you see?
> >>>
> >>> drivers/virtio/virtio_pci.c | 18 +++++++++++++++++-
> >>> 1 files changed, 17 insertions(+), 1 deletions(-)
> >>>
> >>>diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
> >>>index ef8d9d5..06eb2f8 100644
> >>>--- a/drivers/virtio/virtio_pci.c
> >>>+++ b/drivers/virtio/virtio_pci.c
> >>>@@ -25,6 +25,7 @@
> >>> #include<linux/virtio_pci.h>
> >>> #include<linux/highmem.h>
> >>> #include<linux/spinlock.h>
> >>>+#include<linux/sysfs.h>
> >>>
> >>> MODULE_AUTHOR("Anthony Liguori<aliguori@us.ibm.com>");
> >>> MODULE_DESCRIPTION("virtio-pci");
> >>>@@ -667,8 +668,21 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
> >>> if (err)
> >>> goto out_set_drvdata;
> >>>
> >>>- return 0;
> >>>+ err = sysfs_create_link(&pci_dev->dev.kobj,&vp_dev->vdev.dev.kobj,
> >>>+ "virtio_device");
> >>>+ if (err)
> >>>+ goto out_register_device;
> >>>+
> >>>+ err = sysfs_create_link(&vp_dev->vdev.dev.kobj,&pci_dev->dev.kobj,
> >>>+ "bus_device");
> >>>+ if (err)
> >>>+ goto out_create_link;
> >>>
> >>>+ return 0;
> >>>+out_create_link:
> >>>+ sysfs_remove_link(&pci_dev->dev.kobj, "virtio_device");
> >>>+out_register_device:
> >>>+ unregister_virtio_device(&vp_dev->vdev);
> >>> out_set_drvdata:
> >>> pci_set_drvdata(pci_dev, NULL);
> >>> pci_iounmap(pci_dev, vp_dev->ioaddr);
> >>>@@ -685,6 +699,8 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev)
> >>> {
> >>> struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
> >>>
> >>>+ sysfs_remove_link(&vp_dev->vdev.dev.kobj, "bus_device");
> >>>+ sysfs_remove_link(&pci_dev->dev.kobj, "virtio_device");
> >>> unregister_virtio_device(&vp_dev->vdev);
> >>> }
> >>>
^ permalink raw reply
* Re: [PATCH] virtio-pci: add softlinks between virtio and pci
From: Anthony Liguori @ 2011-01-05 20:08 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Jamie Lokier, Thomas Weber, linux-kernel, virtualization
In-Reply-To: <20110105200501.GA3224@redhat.com>
On 01/05/2011 02:05 PM, Michael S. Tsirkin wrote:
> On Wed, Jan 05, 2011 at 01:28:34PM -0600, Anthony Liguori wrote:
>
>> On 01/05/2011 01:17 PM, Michael S. Tsirkin wrote:
>>
>>> We sometimes need to map between the virtio device and
>>> the given pci device. One such use is OS installer that
>>> gets the boot pci device from BIOS and needs to
>>> find the relevant block device. Since it can't,
>>> installation fails.
>>>
>> I have no objection to this patch but I'm a tad confused by the description.
>>
>> I assume you mean the installer is querying the boot device via
>> int13 get driver parameters such that it returns the pci address of
>> the device?
>>
>> Or is it querying geometry information and then trying to find the
>> best match block device?
>>
>> If it's the former, I don't really understand the need for a
>> backlink since the PCI address gives you a link to the block device.
>> OTOH, if it's the later, it would make sense but then your
>> description doesn't really make much sense.
>>
>> At any rate, a better commit message would be helpful in explaining
>> the need for this.
>>
>> Regards,
>>
>> Anthony Liguori
>>
> OK just to clarify: we get pci address from BIOS
> and need the virtio device to get at the linux device
> (e.g. block) in the end. Thus the link from pci to virtio.
> I also added a backlink since I thought it's handy.
>
> Does this answer the questions?
>
> Rusty rewrites my commit logs anyway, he has better style :)
>
It helps. The real reason this is needed is because in a normal device,
there is only one struct device whereas with virtio-pci, the virtio-pci
device has a struct device and then the actual virtio device has another
one. There's probably a better way to handle this in sysfs making
virtio-pci a proper bus with only a single device as a child or
something like that.
But the links are probably an easier solution.
Regards,
Anthony Liguori
>
>>> Supply softlinks between these to make it possible.
>>>
>>> Signed-off-by: Michael S. Tsirkin<mst@redhat.com>
>>> ---
>>>
>>> Gleb, could you please ack that this patch below
>>> will be enough to fix the installer issue that
>>> you see?
>>>
>>> drivers/virtio/virtio_pci.c | 18 +++++++++++++++++-
>>> 1 files changed, 17 insertions(+), 1 deletions(-)
>>>
>>> diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
>>> index ef8d9d5..06eb2f8 100644
>>> --- a/drivers/virtio/virtio_pci.c
>>> +++ b/drivers/virtio/virtio_pci.c
>>> @@ -25,6 +25,7 @@
>>> #include<linux/virtio_pci.h>
>>> #include<linux/highmem.h>
>>> #include<linux/spinlock.h>
>>> +#include<linux/sysfs.h>
>>>
>>> MODULE_AUTHOR("Anthony Liguori<aliguori@us.ibm.com>");
>>> MODULE_DESCRIPTION("virtio-pci");
>>> @@ -667,8 +668,21 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
>>> if (err)
>>> goto out_set_drvdata;
>>>
>>> - return 0;
>>> + err = sysfs_create_link(&pci_dev->dev.kobj,&vp_dev->vdev.dev.kobj,
>>> + "virtio_device");
>>> + if (err)
>>> + goto out_register_device;
>>> +
>>> + err = sysfs_create_link(&vp_dev->vdev.dev.kobj,&pci_dev->dev.kobj,
>>> + "bus_device");
>>> + if (err)
>>> + goto out_create_link;
>>>
>>> + return 0;
>>> +out_create_link:
>>> + sysfs_remove_link(&pci_dev->dev.kobj, "virtio_device");
>>> +out_register_device:
>>> + unregister_virtio_device(&vp_dev->vdev);
>>> out_set_drvdata:
>>> pci_set_drvdata(pci_dev, NULL);
>>> pci_iounmap(pci_dev, vp_dev->ioaddr);
>>> @@ -685,6 +699,8 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev)
>>> {
>>> struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
>>>
>>> + sysfs_remove_link(&vp_dev->vdev.dev.kobj, "bus_device");
>>> + sysfs_remove_link(&pci_dev->dev.kobj, "virtio_device");
>>> unregister_virtio_device(&vp_dev->vdev);
>>> }
>>>
>>>
^ permalink raw reply
* Re: [PATCH] virtio-pci: add softlinks between virtio and pci
From: Anthony Liguori @ 2011-01-05 20:06 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Jamie Lokier, Thomas Weber, linux-kernel, virtualization
In-Reply-To: <20110105193849.GB28688@redhat.com>
On 01/05/2011 01:38 PM, Michael S. Tsirkin wrote:
> On Wed, Jan 05, 2011 at 01:28:34PM -0600, Anthony Liguori wrote:
>
>> On 01/05/2011 01:17 PM, Michael S. Tsirkin wrote:
>>
>>> We sometimes need to map between the virtio device and
>>> the given pci device. One such use is OS installer that
>>> gets the boot pci device from BIOS and needs to
>>> find the relevant block device. Since it can't,
>>> installation fails.
>>>
>> I have no objection to this patch but I'm a tad confused by the description.
>>
>> I assume you mean the installer is querying the boot device via
>> int13 get driver parameters such that it returns the pci address of
>> the device?
>>
>> Or is it querying geometry information and then trying to find the
>> best match block device?
>>
> I think it's the former.
>
>
>> If it's the former, I don't really understand the need for a
>> backlink since the PCI address gives you a link to the block device.
>>
> It does? How does it?
>
Okay, after some more discussion, I think I better understand what's
going on here.
The installer needs to figure out the boot device. It does this by
querying the BIOS and the BIOS can only give it back a PCI address.
Right now, if you follow the PCI sysfs path, you cannot reach the actual
virtio device because the PCI device only refers to the bus. This is
because virtio has a separate struct device than the PCI struct device.
These explicit links establish the relationship.
A lot of this would be cleaner if virtio didn't force an independent
struct device and could simply make use of an already existing struct
device.
Regards,
Anthony Liguori
>
>> OTOH, if it's the later, it would make sense but then your
>> description doesn't really make much sense.
>>
>> At any rate, a better commit message would be helpful in explaining
>> the need for this.
>>
>> Regards,
>>
>> Anthony Liguori
>>
>>
>>> Supply softlinks between these to make it possible.
>>>
>>> Signed-off-by: Michael S. Tsirkin<mst@redhat.com>
>>> ---
>>>
>>> Gleb, could you please ack that this patch below
>>> will be enough to fix the installer issue that
>>> you see?
>>>
>>> drivers/virtio/virtio_pci.c | 18 +++++++++++++++++-
>>> 1 files changed, 17 insertions(+), 1 deletions(-)
>>>
>>> diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
>>> index ef8d9d5..06eb2f8 100644
>>> --- a/drivers/virtio/virtio_pci.c
>>> +++ b/drivers/virtio/virtio_pci.c
>>> @@ -25,6 +25,7 @@
>>> #include<linux/virtio_pci.h>
>>> #include<linux/highmem.h>
>>> #include<linux/spinlock.h>
>>> +#include<linux/sysfs.h>
>>>
>>> MODULE_AUTHOR("Anthony Liguori<aliguori@us.ibm.com>");
>>> MODULE_DESCRIPTION("virtio-pci");
>>> @@ -667,8 +668,21 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
>>> if (err)
>>> goto out_set_drvdata;
>>>
>>> - return 0;
>>> + err = sysfs_create_link(&pci_dev->dev.kobj,&vp_dev->vdev.dev.kobj,
>>> + "virtio_device");
>>> + if (err)
>>> + goto out_register_device;
>>> +
>>> + err = sysfs_create_link(&vp_dev->vdev.dev.kobj,&pci_dev->dev.kobj,
>>> + "bus_device");
>>> + if (err)
>>> + goto out_create_link;
>>>
>>> + return 0;
>>> +out_create_link:
>>> + sysfs_remove_link(&pci_dev->dev.kobj, "virtio_device");
>>> +out_register_device:
>>> + unregister_virtio_device(&vp_dev->vdev);
>>> out_set_drvdata:
>>> pci_set_drvdata(pci_dev, NULL);
>>> pci_iounmap(pci_dev, vp_dev->ioaddr);
>>> @@ -685,6 +699,8 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev)
>>> {
>>> struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
>>>
>>> + sysfs_remove_link(&vp_dev->vdev.dev.kobj, "bus_device");
>>> + sysfs_remove_link(&pci_dev->dev.kobj, "virtio_device");
>>> unregister_virtio_device(&vp_dev->vdev);
>>> }
>>>
>>>
^ permalink raw reply
* Re: [PATCH] virtio-pci: add softlinks between virtio and pci
From: Michael S. Tsirkin @ 2011-01-05 20:05 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Jamie Lokier, Thomas Weber, linux-kernel, virtualization
In-Reply-To: <4D24C662.9070804@codemonkey.ws>
On Wed, Jan 05, 2011 at 01:28:34PM -0600, Anthony Liguori wrote:
> On 01/05/2011 01:17 PM, Michael S. Tsirkin wrote:
> >We sometimes need to map between the virtio device and
> >the given pci device. One such use is OS installer that
> >gets the boot pci device from BIOS and needs to
> >find the relevant block device. Since it can't,
> >installation fails.
>
> I have no objection to this patch but I'm a tad confused by the description.
>
> I assume you mean the installer is querying the boot device via
> int13 get driver parameters such that it returns the pci address of
> the device?
>
> Or is it querying geometry information and then trying to find the
> best match block device?
>
> If it's the former, I don't really understand the need for a
> backlink since the PCI address gives you a link to the block device.
> OTOH, if it's the later, it would make sense but then your
> description doesn't really make much sense.
>
> At any rate, a better commit message would be helpful in explaining
> the need for this.
>
> Regards,
>
> Anthony Liguori
OK just to clarify: we get pci address from BIOS
and need the virtio device to get at the linux device
(e.g. block) in the end. Thus the link from pci to virtio.
I also added a backlink since I thought it's handy.
Does this answer the questions?
Rusty rewrites my commit logs anyway, he has better style :)
> >Supply softlinks between these to make it possible.
> >
> >Signed-off-by: Michael S. Tsirkin<mst@redhat.com>
> >---
> >
> >Gleb, could you please ack that this patch below
> >will be enough to fix the installer issue that
> >you see?
> >
> > drivers/virtio/virtio_pci.c | 18 +++++++++++++++++-
> > 1 files changed, 17 insertions(+), 1 deletions(-)
> >
> >diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
> >index ef8d9d5..06eb2f8 100644
> >--- a/drivers/virtio/virtio_pci.c
> >+++ b/drivers/virtio/virtio_pci.c
> >@@ -25,6 +25,7 @@
> > #include<linux/virtio_pci.h>
> > #include<linux/highmem.h>
> > #include<linux/spinlock.h>
> >+#include<linux/sysfs.h>
> >
> > MODULE_AUTHOR("Anthony Liguori<aliguori@us.ibm.com>");
> > MODULE_DESCRIPTION("virtio-pci");
> >@@ -667,8 +668,21 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
> > if (err)
> > goto out_set_drvdata;
> >
> >- return 0;
> >+ err = sysfs_create_link(&pci_dev->dev.kobj,&vp_dev->vdev.dev.kobj,
> >+ "virtio_device");
> >+ if (err)
> >+ goto out_register_device;
> >+
> >+ err = sysfs_create_link(&vp_dev->vdev.dev.kobj,&pci_dev->dev.kobj,
> >+ "bus_device");
> >+ if (err)
> >+ goto out_create_link;
> >
> >+ return 0;
> >+out_create_link:
> >+ sysfs_remove_link(&pci_dev->dev.kobj, "virtio_device");
> >+out_register_device:
> >+ unregister_virtio_device(&vp_dev->vdev);
> > out_set_drvdata:
> > pci_set_drvdata(pci_dev, NULL);
> > pci_iounmap(pci_dev, vp_dev->ioaddr);
> >@@ -685,6 +699,8 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev)
> > {
> > struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
> >
> >+ sysfs_remove_link(&vp_dev->vdev.dev.kobj, "bus_device");
> >+ sysfs_remove_link(&pci_dev->dev.kobj, "virtio_device");
> > unregister_virtio_device(&vp_dev->vdev);
> > }
> >
^ permalink raw reply
* Re: [PATCH] virtio-pci: add softlinks between virtio and pci
From: Michael S. Tsirkin @ 2011-01-05 19:38 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Jamie Lokier, Thomas Weber, linux-kernel, virtualization
In-Reply-To: <4D24C662.9070804@codemonkey.ws>
On Wed, Jan 05, 2011 at 01:28:34PM -0600, Anthony Liguori wrote:
> On 01/05/2011 01:17 PM, Michael S. Tsirkin wrote:
> >We sometimes need to map between the virtio device and
> >the given pci device. One such use is OS installer that
> >gets the boot pci device from BIOS and needs to
> >find the relevant block device. Since it can't,
> >installation fails.
>
> I have no objection to this patch but I'm a tad confused by the description.
>
> I assume you mean the installer is querying the boot device via
> int13 get driver parameters such that it returns the pci address of
> the device?
>
> Or is it querying geometry information and then trying to find the
> best match block device?
I think it's the former.
> If it's the former, I don't really understand the need for a
> backlink since the PCI address gives you a link to the block device.
It does? How does it?
> OTOH, if it's the later, it would make sense but then your
> description doesn't really make much sense.
>
> At any rate, a better commit message would be helpful in explaining
> the need for this.
>
> Regards,
>
> Anthony Liguori
>
> >Supply softlinks between these to make it possible.
> >
> >Signed-off-by: Michael S. Tsirkin<mst@redhat.com>
> >---
> >
> >Gleb, could you please ack that this patch below
> >will be enough to fix the installer issue that
> >you see?
> >
> > drivers/virtio/virtio_pci.c | 18 +++++++++++++++++-
> > 1 files changed, 17 insertions(+), 1 deletions(-)
> >
> >diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
> >index ef8d9d5..06eb2f8 100644
> >--- a/drivers/virtio/virtio_pci.c
> >+++ b/drivers/virtio/virtio_pci.c
> >@@ -25,6 +25,7 @@
> > #include<linux/virtio_pci.h>
> > #include<linux/highmem.h>
> > #include<linux/spinlock.h>
> >+#include<linux/sysfs.h>
> >
> > MODULE_AUTHOR("Anthony Liguori<aliguori@us.ibm.com>");
> > MODULE_DESCRIPTION("virtio-pci");
> >@@ -667,8 +668,21 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
> > if (err)
> > goto out_set_drvdata;
> >
> >- return 0;
> >+ err = sysfs_create_link(&pci_dev->dev.kobj,&vp_dev->vdev.dev.kobj,
> >+ "virtio_device");
> >+ if (err)
> >+ goto out_register_device;
> >+
> >+ err = sysfs_create_link(&vp_dev->vdev.dev.kobj,&pci_dev->dev.kobj,
> >+ "bus_device");
> >+ if (err)
> >+ goto out_create_link;
> >
> >+ return 0;
> >+out_create_link:
> >+ sysfs_remove_link(&pci_dev->dev.kobj, "virtio_device");
> >+out_register_device:
> >+ unregister_virtio_device(&vp_dev->vdev);
> > out_set_drvdata:
> > pci_set_drvdata(pci_dev, NULL);
> > pci_iounmap(pci_dev, vp_dev->ioaddr);
> >@@ -685,6 +699,8 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev)
> > {
> > struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
> >
> >+ sysfs_remove_link(&vp_dev->vdev.dev.kobj, "bus_device");
> >+ sysfs_remove_link(&pci_dev->dev.kobj, "virtio_device");
> > unregister_virtio_device(&vp_dev->vdev);
> > }
> >
^ permalink raw reply
* Re: [PATCH] virtio-pci: add softlinks between virtio and pci
From: Anthony Liguori @ 2011-01-05 19:28 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Jamie Lokier, Thomas Weber, linux-kernel, virtualization
In-Reply-To: <20110105191711.GA27489@redhat.com>
On 01/05/2011 01:17 PM, Michael S. Tsirkin wrote:
> We sometimes need to map between the virtio device and
> the given pci device. One such use is OS installer that
> gets the boot pci device from BIOS and needs to
> find the relevant block device. Since it can't,
> installation fails.
>
I have no objection to this patch but I'm a tad confused by the description.
I assume you mean the installer is querying the boot device via int13
get driver parameters such that it returns the pci address of the device?
Or is it querying geometry information and then trying to find the best
match block device?
If it's the former, I don't really understand the need for a backlink
since the PCI address gives you a link to the block device. OTOH, if
it's the later, it would make sense but then your description doesn't
really make much sense.
At any rate, a better commit message would be helpful in explaining the
need for this.
Regards,
Anthony Liguori
> Supply softlinks between these to make it possible.
>
> Signed-off-by: Michael S. Tsirkin<mst@redhat.com>
> ---
>
> Gleb, could you please ack that this patch below
> will be enough to fix the installer issue that
> you see?
>
> drivers/virtio/virtio_pci.c | 18 +++++++++++++++++-
> 1 files changed, 17 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
> index ef8d9d5..06eb2f8 100644
> --- a/drivers/virtio/virtio_pci.c
> +++ b/drivers/virtio/virtio_pci.c
> @@ -25,6 +25,7 @@
> #include<linux/virtio_pci.h>
> #include<linux/highmem.h>
> #include<linux/spinlock.h>
> +#include<linux/sysfs.h>
>
> MODULE_AUTHOR("Anthony Liguori<aliguori@us.ibm.com>");
> MODULE_DESCRIPTION("virtio-pci");
> @@ -667,8 +668,21 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
> if (err)
> goto out_set_drvdata;
>
> - return 0;
> + err = sysfs_create_link(&pci_dev->dev.kobj,&vp_dev->vdev.dev.kobj,
> + "virtio_device");
> + if (err)
> + goto out_register_device;
> +
> + err = sysfs_create_link(&vp_dev->vdev.dev.kobj,&pci_dev->dev.kobj,
> + "bus_device");
> + if (err)
> + goto out_create_link;
>
> + return 0;
> +out_create_link:
> + sysfs_remove_link(&pci_dev->dev.kobj, "virtio_device");
> +out_register_device:
> + unregister_virtio_device(&vp_dev->vdev);
> out_set_drvdata:
> pci_set_drvdata(pci_dev, NULL);
> pci_iounmap(pci_dev, vp_dev->ioaddr);
> @@ -685,6 +699,8 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev)
> {
> struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
>
> + sysfs_remove_link(&vp_dev->vdev.dev.kobj, "bus_device");
> + sysfs_remove_link(&pci_dev->dev.kobj, "virtio_device");
> unregister_virtio_device(&vp_dev->vdev);
> }
>
>
^ permalink raw reply
* [PATCH] virtio-pci: add softlinks between virtio and pci
From: Michael S. Tsirkin @ 2011-01-05 19:17 UTC (permalink / raw)
To: Michael S. Tsirkin, Rusty Russell, Anthony Liguori, Jamie Lokier,
Thomas
We sometimes need to map between the virtio device and
the given pci device. One such use is OS installer that
gets the boot pci device from BIOS and needs to
find the relevant block device. Since it can't,
installation fails.
Supply softlinks between these to make it possible.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
Gleb, could you please ack that this patch below
will be enough to fix the installer issue that
you see?
drivers/virtio/virtio_pci.c | 18 +++++++++++++++++-
1 files changed, 17 insertions(+), 1 deletions(-)
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index ef8d9d5..06eb2f8 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -25,6 +25,7 @@
#include <linux/virtio_pci.h>
#include <linux/highmem.h>
#include <linux/spinlock.h>
+#include <linux/sysfs.h>
MODULE_AUTHOR("Anthony Liguori <aliguori@us.ibm.com>");
MODULE_DESCRIPTION("virtio-pci");
@@ -667,8 +668,21 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
if (err)
goto out_set_drvdata;
- return 0;
+ err = sysfs_create_link(&pci_dev->dev.kobj, &vp_dev->vdev.dev.kobj,
+ "virtio_device");
+ if (err)
+ goto out_register_device;
+
+ err = sysfs_create_link(&vp_dev->vdev.dev.kobj, &pci_dev->dev.kobj,
+ "bus_device");
+ if (err)
+ goto out_create_link;
+ return 0;
+out_create_link:
+ sysfs_remove_link(&pci_dev->dev.kobj, "virtio_device");
+out_register_device:
+ unregister_virtio_device(&vp_dev->vdev);
out_set_drvdata:
pci_set_drvdata(pci_dev, NULL);
pci_iounmap(pci_dev, vp_dev->ioaddr);
@@ -685,6 +699,8 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev)
{
struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
+ sysfs_remove_link(&vp_dev->vdev.dev.kobj, "bus_device");
+ sysfs_remove_link(&pci_dev->dev.kobj, "virtio_device");
unregister_virtio_device(&vp_dev->vdev);
}
--
1.7.3.2.91.g446ac
^ permalink raw reply related
* Re: [PATCH] LGUEST_GUEST: fix unmet direct dependencies (VIRTUALIZATION && VIRTIO)
From: Rusty Russell @ 2011-01-04 2:12 UTC (permalink / raw)
To: Randy Dunlap
Cc: Toralf Förster, lguest-uLR06cmDAlY/bJ5BZ2RsiQ,
virtualization-qjLDD68F18O7TbgM5vRIOg
In-Reply-To: <20110101110846.6a88bf7e.rdunlap-/UHa2rfvQTnk1uMJSBkQmQ@public.gmane.org>
On Sun, 2 Jan 2011 05:38:46 am Randy Dunlap wrote:
> From: Randy Dunlap <randy.dunlap-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
>
> Honor the kconfig menu hierarchy to remove kconfig dependency warnings:
> VIRTIO and VIRTIO_RING are subordinate to VIRTUALIZATION.
>
> warning: (LGUEST_GUEST) selects VIRTIO which has unmet direct dependencies (VIRTUALIZATION)
> warning: (LGUEST_GUEST && VIRTIO_PCI && VIRTIO_BALLOON) selects VIRTIO_RING which has unmet direct dependencies (VIRTUALIZATION && VIRTIO)
>
> Reported-by: Toralf F_rster <toralf.foerster-Mmb7MZpHnFY@public.gmane.org>
> Signed-off-by: Randy Dunlap <randy.dunlap-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
Thanks, applied!
Rusty.
^ permalink raw reply
* Reminder: ICAC2011 deadline is in 1 week (8th International Conference on Autonomic Computing)
From: Ming Zhao @ 2011-01-03 4:14 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:
-------
* Reminder: Submission deadline is in one week (January 8th, 2011)
* 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
* [PATCH] LGUEST_GUEST: fix unmet direct dependencies (VIRTUALIZATION && VIRTIO)
From: Randy Dunlap @ 2011-01-01 19:08 UTC (permalink / raw)
To: Toralf Förster, Rusty Russell; +Cc: virtualization, lguest
In-Reply-To: <201012271242.53835.toralf.foerster@gmx.de>
From: Randy Dunlap <randy.dunlap@oracle.com>
Honor the kconfig menu hierarchy to remove kconfig dependency warnings:
VIRTIO and VIRTIO_RING are subordinate to VIRTUALIZATION.
warning: (LGUEST_GUEST) selects VIRTIO which has unmet direct dependencies (VIRTUALIZATION)
warning: (LGUEST_GUEST && VIRTIO_PCI && VIRTIO_BALLOON) selects VIRTIO_RING which has unmet direct dependencies (VIRTUALIZATION && VIRTIO)
Reported-by: Toralf F_rster <toralf.foerster@gmx.de>
Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
---
arch/x86/lguest/Kconfig | 1 +
1 file changed, 1 insertion(+)
--- linux-next-20101231.orig/arch/x86/lguest/Kconfig
+++ linux-next-20101231/arch/x86/lguest/Kconfig
@@ -2,6 +2,7 @@ config LGUEST_GUEST
bool "Lguest guest support"
select PARAVIRT
depends on X86_32
+ select VIRTUALIZATION
select VIRTIO
select VIRTIO_RING
select VIRTIO_CONSOLE
^ permalink raw reply
* unmet direct dependencies (VIRTUALIZATION && VIRTIO)
From: Toralf Förster @ 2010-12-27 11:42 UTC (permalink / raw)
To: virtualization
Hello,
a "make randconfig 1>/dev/null" gave today :
warning: (LGUEST_GUEST && PARAVIRT_GUEST && X86_32 || VIRTIO_PCI && VIRTUALIZATION && PCI && EXPERIMENTAL || VIRTIO_BALLOON &&
VIRTUALIZATION) selects VIRTIO which has unmet direct dependencies (VIRTUALIZATION)
warning: (GPIO_VX855 && GPIOLIB) selects MFD_VX855 which has unmet direct dependencies (MFD_SUPPORT && PCI)
warning: (LGUEST_GUEST && PARAVIRT_GUEST && X86_32 || VIRTIO_PCI && VIRTUALIZATION && PCI && EXPERIMENTAL || VIRTIO_BALLOON &&
VIRTUALIZATION) selects VIRTIO_RING which has unmet direct dependencies (VIRTUALIZATION && VIRTIO)
for the current git kernel sources.
Is this an already known issue ?
--
MfG/Kind regards
Toralf Förster
pgp finger print: 7B1A 07F4 EC82 0F90 D4C2 8936 872A E508 7DB6 9DA3
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* unable to write into Local APIC registers
From: Ravi Kumar Kulkarni @ 2010-12-21 13:23 UTC (permalink / raw)
To: virtualization, kvm
Hi all,
Im using qemu 0.12.3 .I have come to a point where i have developed a
small kernel (setting up the IDT, GDT n all)
Im disabling 8259 and enabling Local APIC but im unable to write into
Local APIC registers . can anyone tell me is there something which im
missing
?
Here is my piece of code
SVR EQU 0FEE000F0H ; define the Spurious interrupt vector
APIC_ENABLE EQU 100H
;disable 8259
MOV AL,0FFH
OUT 0A1H, AL
OUT 021H, AL
;enable local apic and set the spurious interrupt vector
MOV ESI,SVR
MOV EAX,<ESI>
OR EAX,APIC_ENABLE
MOV <ESI>,EAX
Warm regards,
Ravi Kulkarni.
^ permalink raw reply
* SNAPI 2011 CFP: 7th IEEE International Workshop on Storage Network Architecture and Parallel I/Os
From: Ming Zhao @ 2010-12-20 3:05 UTC (permalink / raw)
[Just a gentle reminder that the deadline is less than two months away;
Apologies if you receive multiple copies of this announcement]
========================================================================
Call for Papers
7th IEEE International Workshop on
Storage Network Architecture and Parallel I/Os
(SNAPI 2011)
http://snapi2011.cis.fiu.edu
May 25, 2011 Denver, Colorado, USA
In conjunction with the 27th IEEE Conference on
Mass Storage Systems and Technologies (MSST 2011)
========================================================================
SCOPE:
------
The 7th IEEE Storage Networking Architecture and Parallel I/O (SNAPI
2011) Workshop aims to highlight the latest research in the
architecture, design, implementation, and evaluation of local and
networked storage and parallel I/O systems. The workshop is co-located
with the 27th IEEE Conference on Mass Storage Systems and Technologies
(MSST2011) that features a full week dedicated to "all things storage".
The SNAPI 2011 workshop, held in the middle of the MSST week, will
feature a full day of technical papers that showcase the latest work
from the academia, the labs, and the industry.
This year we would like to encourage a variety of submissions including
novel idea papers, real system experience papers, as well as analysis
and evaluation papers. Topics of interest include, but are not limited
to:
* Caching, replication, and consistency
* Energy-efficient storage
* Evaluation of networked storage architectures
* Experiences with real systems
* File and block based network storage
* Integration and evaluation of emerging storage technology
* I/O quality of service
* New abstractions/protocols for data, storage, and I/O
* Parallel I/O
* Performance, scalability, and manageability of networked storage
* SSD-based storage architectures and tiered storage
* Storage device and workload characterization
* Storage networking
* Storage reliability and failure management
* Storage virtualization
* Thin provisioning, consolidation, compression, and deduplication
* Wide-area networked storage
SUBMISSIONS INSTRUCTIONS:
-------------------------
Submissions should not exceed 8 single-space pages including all text,
figures, and references. Submissions must be typeset as double-column
text, using no less than 10 pt font, and using a text block that does
not exceed 6.5" width and 9" height.
The reviewing is double-blind. Authors must not be identified in the
submission either directly or indirectly. Please be careful so as to not
refer to your own work in the first person or leak authorship in any way
within the text of the paper. Reviewing will be performed by the members
of the SNAPI’11 Program Committee. Each paper will receive at least
three reviews from members of the Program Committee.
The final version of the paper prepared after incorporating reviewer
feedback should be submitted by April 1st, 2011. At least one author of
each accepted paper will be expected to attend the workshop and present
their work in a 25 minute talk.
BEST PAPER AWARD:
-----------------
Authors of the best paper, chosen by the Program Committee, will be
presented an award at the workshop.
Important dates:
----------------
* Full paper submission: January 28, 2011
* Notification of acceptance: March 4, 2011
* Final manuscripts due: April 1, 2011
* Workshop: May 25, 2011
Organization:
-------------
* Program Chair:
o Raju Rangaswami, Florida International University
* Program Committee:
o Angelos Bilas, FORTH and University of Crete
o Randal Burns, Johns Hopkins University
o Dan Feng, Huazhong University of Science and Technology
o Dirk Grunwald, University of Colorado, Boulder
o Ajay Gulati, VMware
o Ron Oldfield, Sandia National Laboratory
o Vijayan Prabhakaran, Microsoft Research
o Himabindu Pucha, IBM Research - Almaden
o A. L. Narasimha Reddy, Texas A&M University
o Alma Riska, College of William and Mary
o Philip Roth, Oak Ridge National Laboratory
o Jiri Schindler, NetApp
o Rajeev Thakur, Argonne National Laboratory
o Bhuvan Urgaonkar, Pennsylvania State University
o Youjip Won, Hanyang University
o Ming Zhao, Florida International University
* Web and Publicity Chair:
o Ming Zhao, Florida International University
* Steering Committee:
o Qing Yang, University of Rhode Island
o Hong Jiang, University of Nebraska-Lincoln
o Xubin He, Tennessee Tech University
SPONSORSHIP:
------------
IEEE Mass Storage Systems Technical Committee (MSSTC)
Information:
------------
* SNAPI 2001 Web: http://snapi2011.cis.fiu.edu
* MSST 2011 Web: http://storageconference.org
* Email: snapi2011@cis.fiu.edu
^ permalink raw reply
* [PATCH] Staging: hv: Add code to create the device directory under /sys/block/hdx
From: Ky Srinivasan @ 2010-12-17 1:59 UTC (permalink / raw)
To: devel, Virtualization; +Cc: Haiyang Zhang, Greg KH
In-Reply-To: <1292530231-14109-1-git-send-email-ksrinivasan@novell.com>
Add code to create the device directory under sysfs.
Signed-off-by: K. Y. Srinivasan <ksrinivasan@novell.com>
---
drivers/staging/hv/blkvsc_drv.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
index b3d05fc..4fb8094 100644
--- a/drivers/staging/hv/blkvsc_drv.c
+++ b/drivers/staging/hv/blkvsc_drv.c
@@ -368,6 +368,7 @@ static int blkvsc_probe(struct device *device)
blkdev->gd->first_minor = 0;
blkdev->gd->fops = &block_ops;
blkdev->gd->private_data = blkdev;
+ blkdev->gd->driverfs_dev = &(blkdev->device_ctx->device);
sprintf(blkdev->gd->disk_name, "hd%c", 'a' + devnum);
blkvsc_do_inquiry(blkdev);
--
1.7.1
^ permalink raw reply related
* [PATCH 4/4] Staging: hv: Add a user-space daemon to support key/value pair (KVP)
From: Ky Srinivasan @ 2010-12-17 1:56 UTC (permalink / raw)
To: devel, Virtualization; +Cc: Zbr, Haiyang Zhang, Stephen Hemminger, Greg KH
In-Reply-To: <1292531122-14375-1-git-send-email-ksrinivasan@novell.com>
All guest specific data gathering is implemented in a user-mode daemon.
The kernel component of KVP passes the "key" to this daemon and
the daemon is responsible for passing back the corresponding
value. This daemon communicates with the kernel
component via a netlink channel.
Signed-off-by: K. Y. Srinivasan <ksrinivasan@novell.com>
---
drivers/staging/hv/tools/hv_kvp_daemon.c | 470 ++++++++++++++++++++++++++++++
1 files changed, 470 insertions(+), 0 deletions(-)
create mode 100644 drivers/staging/hv/tools/hv_kvp_daemon.c
diff --git a/drivers/staging/hv/tools/hv_kvp_daemon.c b/drivers/staging/hv/tools/hv_kvp_daemon.c
new file mode 100644
index 0000000..f5a2dd6
--- /dev/null
+++ b/drivers/staging/hv/tools/hv_kvp_daemon.c
@@ -0,0 +1,470 @@
+/*
+ * An implementation of key value pair (KVP) functionality for Linux.
+ *
+ *
+ * Copyright (C) 2010, Novell, Inc.
+ * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <sys/utsname.h>
+#include <linux/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <linux/connector.h>
+#include <linux/netlink.h>
+#include <sys/socket.h>
+#include <ifaddrs.h>
+#include <netdb.h>
+#include <syslog.h>
+
+/*
+ * KYS: TODO. Need to register these in the kernel.
+ *
+ * The following definitions are shared with the in-kernel component; do not
+ * change any of this without making the corresponding changes in
+ * the KVP kernel component.
+ */
+#define CN_KVP_IDX 0x9 /* MSFT KVP functionality */
+#define CN_KVP_VAL 0x1 /* This supports queries from the kernel */
+#define CN_KVP_USER_VAL 0x2 /* This supports queries from the user */
+
+/*
+ * KVP protocol: The user mode component first registers with the
+ * the kernel component. Subsequently, the kernel component requests, data
+ * for the specified keys. In response to this message the user mode component
+ * fills in the value corresponding to the specified key. We overload the
+ * sequence field in the cn_msg header to define our KVP message types.
+ *
+ * We use this infrastructure for also supporting queries from user mode
+ * application for state that may be maintained in the KVP kernel component.
+ *
+ * XXXKYS: Have a shared header file between the user and kernel (TODO)
+ */
+
+enum kvp_op {
+ KVP_REGISTER = 0, /* Register the user mode component*/
+ KVP_KERNEL_GET, /*Kernel is requesting the value for the specified key*/
+ KVP_KERNEL_SET, /*Kernel is providing the value for the specified key*/
+ KVP_USER_GET, /*User is requesting the value for the specified key*/
+ KVP_USER_SET /*User is providing the value for the specified key*/
+};
+
+#define HV_KVP_EXCHANGE_MAX_KEY_SIZE 512
+#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE 2048
+
+struct hv_ku_msg {
+ __u32 kvp_index;
+ __u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */
+ __u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key value */
+};
+
+enum key_index {
+ FullyQualifiedDomainName = 0,
+ IntegrationServicesVersion, /*This key is serviced in the kernel*/
+ NetworkAddressIPv4,
+ NetworkAddressIPv6,
+ OSBuildNumber,
+ OSName,
+ OSMajorVersion,
+ OSMinorVersion,
+ OSVersion,
+ ProcessorArchitecture
+};
+
+/*
+ * End of shared definitions.
+ */
+
+static char kvp_send_buffer[4096];
+static char kvp_recv_buffer[4096];
+static struct sockaddr_nl addr;
+
+static char os_name[100];
+static char os_major[50];
+static char os_minor[50];
+static char processor_arch[50];
+static char os_build[100];
+static char *lic_version;
+
+void kvp_get_os_info(void)
+{
+ FILE *file;
+ char *eol;
+ struct utsname buf;
+
+ uname(&buf);
+ strcpy(os_build, buf.release);
+ strcpy(processor_arch, buf.machine);
+
+ file = fopen("/etc/SuSE-release", "r");
+ if (file != NULL)
+ goto kvp_osinfo_found;
+ file = fopen("/etc/redhat-release", "r");
+ if (file != NULL)
+ goto kvp_osinfo_found;
+ /*
+ * Add code for other supported platforms.
+ */
+
+ /*
+ * We don't have information about the os.
+ */
+ strcpy(os_name, "Linux");
+ strcpy(os_major, "0");
+ strcpy(os_minor, "0");
+ return;
+
+kvp_osinfo_found:
+ fgets(os_name, 99, file);
+ eol = index(os_name, '\n');
+ *eol = '\0';
+ fgets(os_major, 49, file);
+ eol = index(os_major, '\n');
+ *eol = '\0';
+ fgets(os_minor, 49, file);
+ eol = index(os_minor, '\n');
+ *eol = '\0';
+ fclose(file);
+ return;
+}
+
+static int
+kvp_get_ip_address(int family, char *buffer, int length)
+{
+ struct ifaddrs *ifap;
+ struct ifaddrs *curp;
+ int ipv4_len = strlen("255.255.255.255") + 1;
+ int ipv6_len = strlen("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")+1;
+ int offset = 0;
+ const char *str;
+ char tmp[50];
+ int error = 0;
+
+ /*
+ * On entry into this function, the buffer is capable of holding the
+ * maximum key value (2048 bytes).
+ */
+
+ if (getifaddrs(&ifap)) {
+ strcpy(buffer, "getifaddrs failed\n");
+ return 1;
+ }
+
+ curp = ifap;
+ while (curp != NULL) {
+ if ((curp->ifa_addr != NULL) &&
+ (curp->ifa_addr->sa_family == family)) {
+ if (family == AF_INET) {
+ struct sockaddr_in *addr =
+ (struct sockaddr_in *) curp->ifa_addr;
+
+ str = inet_ntop(family, &addr->sin_addr,
+ tmp, 50);
+ if (str == NULL) {
+ strcpy(buffer, "inet_ntop failed\n");
+ error = 1;
+ goto getaddr_done;
+ }
+ if (offset == 0)
+ strcpy(buffer, tmp);
+ else
+ strcat(buffer, tmp);
+ strcat(buffer, ";");
+
+ offset += strlen(str) + 1;
+ if ((length - offset) < (ipv4_len + 1))
+ goto getaddr_done;
+
+ } else {
+
+ /*
+ * We only support AF_INET and AF_INET6
+ * and the list of addresses is seperated by a ";".
+ */
+ struct sockaddr_in6 *addr =
+ (struct sockaddr_in6 *) curp->ifa_addr;
+
+ str = inet_ntop(family,
+ &addr->sin6_addr.s6_addr,
+ tmp, 50);
+ if (str == NULL) {
+ strcpy(buffer, "inet_ntop failed\n");
+ error = 1;
+ goto getaddr_done;
+ }
+ if (offset == 0)
+ strcpy(buffer, tmp);
+ else
+ strcat(buffer, tmp);
+ strcat(buffer, ";");
+ offset += strlen(str) + 1;
+ if ((length - offset) < (ipv6_len + 1))
+ goto getaddr_done;
+
+ }
+
+ }
+ curp = curp->ifa_next;
+ }
+
+getaddr_done:
+ freeifaddrs(ifap);
+ return error;
+}
+
+
+static int
+kvp_get_domain_name(char *buffer, int length)
+{
+ struct addrinfo hints, *info ;
+ gethostname(buffer, length);
+ int error = 0;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET; /*Get only ipv4 addrinfo. */
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_CANONNAME;
+
+ error = getaddrinfo(buffer, "http", &hints, &info);
+ if (error != 0) {
+ strcpy(buffer, "getaddrinfo failed\n");
+ error = 1;
+ goto get_domain_done;
+ }
+ strcpy(buffer, info->ai_canonname);
+get_domain_done:
+ freeaddrinfo(info);
+ return error;
+}
+
+static int
+netlink_send(int fd, struct cn_msg *msg)
+{
+ struct nlmsghdr *nlh;
+ unsigned int size;
+ struct msghdr message;
+ char buffer[64];
+ struct iovec iov[2];
+
+ size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len);
+
+ nlh = (struct nlmsghdr *)buffer;
+ nlh->nlmsg_seq = 0;
+ nlh->nlmsg_pid = getpid();
+ nlh->nlmsg_type = NLMSG_DONE;
+ nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh));
+ nlh->nlmsg_flags = 0;
+
+ iov[0].iov_base = nlh;
+ iov[0].iov_len = sizeof(*nlh);
+
+ iov[1].iov_base = msg;
+ iov[1].iov_len = size;
+
+ memset(&message, 0, sizeof(message));
+ message.msg_name = &addr;
+ message.msg_namelen = sizeof(addr);
+ message.msg_iov = iov;
+ message.msg_iovlen = 2;
+
+ return sendmsg(fd, &message, 0);
+}
+
+main(void)
+{
+ int fd, len, sock_opt;
+ int error;
+ struct cn_msg *message;
+ struct pollfd pfd;
+ struct nlmsghdr *incoming_msg;
+ struct cn_msg *incoming_cn_msg;
+ char *key_value;
+ char *key_name;
+ int key_index;
+
+ daemon(1, 0);
+ openlog("KVP", 0, LOG_USER);
+ syslog(LOG_INFO, "KVP starting; pid is:%d", getpid());
+ /*
+ * Retrieve OS release information.
+ */
+ kvp_get_os_info();
+
+ fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
+ if (fd < 0) {
+ syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd);
+ exit(-1);
+ }
+ addr.nl_family = AF_NETLINK;
+ addr.nl_pad = 0;
+ addr.nl_pid = 0;
+ addr.nl_groups = CN_KVP_IDX;
+
+
+ error = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
+ if (error < 0) {
+ syslog(LOG_ERR, "bind failed; error:%d", error);
+ close(fd);
+ exit(-1);
+ }
+ sock_opt = addr.nl_groups;
+ setsockopt(fd, 270, 1, &sock_opt, sizeof(sock_opt));
+ /*
+ * Register ourselves with the kernel.
+ */
+ message = (struct cn_msg *)kvp_send_buffer;
+ message->id.idx = CN_KVP_IDX;
+ message->id.val = CN_KVP_VAL;
+ message->seq = KVP_REGISTER;
+ message->ack = 0;
+ message->len = 0;
+
+ len = netlink_send(fd, message);
+ if (len < 0) {
+ syslog(LOG_ERR, "netlink_send failed; error:%d", len);
+ close(fd);
+ exit(-1);
+ }
+
+ pfd.fd = fd;
+
+ while (1) {
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+ poll(&pfd, 1, -1);
+
+ len = recv(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0);
+
+ if (len < 0) {
+ syslog(LOG_ERR, "recv failed; error:%d", len);
+ close(fd);
+ return -1;
+ }
+
+ incoming_msg = (struct nlmsghdr *)kvp_recv_buffer;
+ incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);
+
+ switch (incoming_cn_msg->seq) {
+ case KVP_REGISTER:
+ /*
+ * Driver is registering with us; stash away the version
+ * information.
+ */
+ lic_version = malloc(strlen(incoming_cn_msg->data) + 1);
+ if (lic_version) {
+ strcpy(lic_version, incoming_cn_msg->data);
+ syslog(LOG_INFO, "KVP LIC Version: %s",
+ lic_version);
+ } else {
+ syslog(LOG_ERR, "malloc failed");
+ }
+ continue;
+
+ case KVP_KERNEL_GET:
+ break;
+ default:
+ continue;
+ }
+
+ key_index =
+ ((struct hv_ku_msg *)incoming_cn_msg->data)->kvp_index;
+ key_name =
+ ((struct hv_ku_msg *)incoming_cn_msg->data)->kvp_key;
+ key_value =
+ ((struct hv_ku_msg *)incoming_cn_msg->data)->kvp_value;
+
+ switch (key_index) {
+ case FullyQualifiedDomainName:
+ kvp_get_domain_name(key_value,
+ HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
+ strcpy(key_name, "FullyQualifiedDomainName");
+ break;
+ case IntegrationServicesVersion:
+ strcpy(key_name, "IntegrationServicesVersion");
+ strcpy(key_value, lic_version);
+ break;
+ case NetworkAddressIPv4:
+ kvp_get_ip_address(AF_INET, key_value,
+ HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
+ strcpy(key_name, "NetworkAddressIPv4");
+ break;
+ case NetworkAddressIPv6:
+ kvp_get_ip_address(AF_INET6, key_value,
+ HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
+ strcpy(key_name, "NetworkAddressIPv6");
+ break;
+ case OSBuildNumber:
+ strcpy(key_value, os_build);
+ strcpy(key_name, "OSBuildNumber");
+ break;
+ case OSName:
+ strcpy(key_value, os_name);
+ strcpy(key_name, "OSName");
+ break;
+ case OSMajorVersion:
+ strcpy(key_value, os_major);
+ strcpy(key_name, "OSMajorVersion");
+ break;
+ case OSMinorVersion:
+ strcpy(key_value, os_minor);
+ strcpy(key_name, "OSMinorVersion");
+ break;
+ case OSVersion:
+ strcpy(key_value, os_build);
+ strcpy(key_name, "OSVersion");
+ break;
+ case ProcessorArchitecture:
+ strcpy(key_value, processor_arch);
+ strcpy(key_name, "ProcessorArchitecture");
+ break;
+ default:
+ strcpy(key_value, "Unknown Key");
+ /*
+ * We use a null key name to terminate enumeration.
+ */
+ strcpy(key_name, "");
+ break;
+ }
+ /*
+ * Send the value back to the kernel. The response is
+ * already in the receive buffer. Update the cn_msg header to
+ * reflect the key value that has been added to the message
+ */
+
+ incoming_cn_msg->id.idx = CN_KVP_IDX;
+ incoming_cn_msg->id.val = CN_KVP_VAL;
+ incoming_cn_msg->seq = KVP_USER_SET;
+ incoming_cn_msg->ack = 0;
+ incoming_cn_msg->len = sizeof(struct hv_ku_msg);
+
+ len = netlink_send(fd, incoming_cn_msg);
+ if (len < 0) {
+ syslog(LOG_ERR, "net_link send failed; error:%d", len);
+ exit(-1);
+ }
+ }
+
+}
--
1.7.1
^ permalink raw reply related
* [PATCH 3/4] Staging: hv: Implement key/value pair (KVP)
From: Ky Srinivasan @ 2010-12-17 1:54 UTC (permalink / raw)
To: devel, Virtualization; +Cc: Zbr, Haiyang Zhang, Stephen Hemminger, Greg KH
In-Reply-To: <1292531082-14337-1-git-send-email-ksrinivasan@novell.com>
This is an implementation of the key value/pair (KVP) functionality
for Linux guests hosted on HyperV. This component communicates
with the host to support the KVP functionality.
Signed-off-by: K. Y. Srinivasan <ksrinivasan@novell.com>
---
drivers/staging/hv/Makefile | 2 +-
drivers/staging/hv/channel_mgmt.c | 23 +++-
drivers/staging/hv/hv_kvp.c | 346 +++++++++++++++++++++++++++++++++++++
drivers/staging/hv/hv_kvp.h | 184 ++++++++++++++++++++
drivers/staging/hv/hv_util.c | 14 ++
drivers/staging/hv/utils.h | 1 +
6 files changed, 567 insertions(+), 3 deletions(-)
create mode 100644 drivers/staging/hv/hv_kvp.c
create mode 100644 drivers/staging/hv/hv_kvp.h
diff --git a/drivers/staging/hv/Makefile b/drivers/staging/hv/Makefile
index 4c14138..606ce7d 100644
--- a/drivers/staging/hv/Makefile
+++ b/drivers/staging/hv/Makefile
@@ -10,4 +10,4 @@ hv_vmbus-y := vmbus_drv.o osd.o \
hv_storvsc-y := storvsc_drv.o storvsc.o
hv_blkvsc-y := blkvsc_drv.o blkvsc.o
hv_netvsc-y := netvsc_drv.o netvsc.o rndis_filter.o
-hv_utils-y := hv_util.o
+hv_utils-y := hv_util.o hv_kvp.o
diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c
index 0f4d609..375f164 100644
--- a/drivers/staging/hv/channel_mgmt.c
+++ b/drivers/staging/hv/channel_mgmt.c
@@ -34,8 +34,8 @@ struct vmbus_channel_message_table_entry {
void (*messageHandler)(struct vmbus_channel_message_header *msg);
};
-#define MAX_MSG_TYPES 3
-#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 7
+#define MAX_MSG_TYPES 4
+#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8
static const struct hv_guid
gSupportedDeviceClasses[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = {
@@ -98,6 +98,15 @@ static const struct hv_guid
0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d
}
},
+ /* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */
+ /* KVP */
+ {
+ .data = {
+ 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
+ 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6
+ }
+ },
+
};
@@ -231,6 +240,16 @@ struct hyperv_service_callback hv_cb_utils[MAX_MSG_TYPES] = {
.callback = chn_cb_negotiate,
.log_msg = "Heartbeat channel functionality initialized"
},
+ /* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */
+ /* KVP */
+ {
+ .data = {
+ 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
+ 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6
+ },
+ .callback = chn_cb_negotiate,
+ .log_msg = "KVP channel functionality initialized"
+ },
};
EXPORT_SYMBOL(hv_cb_utils);
diff --git a/drivers/staging/hv/hv_kvp.c b/drivers/staging/hv/hv_kvp.c
new file mode 100644
index 0000000..5458631
--- /dev/null
+++ b/drivers/staging/hv/hv_kvp.c
@@ -0,0 +1,346 @@
+/*
+ * An implementation of key value pair (KVP) functionality for Linux.
+ *
+ *
+ * Copyright (C) 2010, Novell, Inc.
+ * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+
+#include <linux/net.h>
+#include <linux/nls.h>
+#include <linux/connector.h>
+#include <linux/workqueue.h>
+
+#include "logging.h"
+#include "osd.h"
+#include "vmbus.h"
+#include "vmbus_packet_format.h"
+#include "vmbus_channel_interface.h"
+#include "version_info.h"
+#include "channel.h"
+#include "vmbus_private.h"
+#include "vmbus_api.h"
+#include "utils.h"
+#include "hv_kvp.h"
+
+
+
+/*
+ * Global state maintained for transaction that is being processed.
+ * Note that only one transaction can be active at any point in time.
+ *
+ * This state is set when we receive a request from the host; we
+ * cleanup this state when the transaction is completed - when we respond
+ * to the host with the key value.
+ */
+
+static struct {
+ bool active; /* transaction status - active or not */
+ int recv_len; /* number of bytes received. */
+ struct vmbus_channel *recv_channel; /* chn we got the request */
+ u64 recv_req_id; /* request ID. */
+} kvp_transaction;
+
+static int kvp_send_key(int index);
+
+static void kvp_respond_to_host(char *key, char *value, int error);
+static void kvp_work_func(struct work_struct *dummy);
+static void kvp_register(void);
+
+static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func);
+
+static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL };
+static const char kvp_name[] = "kvp_kernel_module";
+static int timeout_fired;
+static u8 *recv_buffer;
+/*
+ * Register the kernel component with the user-level daemon.
+ * As part of this registration, pass the LIC version number.
+ */
+
+static void
+kvp_register(void)
+{
+
+ struct cn_msg *msg;
+
+ msg = kzalloc(sizeof(*msg) + strlen(HV_DRV_VERSION) + 1 , GFP_ATOMIC);
+
+ if (msg) {
+ msg->id.idx = CN_KVP_IDX;
+ msg->id.val = CN_KVP_VAL;
+ msg->seq = KVP_REGISTER;
+ strcpy(msg->data, HV_DRV_VERSION);
+ msg->len = strlen(HV_DRV_VERSION) + 1;
+ cn_netlink_send(msg, 0, GFP_ATOMIC);
+ kfree(msg);
+ }
+}
+static void
+kvp_work_func(struct work_struct *dummy)
+{
+ /*
+ * If the timer fires, the user-mode component has not responded;
+ * process the pending transaction.
+ */
+ kvp_respond_to_host("Unknown key", "Guest timed out", timeout_fired);
+ timeout_fired = 1;
+}
+
+/*
+ * Callback when data is received from user mode.
+ */
+
+static void
+kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
+{
+ struct hv_ku_msg *message;
+
+ message = (struct hv_ku_msg *)msg->data;
+ if (msg->seq == KVP_REGISTER) {
+ printk(KERN_INFO "KVP: user-mode registering done.\n");
+ kvp_register();
+ }
+
+ if (msg->seq == KVP_USER_SET) {
+ /*
+ * Complete the transaction by forwarding the key value
+ * to the host. But first, cancel the timeout.
+ */
+ if (cancel_delayed_work_sync(&kvp_work))
+ kvp_respond_to_host(message->kvp_key,
+ message->kvp_value,
+ !strlen(message->kvp_key));
+ }
+}
+
+static int
+kvp_send_key(int index)
+{
+ struct cn_msg *msg;
+
+ msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC);
+
+ if (msg) {
+ msg->id.idx = CN_KVP_IDX;
+ msg->id.val = CN_KVP_VAL;
+ msg->seq = KVP_KERNEL_GET;
+ ((struct hv_ku_msg *)msg->data)->kvp_index = index;
+ msg->len = sizeof(struct hv_ku_msg);
+ cn_netlink_send(msg, 0, GFP_ATOMIC);
+ kfree(msg);
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Send a response back to the host.
+ */
+
+static void
+kvp_respond_to_host(char *key, char *value, int error)
+{
+ struct hv_kvp_msg *kvp_msg;
+ struct hv_kvp_msg_enumerate *kvp_data;
+ char *key_name;
+ struct icmsg_hdr *icmsghdrp;
+ int keylen, valuelen;
+ u32 buf_len;
+ struct vmbus_channel *channel;
+ u64 req_id;
+
+ /*
+ * If a transaction is not active; log and return.
+ */
+
+ if (!kvp_transaction.active) {
+ /*
+ * This is a spurious call!
+ */
+ printk(KERN_WARNING "KVP: Transaction not active\n");
+ return;
+ }
+ /*
+ * Copy the global state for completing the transaction. Note that
+ * only one transaction can be active at a time.
+ */
+
+ buf_len = kvp_transaction.recv_len;
+ channel = kvp_transaction.recv_channel;
+ req_id = kvp_transaction.recv_req_id;
+
+ icmsghdrp = (struct icmsg_hdr *)
+ &recv_buffer[sizeof(struct vmbuspipe_hdr)];
+ kvp_msg = (struct hv_kvp_msg *)
+ &recv_buffer[sizeof(struct vmbuspipe_hdr) +
+ sizeof(struct icmsg_hdr)];
+ kvp_data = &kvp_msg->kvp_data;
+ key_name = key;
+
+ /*
+ * If the error parameter is set, terminate the host's enumeration.
+ */
+ if (error) {
+ /*
+ * We don't support this index or the we have timedout;
+ * terminate the host-side iteration by returning an error.
+ */
+ icmsghdrp->status = HV_E_FAIL;
+ goto response_done;
+ }
+
+ /*
+ * The windows host expects the key/value pair to be encoded
+ * in utf16.
+ */
+ keylen = utf8s_to_utf16s(key_name, strlen(key_name),
+ (wchar_t *)kvp_data->data.key);
+ kvp_data->data.key_size = 2*(keylen + 1); /* utf16 encoding */
+ valuelen = utf8s_to_utf16s(value, strlen(value),
+ (wchar_t *)kvp_data->data.value);
+ kvp_data->data.value_size = 2*(valuelen + 1); /* utf16 encoding */
+
+ kvp_data->data.value_type = REG_SZ; /* all our values are strings */
+ icmsghdrp->status = HV_S_OK;
+
+response_done:
+ icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
+
+ vmbus_sendpacket(channel, recv_buffer, buf_len, req_id,
+ VmbusPacketTypeDataInBand, 0);
+
+ kvp_transaction.active = false;
+}
+
+/*
+ * This callback is invoked when we get a KVP message from the host.
+ * The host ensures that only one KVP transaction can be active at a time.
+ * KVP implementation in Linux needs to forward the key to a user-mde
+ * component to retrive the corresponding value. Consequently, we cannot
+ * respond to the host in the conext of this callback. Since the host
+ * guarantees that at most only one transaction can be active at a time,
+ * we stash away the transaction state in a set of global variables.
+ */
+
+void hv_kvp_onchannelcallback(void *context)
+{
+ struct vmbus_channel *channel = context;
+ u32 recvlen;
+ u64 requestid;
+
+ struct hv_kvp_msg *kvp_msg;
+ struct hv_kvp_msg_enumerate *kvp_data;
+
+ struct icmsg_hdr *icmsghdrp;
+ struct icmsg_negotiate *negop = NULL;
+
+
+ if (kvp_transaction.active)
+ return;
+
+
+ vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid);
+
+ if (recvlen > 0) {
+ DPRINT_DBG(VMBUS, "KVP packet: len=%d, requestid=%lld",
+ recvlen, requestid);
+
+ icmsghdrp = (struct icmsg_hdr *)&recv_buffer[
+ sizeof(struct vmbuspipe_hdr)];
+
+ if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+ prep_negotiate_resp(icmsghdrp, negop, recv_buffer);
+ } else {
+ kvp_msg = (struct hv_kvp_msg *)&recv_buffer[
+ sizeof(struct vmbuspipe_hdr) +
+ sizeof(struct icmsg_hdr)];
+
+ kvp_data = &kvp_msg->kvp_data;
+
+ /*
+ * We only support the "get" operation on
+ * "KVP_POOL_AUTO" pool.
+ */
+
+ if ((kvp_msg->kvp_hdr.pool != KVP_POOL_AUTO) ||
+ (kvp_msg->kvp_hdr.operation !=
+ KVP_OP_ENUMERATE)) {
+ icmsghdrp->status = HV_E_FAIL;
+ goto callback_done;
+ }
+
+ /*
+ * Stash away this global state for completing the
+ * transaction; note transactions are serialized.
+ */
+ kvp_transaction.recv_len = recvlen;
+ kvp_transaction.recv_channel = channel;
+ kvp_transaction.recv_req_id = requestid;
+ kvp_transaction.active = true;
+
+ /*
+ * Get the information from the
+ * user-mode component.
+ * component. This transaction will be
+ * completed when we get the value from
+ * the user-mode component.
+ * Set a timeout to deal with
+ * user-mode not responding.
+ */
+ kvp_send_key(kvp_data->index);
+ schedule_delayed_work(&kvp_work, 100);
+
+ return;
+
+ }
+
+callback_done:
+
+ icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+ | ICMSGHDRFLAG_RESPONSE;
+
+ vmbus_sendpacket(channel, recv_buffer,
+ recvlen, requestid,
+ VmbusPacketTypeDataInBand, 0);
+ }
+
+}
+
+int
+hv_kvp_init(void)
+{
+ int err;
+
+ err = cn_add_callback(&kvp_id, kvp_name, kvp_cn_callback);
+ if (err)
+ return err;
+ recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!recv_buffer)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void hv_kvp_deinit(void)
+{
+ cn_del_callback(&kvp_id);
+ cancel_delayed_work_sync(&kvp_work);
+ kfree(recv_buffer);
+}
diff --git a/drivers/staging/hv/hv_kvp.h b/drivers/staging/hv/hv_kvp.h
new file mode 100644
index 0000000..e069f59
--- /dev/null
+++ b/drivers/staging/hv/hv_kvp.h
@@ -0,0 +1,184 @@
+/*
+ * An implementation of HyperV key value pair (KVP) functionality for Linux.
+ *
+ *
+ * Copyright (C) 2010, Novell, Inc.
+ * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef _KVP_H
+#define _KVP_H_
+
+/*
+ * Maximum value size - used for both key names and value data, and includes
+ * any applicable NULL terminators.
+ *
+ * Note: This limit is somewhat arbitrary, but falls easily within what is
+ * supported for all native guests (back to Win 2000) and what is reasonable
+ * for the IC KVP exchange functionality. Note that Windows Me/98/95 are
+ * limited to 255 character key names.
+ *
+ * MSDN recommends not storing data values larger than 2048 bytes in the
+ * registry.
+ *
+ * Note: This value is used in defining the KVP exchange message - this value
+ * cannot be modified without affecting the message size and compatability.
+ */
+
+/*
+ * bytes, including any null terminators
+ */
+#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE (2048)
+
+
+/*
+ * Maximum key size - the registry limit for the length of an entry name
+ * is 256 characters, including the null terminator
+ */
+
+#define HV_KVP_EXCHANGE_MAX_KEY_SIZE (512)
+
+/*
+ * In Linux, we implement the KVP functionality in two components:
+ * 1) The kernel component which is packaged as part of the hv_utils driver
+ * is responsible for communicating with the host and responsible for
+ * implementing the host/guest protocol. 2) A user level daemon that is
+ * responsible for data gathering.
+ *
+ * Host/Guest Protocol: The host iterates over an index and expects the guest
+ * to assign a key name to the index and also return the value corresponding to
+ * the key. The host will have atmost one KVP transaction outstanding at any
+ * given point in time. The host side iteration stops when the guest returns
+ * an error. Microsoft has specified the following mapping of key names to
+ * host specified index:
+ *
+ * Index Key Name
+ * 0 FullyQualifiedDomainName
+ * 1 IntegrationServicesVersion
+ * 2 NetworkAddressIPv4
+ * 3 NetworkAddressIPv6
+ * 4 OSBuildNumber
+ * 5 OSName
+ * 6 OSMajorVersion
+ * 7 OSMinorVersion
+ * 8 OSVersion
+ * 9 ProcessorArchitecture
+ *
+ * The Windows host expects the Key Name and Key Value to be encoded in utf16.
+ *
+ * Guest Kernel/KVP Daemon Protocol: As noted earlier, we implement all of the
+ * data gathering functionality in a user mode daemon. The user level daemon
+ * is also responsible for binding the key name to the index as well. The
+ * kernel and user-level daemon communicate using a connector channel.
+ *
+ * The user mode component first registers with the
+ * the kernel component. Subsequently, the kernel component requests, data
+ * for the specified keys. In response to this message the user mode component
+ * fills in the value corresponding to the specified key. We overload the
+ * sequence field in the cn_msg header to define our KVP message types.
+ *
+ *
+ * The kernel component simply acts as a conduit for communication between the
+ * Windows host and the user-level daemon. The kernel component passes up the
+ * index received from the Host to the user-level daemon. If the index is
+ * valid (supported), the corresponding key as well as its
+ * value (both are strings) is returned. If the index is invalid
+ * (not supported), a NULL key string is returned.
+ */
+
+/*
+ *
+ * The following definitions are shared with the user-mode component; do not
+ * change any of this without making the corresponding changes in
+ * the KVP user-mode component.
+ */
+
+#define CN_KVP_VAL 0x1 /* This supports queries from the kernel */
+#define CN_KVP_USER_VAL 0x2 /* This supports queries from the user */
+
+enum hv_ku_op {
+ KVP_REGISTER = 0, /* Register the user mode component */
+ KVP_KERNEL_GET, /* Kernel is requesting the value */
+ KVP_KERNEL_SET, /* Kernel is providing the value */
+ KVP_USER_GET, /* User is requesting the value */
+ KVP_USER_SET /* User is providing the value */
+};
+
+struct hv_ku_msg {
+ __u32 kvp_index; /* Key index */
+ __u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */
+ __u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key value */
+};
+
+
+
+
+#ifdef __KERNEL__
+
+/*
+ * Registry value types.
+ */
+
+#define REG_SZ 1
+
+enum hv_kvp_exchg_op {
+ KVP_OP_GET = 0,
+ KVP_OP_SET,
+ KVP_OP_DELETE,
+ KVP_OP_ENUMERATE,
+ KVP_OP_COUNT /* Number of operations, must be last. */
+};
+
+enum hv_kvp_exchg_pool {
+ KVP_POOL_EXTERNAL = 0,
+ KVP_POOL_GUEST,
+ KVP_POOL_AUTO,
+ KVP_POOL_AUTO_EXTERNAL,
+ KVP_POOL_AUTO_INTERNAL,
+ KVP_POOL_COUNT /* Number of pools, must be last. */
+};
+
+struct hv_kvp_hdr {
+ u8 operation;
+ u8 pool;
+};
+
+struct hv_kvp_exchg_msg_value {
+ u32 value_type;
+ u32 key_size;
+ u32 value_size;
+ u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
+ u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
+};
+
+struct hv_kvp_msg_enumerate {
+ u32 index;
+ struct hv_kvp_exchg_msg_value data;
+};
+
+struct hv_kvp_msg {
+ struct hv_kvp_hdr kvp_hdr;
+ struct hv_kvp_msg_enumerate kvp_data;
+};
+
+int hv_kvp_init(void);
+void hv_kvp_deinit(void);
+void hv_kvp_onchannelcallback(void *);
+
+#endif /* __KERNEL__ */
+#endif /* _KVP_H */
+
diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c
index 0074581..dea0513 100644
--- a/drivers/staging/hv/hv_util.c
+++ b/drivers/staging/hv/hv_util.c
@@ -37,6 +37,7 @@
#include "vmbus_private.h"
#include "vmbus_api.h"
#include "utils.h"
+#include "hv_kvp.h"
static u8 *shut_txf_buf;
static u8 *time_txf_buf;
@@ -255,6 +256,10 @@ static int __init init_hyperv_utils(void)
{
printk(KERN_INFO "Registering HyperV Utility Driver\n");
+ if (hv_kvp_init())
+ return -ENODEV;
+
+
if (!dmi_check_system(hv_utils_dmi_table))
return -ENODEV;
@@ -283,6 +288,11 @@ static int __init init_hyperv_utils(void)
&heartbeat_onchannelcallback;
hv_cb_utils[HV_HEARTBEAT_MSG].callback = &heartbeat_onchannelcallback;
+ hv_cb_utils[HV_KVP_MSG].channel->onchannel_callback =
+ &hv_kvp_onchannelcallback;
+
+
+
return 0;
}
@@ -302,6 +312,10 @@ static void exit_hyperv_utils(void)
&chn_cb_negotiate;
hv_cb_utils[HV_HEARTBEAT_MSG].callback = &chn_cb_negotiate;
+ hv_cb_utils[HV_KVP_MSG].channel->onchannel_callback =
+ &chn_cb_negotiate;
+ hv_kvp_deinit();
+
kfree(shut_txf_buf);
kfree(time_txf_buf);
kfree(hbeat_txf_buf);
diff --git a/drivers/staging/hv/utils.h b/drivers/staging/hv/utils.h
index 7c07499..6d27d15 100644
--- a/drivers/staging/hv/utils.h
+++ b/drivers/staging/hv/utils.h
@@ -102,6 +102,7 @@ struct ictimesync_data{
#define HV_SHUTDOWN_MSG 0
#define HV_TIMESYNC_MSG 1
#define HV_HEARTBEAT_MSG 2
+#define HV_KVP_MSG 3
struct hyperv_service_callback {
u8 msg_type;
--
1.7.1
^ permalink raw reply related
* [PATCH 2/4] Staging: hv: Rename hv_utils.c to hv_util.c
From: Ky Srinivasan @ 2010-12-17 1:38 UTC (permalink / raw)
To: devel, Virtualization; +Cc: Zbr, Haiyang Zhang, Stephen Hemminger, Greg KH
In-Reply-To: <1292531022-14297-1-git-send-email-ksrinivasan@novell.com>
The hv_utils module will be composed of more than one file;
rename hv_utils.c to accommodate this without changing the module name.
Signed-off-by: K. Y. Srinivasan <ksrinivasan@novell.com>
---
drivers/staging/hv/Makefile | 1 +
drivers/staging/hv/hv_util.c | 315 +++++++++++++++++++++++++++++++++++++++++
drivers/staging/hv/hv_utils.c | 315 -----------------------------------------
3 files changed, 316 insertions(+), 315 deletions(-)
create mode 100644 drivers/staging/hv/hv_util.c
delete mode 100644 drivers/staging/hv/hv_utils.c
diff --git a/drivers/staging/hv/Makefile b/drivers/staging/hv/Makefile
index acd39bd..4c14138 100644
--- a/drivers/staging/hv/Makefile
+++ b/drivers/staging/hv/Makefile
@@ -10,3 +10,4 @@ hv_vmbus-y := vmbus_drv.o osd.o \
hv_storvsc-y := storvsc_drv.o storvsc.o
hv_blkvsc-y := blkvsc_drv.o blkvsc.o
hv_netvsc-y := netvsc_drv.o netvsc.o rndis_filter.o
+hv_utils-y := hv_util.o
diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c
new file mode 100644
index 0000000..0074581
--- /dev/null
+++ b/drivers/staging/hv/hv_util.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2010, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ * Haiyang Zhang <haiyangz@microsoft.com>
+ * Hank Janssen <hjanssen@microsoft.com>
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/sysctl.h>
+#include <linux/reboot.h>
+#include <linux/dmi.h>
+#include <linux/pci.h>
+
+#include "logging.h"
+#include "osd.h"
+#include "vmbus.h"
+#include "vmbus_packet_format.h"
+#include "vmbus_channel_interface.h"
+#include "version_info.h"
+#include "channel.h"
+#include "vmbus_private.h"
+#include "vmbus_api.h"
+#include "utils.h"
+
+static u8 *shut_txf_buf;
+static u8 *time_txf_buf;
+static u8 *hbeat_txf_buf;
+
+static void shutdown_onchannelcallback(void *context)
+{
+ struct vmbus_channel *channel = context;
+ u32 recvlen;
+ u64 requestid;
+ u8 execute_shutdown = false;
+
+ struct shutdown_msg_data *shutdown_msg;
+
+ struct icmsg_hdr *icmsghdrp;
+ struct icmsg_negotiate *negop = NULL;
+
+ vmbus_recvpacket(channel, shut_txf_buf,
+ PAGE_SIZE, &recvlen, &requestid);
+
+ if (recvlen > 0) {
+ DPRINT_DBG(VMBUS, "shutdown packet: len=%d, requestid=%lld",
+ recvlen, requestid);
+
+ icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[
+ sizeof(struct vmbuspipe_hdr)];
+
+ if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+ prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf);
+ } else {
+ shutdown_msg =
+ (struct shutdown_msg_data *)&shut_txf_buf[
+ sizeof(struct vmbuspipe_hdr) +
+ sizeof(struct icmsg_hdr)];
+
+ switch (shutdown_msg->flags) {
+ case 0:
+ case 1:
+ icmsghdrp->status = HV_S_OK;
+ execute_shutdown = true;
+
+ DPRINT_INFO(VMBUS, "Shutdown request received -"
+ " gracefull shutdown initiated");
+ break;
+ default:
+ icmsghdrp->status = HV_E_FAIL;
+ execute_shutdown = false;
+
+ DPRINT_INFO(VMBUS, "Shutdown request received -"
+ " Invalid request");
+ break;
+ };
+ }
+
+ icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+ | ICMSGHDRFLAG_RESPONSE;
+
+ vmbus_sendpacket(channel, shut_txf_buf,
+ recvlen, requestid,
+ VmbusPacketTypeDataInBand, 0);
+ }
+
+ if (execute_shutdown == true)
+ orderly_poweroff(false);
+}
+
+/*
+ * Set guest time to host UTC time.
+ */
+static inline void do_adj_guesttime(u64 hosttime)
+{
+ s64 host_tns;
+ struct timespec host_ts;
+
+ host_tns = (hosttime - WLTIMEDELTA) * 100;
+ host_ts = ns_to_timespec(host_tns);
+
+ do_settimeofday(&host_ts);
+}
+
+/*
+ * Synchronize time with host after reboot, restore, etc.
+ *
+ * ICTIMESYNCFLAG_SYNC flag bit indicates reboot, restore events of the VM.
+ * After reboot the flag ICTIMESYNCFLAG_SYNC is included in the first time
+ * message after the timesync channel is opened. Since the hv_utils module is
+ * loaded after hv_vmbus, the first message is usually missed. The other
+ * thing is, systime is automatically set to emulated hardware clock which may
+ * not be UTC time or in the same time zone. So, to override these effects, we
+ * use the first 50 time samples for initial system time setting.
+ */
+static inline void adj_guesttime(u64 hosttime, u8 flags)
+{
+ static s32 scnt = 50;
+
+ if ((flags & ICTIMESYNCFLAG_SYNC) != 0) {
+ do_adj_guesttime(hosttime);
+ return;
+ }
+
+ if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 && scnt > 0) {
+ scnt--;
+ do_adj_guesttime(hosttime);
+ }
+}
+
+/*
+ * Time Sync Channel message handler.
+ */
+static void timesync_onchannelcallback(void *context)
+{
+ struct vmbus_channel *channel = context;
+ u32 recvlen;
+ u64 requestid;
+ struct icmsg_hdr *icmsghdrp;
+ struct ictimesync_data *timedatap;
+
+ vmbus_recvpacket(channel, time_txf_buf,
+ PAGE_SIZE, &recvlen, &requestid);
+
+ if (recvlen > 0) {
+ DPRINT_DBG(VMBUS, "timesync packet: recvlen=%d, requestid=%lld",
+ recvlen, requestid);
+
+ icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[
+ sizeof(struct vmbuspipe_hdr)];
+
+ if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+ prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf);
+ } else {
+ timedatap = (struct ictimesync_data *)&time_txf_buf[
+ sizeof(struct vmbuspipe_hdr) +
+ sizeof(struct icmsg_hdr)];
+ adj_guesttime(timedatap->parenttime, timedatap->flags);
+ }
+
+ icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+ | ICMSGHDRFLAG_RESPONSE;
+
+ vmbus_sendpacket(channel, time_txf_buf,
+ recvlen, requestid,
+ VmbusPacketTypeDataInBand, 0);
+ }
+}
+
+/*
+ * Heartbeat functionality.
+ * Every two seconds, Hyper-V send us a heartbeat request message.
+ * we respond to this message, and Hyper-V knows we are alive.
+ */
+static void heartbeat_onchannelcallback(void *context)
+{
+ struct vmbus_channel *channel = context;
+ u32 recvlen;
+ u64 requestid;
+ struct icmsg_hdr *icmsghdrp;
+ struct heartbeat_msg_data *heartbeat_msg;
+
+ vmbus_recvpacket(channel, hbeat_txf_buf,
+ PAGE_SIZE, &recvlen, &requestid);
+
+ if (recvlen > 0) {
+ DPRINT_DBG(VMBUS, "heartbeat packet: len=%d, requestid=%lld",
+ recvlen, requestid);
+
+ icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
+ sizeof(struct vmbuspipe_hdr)];
+
+ if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+ prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf);
+ } else {
+ heartbeat_msg =
+ (struct heartbeat_msg_data *)&hbeat_txf_buf[
+ sizeof(struct vmbuspipe_hdr) +
+ sizeof(struct icmsg_hdr)];
+
+ DPRINT_DBG(VMBUS, "heartbeat seq = %lld",
+ heartbeat_msg->seq_num);
+
+ heartbeat_msg->seq_num += 1;
+ }
+
+ icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+ | ICMSGHDRFLAG_RESPONSE;
+
+ vmbus_sendpacket(channel, hbeat_txf_buf,
+ recvlen, requestid,
+ VmbusPacketTypeDataInBand, 0);
+ }
+}
+
+static const struct pci_device_id __initconst
+hv_utils_pci_table[] __maybe_unused = {
+ { PCI_DEVICE(0x1414, 0x5353) }, /* Hyper-V emulated VGA controller */
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, hv_utils_pci_table);
+
+
+static const struct dmi_system_id __initconst
+hv_utils_dmi_table[] __maybe_unused = {
+ {
+ .ident = "Hyper-V",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+ DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
+ },
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(dmi, hv_utils_dmi_table);
+
+
+static int __init init_hyperv_utils(void)
+{
+ printk(KERN_INFO "Registering HyperV Utility Driver\n");
+
+ if (!dmi_check_system(hv_utils_dmi_table))
+ return -ENODEV;
+
+ shut_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ time_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ hbeat_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+
+ if (!shut_txf_buf || !time_txf_buf || !hbeat_txf_buf) {
+ printk(KERN_INFO
+ "Unable to allocate memory for receive buffer\n");
+ kfree(shut_txf_buf);
+ kfree(time_txf_buf);
+ kfree(hbeat_txf_buf);
+ return -ENOMEM;
+ }
+
+ hv_cb_utils[HV_SHUTDOWN_MSG].channel->onchannel_callback =
+ &shutdown_onchannelcallback;
+ hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback;
+
+ hv_cb_utils[HV_TIMESYNC_MSG].channel->onchannel_callback =
+ ×ync_onchannelcallback;
+ hv_cb_utils[HV_TIMESYNC_MSG].callback = ×ync_onchannelcallback;
+
+ hv_cb_utils[HV_HEARTBEAT_MSG].channel->onchannel_callback =
+ &heartbeat_onchannelcallback;
+ hv_cb_utils[HV_HEARTBEAT_MSG].callback = &heartbeat_onchannelcallback;
+
+ return 0;
+}
+
+static void exit_hyperv_utils(void)
+{
+ printk(KERN_INFO "De-Registered HyperV Utility Driver\n");
+
+ hv_cb_utils[HV_SHUTDOWN_MSG].channel->onchannel_callback =
+ &chn_cb_negotiate;
+ hv_cb_utils[HV_SHUTDOWN_MSG].callback = &chn_cb_negotiate;
+
+ hv_cb_utils[HV_TIMESYNC_MSG].channel->onchannel_callback =
+ &chn_cb_negotiate;
+ hv_cb_utils[HV_TIMESYNC_MSG].callback = &chn_cb_negotiate;
+
+ hv_cb_utils[HV_HEARTBEAT_MSG].channel->onchannel_callback =
+ &chn_cb_negotiate;
+ hv_cb_utils[HV_HEARTBEAT_MSG].callback = &chn_cb_negotiate;
+
+ kfree(shut_txf_buf);
+ kfree(time_txf_buf);
+ kfree(hbeat_txf_buf);
+}
+
+module_init(init_hyperv_utils);
+module_exit(exit_hyperv_utils);
+
+MODULE_DESCRIPTION("Hyper-V Utilities");
+MODULE_VERSION(HV_DRV_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/hv/hv_utils.c b/drivers/staging/hv/hv_utils.c
deleted file mode 100644
index 0074581..0000000
--- a/drivers/staging/hv/hv_utils.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (c) 2010, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- * Haiyang Zhang <haiyangz@microsoft.com>
- * Hank Janssen <hjanssen@microsoft.com>
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/sysctl.h>
-#include <linux/reboot.h>
-#include <linux/dmi.h>
-#include <linux/pci.h>
-
-#include "logging.h"
-#include "osd.h"
-#include "vmbus.h"
-#include "vmbus_packet_format.h"
-#include "vmbus_channel_interface.h"
-#include "version_info.h"
-#include "channel.h"
-#include "vmbus_private.h"
-#include "vmbus_api.h"
-#include "utils.h"
-
-static u8 *shut_txf_buf;
-static u8 *time_txf_buf;
-static u8 *hbeat_txf_buf;
-
-static void shutdown_onchannelcallback(void *context)
-{
- struct vmbus_channel *channel = context;
- u32 recvlen;
- u64 requestid;
- u8 execute_shutdown = false;
-
- struct shutdown_msg_data *shutdown_msg;
-
- struct icmsg_hdr *icmsghdrp;
- struct icmsg_negotiate *negop = NULL;
-
- vmbus_recvpacket(channel, shut_txf_buf,
- PAGE_SIZE, &recvlen, &requestid);
-
- if (recvlen > 0) {
- DPRINT_DBG(VMBUS, "shutdown packet: len=%d, requestid=%lld",
- recvlen, requestid);
-
- icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[
- sizeof(struct vmbuspipe_hdr)];
-
- if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
- prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf);
- } else {
- shutdown_msg =
- (struct shutdown_msg_data *)&shut_txf_buf[
- sizeof(struct vmbuspipe_hdr) +
- sizeof(struct icmsg_hdr)];
-
- switch (shutdown_msg->flags) {
- case 0:
- case 1:
- icmsghdrp->status = HV_S_OK;
- execute_shutdown = true;
-
- DPRINT_INFO(VMBUS, "Shutdown request received -"
- " gracefull shutdown initiated");
- break;
- default:
- icmsghdrp->status = HV_E_FAIL;
- execute_shutdown = false;
-
- DPRINT_INFO(VMBUS, "Shutdown request received -"
- " Invalid request");
- break;
- };
- }
-
- icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
- | ICMSGHDRFLAG_RESPONSE;
-
- vmbus_sendpacket(channel, shut_txf_buf,
- recvlen, requestid,
- VmbusPacketTypeDataInBand, 0);
- }
-
- if (execute_shutdown == true)
- orderly_poweroff(false);
-}
-
-/*
- * Set guest time to host UTC time.
- */
-static inline void do_adj_guesttime(u64 hosttime)
-{
- s64 host_tns;
- struct timespec host_ts;
-
- host_tns = (hosttime - WLTIMEDELTA) * 100;
- host_ts = ns_to_timespec(host_tns);
-
- do_settimeofday(&host_ts);
-}
-
-/*
- * Synchronize time with host after reboot, restore, etc.
- *
- * ICTIMESYNCFLAG_SYNC flag bit indicates reboot, restore events of the VM.
- * After reboot the flag ICTIMESYNCFLAG_SYNC is included in the first time
- * message after the timesync channel is opened. Since the hv_utils module is
- * loaded after hv_vmbus, the first message is usually missed. The other
- * thing is, systime is automatically set to emulated hardware clock which may
- * not be UTC time or in the same time zone. So, to override these effects, we
- * use the first 50 time samples for initial system time setting.
- */
-static inline void adj_guesttime(u64 hosttime, u8 flags)
-{
- static s32 scnt = 50;
-
- if ((flags & ICTIMESYNCFLAG_SYNC) != 0) {
- do_adj_guesttime(hosttime);
- return;
- }
-
- if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 && scnt > 0) {
- scnt--;
- do_adj_guesttime(hosttime);
- }
-}
-
-/*
- * Time Sync Channel message handler.
- */
-static void timesync_onchannelcallback(void *context)
-{
- struct vmbus_channel *channel = context;
- u32 recvlen;
- u64 requestid;
- struct icmsg_hdr *icmsghdrp;
- struct ictimesync_data *timedatap;
-
- vmbus_recvpacket(channel, time_txf_buf,
- PAGE_SIZE, &recvlen, &requestid);
-
- if (recvlen > 0) {
- DPRINT_DBG(VMBUS, "timesync packet: recvlen=%d, requestid=%lld",
- recvlen, requestid);
-
- icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[
- sizeof(struct vmbuspipe_hdr)];
-
- if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
- prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf);
- } else {
- timedatap = (struct ictimesync_data *)&time_txf_buf[
- sizeof(struct vmbuspipe_hdr) +
- sizeof(struct icmsg_hdr)];
- adj_guesttime(timedatap->parenttime, timedatap->flags);
- }
-
- icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
- | ICMSGHDRFLAG_RESPONSE;
-
- vmbus_sendpacket(channel, time_txf_buf,
- recvlen, requestid,
- VmbusPacketTypeDataInBand, 0);
- }
-}
-
-/*
- * Heartbeat functionality.
- * Every two seconds, Hyper-V send us a heartbeat request message.
- * we respond to this message, and Hyper-V knows we are alive.
- */
-static void heartbeat_onchannelcallback(void *context)
-{
- struct vmbus_channel *channel = context;
- u32 recvlen;
- u64 requestid;
- struct icmsg_hdr *icmsghdrp;
- struct heartbeat_msg_data *heartbeat_msg;
-
- vmbus_recvpacket(channel, hbeat_txf_buf,
- PAGE_SIZE, &recvlen, &requestid);
-
- if (recvlen > 0) {
- DPRINT_DBG(VMBUS, "heartbeat packet: len=%d, requestid=%lld",
- recvlen, requestid);
-
- icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
- sizeof(struct vmbuspipe_hdr)];
-
- if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
- prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf);
- } else {
- heartbeat_msg =
- (struct heartbeat_msg_data *)&hbeat_txf_buf[
- sizeof(struct vmbuspipe_hdr) +
- sizeof(struct icmsg_hdr)];
-
- DPRINT_DBG(VMBUS, "heartbeat seq = %lld",
- heartbeat_msg->seq_num);
-
- heartbeat_msg->seq_num += 1;
- }
-
- icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
- | ICMSGHDRFLAG_RESPONSE;
-
- vmbus_sendpacket(channel, hbeat_txf_buf,
- recvlen, requestid,
- VmbusPacketTypeDataInBand, 0);
- }
-}
-
-static const struct pci_device_id __initconst
-hv_utils_pci_table[] __maybe_unused = {
- { PCI_DEVICE(0x1414, 0x5353) }, /* Hyper-V emulated VGA controller */
- { 0 }
-};
-MODULE_DEVICE_TABLE(pci, hv_utils_pci_table);
-
-
-static const struct dmi_system_id __initconst
-hv_utils_dmi_table[] __maybe_unused = {
- {
- .ident = "Hyper-V",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
- DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
- },
- },
- { },
-};
-MODULE_DEVICE_TABLE(dmi, hv_utils_dmi_table);
-
-
-static int __init init_hyperv_utils(void)
-{
- printk(KERN_INFO "Registering HyperV Utility Driver\n");
-
- if (!dmi_check_system(hv_utils_dmi_table))
- return -ENODEV;
-
- shut_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
- time_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
- hbeat_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-
- if (!shut_txf_buf || !time_txf_buf || !hbeat_txf_buf) {
- printk(KERN_INFO
- "Unable to allocate memory for receive buffer\n");
- kfree(shut_txf_buf);
- kfree(time_txf_buf);
- kfree(hbeat_txf_buf);
- return -ENOMEM;
- }
-
- hv_cb_utils[HV_SHUTDOWN_MSG].channel->onchannel_callback =
- &shutdown_onchannelcallback;
- hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback;
-
- hv_cb_utils[HV_TIMESYNC_MSG].channel->onchannel_callback =
- ×ync_onchannelcallback;
- hv_cb_utils[HV_TIMESYNC_MSG].callback = ×ync_onchannelcallback;
-
- hv_cb_utils[HV_HEARTBEAT_MSG].channel->onchannel_callback =
- &heartbeat_onchannelcallback;
- hv_cb_utils[HV_HEARTBEAT_MSG].callback = &heartbeat_onchannelcallback;
-
- return 0;
-}
-
-static void exit_hyperv_utils(void)
-{
- printk(KERN_INFO "De-Registered HyperV Utility Driver\n");
-
- hv_cb_utils[HV_SHUTDOWN_MSG].channel->onchannel_callback =
- &chn_cb_negotiate;
- hv_cb_utils[HV_SHUTDOWN_MSG].callback = &chn_cb_negotiate;
-
- hv_cb_utils[HV_TIMESYNC_MSG].channel->onchannel_callback =
- &chn_cb_negotiate;
- hv_cb_utils[HV_TIMESYNC_MSG].callback = &chn_cb_negotiate;
-
- hv_cb_utils[HV_HEARTBEAT_MSG].channel->onchannel_callback =
- &chn_cb_negotiate;
- hv_cb_utils[HV_HEARTBEAT_MSG].callback = &chn_cb_negotiate;
-
- kfree(shut_txf_buf);
- kfree(time_txf_buf);
- kfree(hbeat_txf_buf);
-}
-
-module_init(init_hyperv_utils);
-module_exit(exit_hyperv_utils);
-
-MODULE_DESCRIPTION("Hyper-V Utilities");
-MODULE_VERSION(HV_DRV_VERSION);
-MODULE_LICENSE("GPL");
--
1.7.1
^ permalink raw reply related
* [PATCH 1/4] Connector: Add an index to support key/value pair (KVP) functionality
From: Ky Srinivasan @ 2010-12-17 1:35 UTC (permalink / raw)
To: devel, Virtualization; +Cc: Zbr, Haiyang Zhang, Stephen Hemminger, Greg KH
In-Reply-To: <1292530752-14180-1-git-send-email-ksrinivasan@novell.com>
Added a connector index to support key value/pair (KVP) functionality
for Linux guests hosted on a HyperV platform.
Signed-off-by: K. Y. Srinivasan <ksrinivasan@novell.com>
---
include/linux/connector.h | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/include/linux/connector.h b/include/linux/connector.h
index 7e8ca75..2e9759c 100644
--- a/include/linux/connector.h
+++ b/include/linux/connector.h
@@ -42,8 +42,9 @@
#define CN_VAL_DM_USERSPACE_LOG 0x1
#define CN_IDX_DRBD 0x8
#define CN_VAL_DRBD 0x1
+#define CN_KVP_IDX 0x9 /* HyperV KVP */
-#define CN_NETLINK_USERS 8
+#define CN_NETLINK_USERS 9
/*
* Maximum connector's message size.
--
1.7.1
^ permalink raw reply related
* Re: [GIT PULL net-next-2.6] vhost-net: tools, cleanups, optimizations
From: David Miller @ 2010-12-14 19:34 UTC (permalink / raw)
To: mst; +Cc: kvm, virtualization, netdev, linux-kernel
In-Reply-To: <20101214122326.GA19950@redhat.com>
From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Tue, 14 Dec 2010 14:23:26 +0200
> On Mon, Dec 13, 2010 at 12:44:13PM +0200, Michael S. Tsirkin wrote:
>> Please merge the following tree for 2.6.38.
>> Thanks!
>
> Rusty Acked it as is, so please pull the below.
> Thanks very much!
>
>> The following changes since commit ad1184c6cf067a13e8cb2a4e7ccc407f947027d0:
>>
>> net: au1000_eth: remove unused global variable. (2010-12-11 12:01:48 -0800)
>>
>> are available in the git repository at:
>> git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git vhost-net-next
Pulled, thanks a lot.
^ permalink raw reply
* [GIT PULL net-next-2.6] vhost-net: tools, cleanups, optimizations
From: Michael S. Tsirkin @ 2010-12-14 12:23 UTC (permalink / raw)
To: David Miller; +Cc: kvm, virtualization, netdev, linux-kernel
In-Reply-To: <20101213104413.GA678@redhat.com>
On Mon, Dec 13, 2010 at 12:44:13PM +0200, Michael S. Tsirkin wrote:
> Please merge the following tree for 2.6.38.
> Thanks!
Rusty Acked it as is, so please pull the below.
Thanks very much!
> The following changes since commit ad1184c6cf067a13e8cb2a4e7ccc407f947027d0:
>
> net: au1000_eth: remove unused global variable. (2010-12-11 12:01:48 -0800)
>
> are available in the git repository at:
> git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git vhost-net-next
>
> Jason Wang (1):
> vhost: fix typos in comment
>
> Julia Lawall (1):
> drivers/vhost/vhost.c: delete double assignment
>
> Michael S. Tsirkin (9):
> vhost: put mm after thread stop
> vhost-net: batch use/unuse mm
> vhost: copy_to_user -> __copy_to_user
> vhost: get/put_user -> __get/__put_user
> vhost: remove unused include
> vhost: correctly set bits of dirty pages
> vhost: better variable name in logging
> vhost test module
> tools/virtio: virtio_test tool
>
> drivers/vhost/net.c | 9 +-
> drivers/vhost/test.c | 320 ++++++++++++++++++++++++++++++++++
> drivers/vhost/test.h | 7 +
> drivers/vhost/vhost.c | 44 +++---
> drivers/vhost/vhost.h | 2 +-
> tools/virtio/Makefile | 12 ++
> tools/virtio/linux/device.h | 2 +
> tools/virtio/linux/slab.h | 2 +
> tools/virtio/linux/virtio.h | 223 +++++++++++++++++++++++
> tools/virtio/vhost_test/Makefile | 2 +
> tools/virtio/vhost_test/vhost_test.c | 1 +
> tools/virtio/virtio_test.c | 248 ++++++++++++++++++++++++++
> 12 files changed, 842 insertions(+), 30 deletions(-)
> create mode 100644 drivers/vhost/test.c
> create mode 100644 drivers/vhost/test.h
> create mode 100644 tools/virtio/Makefile
> create mode 100644 tools/virtio/linux/device.h
> create mode 100644 tools/virtio/linux/slab.h
> create mode 100644 tools/virtio/linux/virtio.h
> create mode 100644 tools/virtio/vhost_test/Makefile
> create mode 100644 tools/virtio/vhost_test/vhost_test.c
> create mode 100644 tools/virtio/virtio_test.c
^ permalink raw reply
* virtqueue_add_buf
From: devi thapa @ 2010-12-14 5:59 UTC (permalink / raw)
To: virtualization
Hi Everybody,
How to simulate the export function "virtqueue_add_buf"?
I tried to invoke it by pinging to the host machine, but failed.
Awaiting your replies !
Regards,
Devi.
^ permalink raw reply
* Re: [GIT PULL net-next-2.6] vhost-net: tools, cleanups, optimizations
From: Rusty Russell @ 2010-12-14 5:48 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: David Miller, kvm, virtualization, netdev, linux-kernel
In-Reply-To: <20101213172447.GA8560@redhat.com>
On Tue, 14 Dec 2010 03:54:47 am Michael S. Tsirkin wrote:
> On Mon, Dec 13, 2010 at 12:44:13PM +0200, Michael S. Tsirkin wrote:
> > Please merge the following tree for 2.6.38.
> > Thanks!
>
> Um, I sent this out before I noticed the mail from Rusty
> with some questions on the test code. I missed that and
> assumed no comments -> no issues, perhaps wrongly.
>
> Rusty - I tried answering the questions there - any issues
> with merging this? It's just a test so won't be hard to remove
> later if it's not helpful ...
Traditionally this stuff has not gone in tree. However, I think it
should be...
Rusty.
^ permalink raw reply
* [PATCH 1/1] hv: Use only one txf buffer per channel and kmalloc/GFP_KERNEL on initialize
From: Hank Janssen @ 2010-12-14 0:23 UTC (permalink / raw)
To: hjanssen, gregkh, linux-kernel, devel, virtualization
Cc: Haiyang Zhang, Evgeniy Polyakov, Jesper Juhl, Ky Srinivasan
Correct issue with not checking kmalloc return value.
This fix now only uses one receive buffer for all hv_utils
channels, and will do only one kmalloc on init and will return
with a -ENOMEM if kmalloc fails on initialize.
And properly clean up memory on failure.
Thanks to Evgeniy Polyakov <zbr@ioremap.net> for pointing this out.
And thanks to Jesper Juhl <jj@chaosbits.net> and Ky Srinivasan
<ksrinivasan@novell.com> for suggesting a better implementation of
my original patch.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
Reviewed-by: Jesper Juhl <jj@chaosbits.net>
Cc: Evgeniy Polyakov <zbr@ioremap.net>
Cc: Jesper Juhl <jj@chaosbits.net>
Cc: Ky Srinivasan <ksrinivasan@novell.com>
---
drivers/staging/hv/hv_utils.c | 84 +++++++++++++++++++++-------------------
1 files changed, 44 insertions(+), 40 deletions(-)
diff --git a/drivers/staging/hv/hv_utils.c b/drivers/staging/hv/hv_utils.c
index 53e1e29..e0ecc23 100644
--- a/drivers/staging/hv/hv_utils.c
+++ b/drivers/staging/hv/hv_utils.c
@@ -38,12 +38,14 @@
#include "vmbus_api.h"
#include "utils.h"
+static u8 *shut_txf_buf;
+static u8 *time_txf_buf;
+static u8 *hbeat_txf_buf;
static void shutdown_onchannelcallback(void *context)
{
struct vmbus_channel *channel = context;
- u8 *buf;
- u32 buflen, recvlen;
+ u32 recvlen;
u64 requestid;
u8 execute_shutdown = false;
@@ -52,24 +54,23 @@ static void shutdown_onchannelcallback(void *context)
struct icmsg_hdr *icmsghdrp;
struct icmsg_negotiate *negop = NULL;
- buflen = PAGE_SIZE;
- buf = kmalloc(buflen, GFP_ATOMIC);
-
- vmbus_recvpacket(channel, buf, buflen, &recvlen, &requestid);
+ vmbus_recvpacket(channel, shut_txf_buf,
+ PAGE_SIZE, &recvlen, &requestid);
if (recvlen > 0) {
DPRINT_DBG(VMBUS, "shutdown packet: len=%d, requestid=%lld",
recvlen, requestid);
- icmsghdrp = (struct icmsg_hdr *)&buf[
+ icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
- prep_negotiate_resp(icmsghdrp, negop, buf);
+ prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf);
} else {
- shutdown_msg = (struct shutdown_msg_data *)&buf[
- sizeof(struct vmbuspipe_hdr) +
- sizeof(struct icmsg_hdr)];
+ shutdown_msg =
+ (struct shutdown_msg_data *)&shut_txf_buf[
+ sizeof(struct vmbuspipe_hdr) +
+ sizeof(struct icmsg_hdr)];
switch (shutdown_msg->flags) {
case 0:
@@ -93,13 +94,11 @@ static void shutdown_onchannelcallback(void *context)
icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
| ICMSGHDRFLAG_RESPONSE;
- vmbus_sendpacket(channel, buf,
+ vmbus_sendpacket(channel, shut_txf_buf,
recvlen, requestid,
VmbusPacketTypeDataInBand, 0);
}
- kfree(buf);
-
if (execute_shutdown == true)
orderly_poweroff(false);
}
@@ -150,28 +149,25 @@ static inline void adj_guesttime(u64 hosttime, u8 flags)
static void timesync_onchannelcallback(void *context)
{
struct vmbus_channel *channel = context;
- u8 *buf;
- u32 buflen, recvlen;
+ u32 recvlen;
u64 requestid;
struct icmsg_hdr *icmsghdrp;
struct ictimesync_data *timedatap;
- buflen = PAGE_SIZE;
- buf = kmalloc(buflen, GFP_ATOMIC);
-
- vmbus_recvpacket(channel, buf, buflen, &recvlen, &requestid);
+ vmbus_recvpacket(channel, time_txf_buf,
+ PAGE_SIZE, &recvlen, &requestid);
if (recvlen > 0) {
DPRINT_DBG(VMBUS, "timesync packet: recvlen=%d, requestid=%lld",
recvlen, requestid);
- icmsghdrp = (struct icmsg_hdr *)&buf[
+ icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
- prep_negotiate_resp(icmsghdrp, NULL, buf);
+ prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf);
} else {
- timedatap = (struct ictimesync_data *)&buf[
+ timedatap = (struct ictimesync_data *)&time_txf_buf[
sizeof(struct vmbuspipe_hdr) +
sizeof(struct icmsg_hdr)];
adj_guesttime(timedatap->parenttime, timedatap->flags);
@@ -180,12 +176,10 @@ static void timesync_onchannelcallback(void *context)
icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
| ICMSGHDRFLAG_RESPONSE;
- vmbus_sendpacket(channel, buf,
+ vmbus_sendpacket(channel, time_txf_buf,
recvlen, requestid,
VmbusPacketTypeDataInBand, 0);
}
-
- kfree(buf);
}
/*
@@ -196,30 +190,28 @@ static void timesync_onchannelcallback(void *context)
static void heartbeat_onchannelcallback(void *context)
{
struct vmbus_channel *channel = context;
- u8 *buf;
- u32 buflen, recvlen;
+ u32 recvlen;
u64 requestid;
struct icmsg_hdr *icmsghdrp;
struct heartbeat_msg_data *heartbeat_msg;
- buflen = PAGE_SIZE;
- buf = kmalloc(buflen, GFP_ATOMIC);
-
- vmbus_recvpacket(channel, buf, buflen, &recvlen, &requestid);
+ vmbus_recvpacket(channel, hbeat_txf_buf,
+ PAGE_SIZE, &recvlen, &requestid);
if (recvlen > 0) {
DPRINT_DBG(VMBUS, "heartbeat packet: len=%d, requestid=%lld",
recvlen, requestid);
- icmsghdrp = (struct icmsg_hdr *)&buf[
+ icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
sizeof(struct vmbuspipe_hdr)];
if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
- prep_negotiate_resp(icmsghdrp, NULL, buf);
+ prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf);
} else {
- heartbeat_msg = (struct heartbeat_msg_data *)&buf[
- sizeof(struct vmbuspipe_hdr) +
- sizeof(struct icmsg_hdr)];
+ heartbeat_msg =
+ (struct heartbeat_msg_data *)&hbeat_txf_buf[
+ sizeof(struct vmbuspipe_hdr) +
+ sizeof(struct icmsg_hdr)];
DPRINT_DBG(VMBUS, "heartbeat seq = %lld",
heartbeat_msg->seq_num);
@@ -230,12 +222,10 @@ static void heartbeat_onchannelcallback(void *context)
icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
| ICMSGHDRFLAG_RESPONSE;
- vmbus_sendpacket(channel, buf,
+ vmbus_sendpacket(channel, hbeat_txf_buf,
recvlen, requestid,
VmbusPacketTypeDataInBand, 0);
}
-
- kfree(buf);
}
static const struct pci_device_id __initconst
@@ -268,6 +258,19 @@ static int __init init_hyperv_utils(void)
if (!dmi_check_system(hv_utils_dmi_table))
return -ENODEV;
+ shut_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ time_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ hbeat_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+
+ if (!shut_txf_buf || !time_txf_buf || !hbeat_txf_buf) {
+ printk(KERN_INFO
+ "Unable to allocate memory for receive buffer\n");
+ kfree(shut_txf_buf);
+ kfree(time_txf_buf);
+ kfree(hbeat_txf_buf);
+ return -ENOMEM;
+ }
+
hv_cb_utils[HV_SHUTDOWN_MSG].channel->onchannel_callback =
&shutdown_onchannelcallback;
hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback;
@@ -298,6 +298,10 @@ static void exit_hyperv_utils(void)
hv_cb_utils[HV_HEARTBEAT_MSG].channel->onchannel_callback =
&chn_cb_negotiate;
hv_cb_utils[HV_HEARTBEAT_MSG].callback = &chn_cb_negotiate;
+
+ kfree(shut_txf_buf);
+ kfree(time_txf_buf);
+ kfree(hbeat_txf_buf);
}
module_init(init_hyperv_utils);
--
1.6.0.2
^ permalink raw reply related
* RE: [PATCH 1/1] hv: Use only one receive buffer per channel and kmalloc on initialize
From: Hank Janssen @ 2010-12-14 0:11 UTC (permalink / raw)
To: Jesper Juhl, Ky Srinivasan
Cc: devel@linuxdriverproject.org, virtualization@lists.osdl.org,
gregkh@suse.de, linux-kernel@vger.kernel.org, Evgeniy Polyakov,
Haiyang Zhang
In-Reply-To: <alpine.LNX.2.00.1012140048290.26491@swampdragon.chaosbits.net>
> -----Original Message-----
> From: Jesper Juhl [mailto:jj@chaosbits.net]
> Sent: Monday, December 13, 2010 3:51 PM
> To: Ky Srinivasan
> > > + shut_txf_buf = kmalloc(PAGE_SIZE, GFP_ATOMIC);
> > > + time_txf_buf = kmalloc(PAGE_SIZE, GFP_ATOMIC);
> > > + hbeat_txf_buf = kmalloc(PAGE_SIZE, GFP_ATOMIC);
> > Why are these allocations GFP_ATOMIC. Clearly this is in module
> loading context and you can afford to sleep. GFP_KERNEL should be fine.
> >
>
> I actually also noticed this when I did my first review of the patch,
> but
> I didn't point it out since I thought that "there must be a good
> reason".
> But now that you point it out and I look at the code once more I can't
> actually think of a "good reason",, so I agree with you completely that
> these should just be GFP_KERNEL.
I was looking at some of the back code to make sure it is okay, and I see
No reason not make this change either. I will change it and resubmit.
Thanks,
Hank.
^ permalink raw reply
* Re: [PATCH 1/1] hv: Use only one receive buffer per channel and kmalloc on initialize
From: Jesper Juhl @ 2010-12-13 23:50 UTC (permalink / raw)
To: Ky Srinivasan
Cc: devel, virtualization, hjanssen, gregkh, linux-kernel,
Evgeniy Polyakov, Haiyang Zhang
In-Reply-To: <4D0636270200003000091D23@novprvoes0310.provo.novell.com>
On Mon, 13 Dec 2010, Ky Srinivasan wrote:
>
>
> >>> On 12/13/2010 at 3:34 PM, in message
> <1292272498-29483-1-git-send-email-hjanssen@microsoft.com>, Hank Janssen
> <hjanssen@microsoft.com> wrote:
> > Correct issue with not checking kmalloc return value.
> > This fix now only uses one receive buffer for all hv_utils
> > channels, and will do only one kmalloc on init and will return
> > with a -ENOMEM if kmalloc fails on initialize.
> >
> > Thanks to Evgeniy Polyakov <zbr@ioremap.net> for pointing this out.
> > And thanks to Jesper Juhl <jj@chaosbits.net> and Ky Srinivasan
> > <ksrinivasan@novell.com> for suggesting a better implementation of
> > my original patch.
> >
> > Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
> > Signed-off-by: Hank Janssen <hjanssen@microsoft.com>
> > Cc: Evgeniy Polyakov <zbr@ioremap.net>
> > Cc: Jesper Juhl <jj@chaosbits.net>
> > Cc: Ky Srinivasan <ksrinivasan@novell.com>
> >
> > ---
> > drivers/staging/hv/hv_utils.c | 84 +++++++++++++++++++++-------------------
> > 1 files changed, 44 insertions(+), 40 deletions(-)
> >
> > diff --git a/drivers/staging/hv/hv_utils.c b/drivers/staging/hv/hv_utils.c
> > index 53e1e29..e0ecc23 100644
> > --- a/drivers/staging/hv/hv_utils.c
> > +++ b/drivers/staging/hv/hv_utils.c
> > @@ -38,12 +38,14 @@
> > #include "vmbus_api.h"
> > #include "utils.h"
> >
> > +static u8 *shut_txf_buf;
> > +static u8 *time_txf_buf;
> > +static u8 *hbeat_txf_buf;
> >
> > static void shutdown_onchannelcallback(void *context)
> > {
> > struct vmbus_channel *channel = context;
> > - u8 *buf;
> > - u32 buflen, recvlen;
> > + u32 recvlen;
> > u64 requestid;
> > u8 execute_shutdown = false;
> >
> > @@ -52,24 +54,23 @@ static void shutdown_onchannelcallback(void *context)
> > struct icmsg_hdr *icmsghdrp;
> > struct icmsg_negotiate *negop = NULL;
> >
> > - buflen = PAGE_SIZE;
> > - buf = kmalloc(buflen, GFP_ATOMIC);
> > -
> > - vmbus_recvpacket(channel, buf, buflen, &recvlen, &requestid);
> > + vmbus_recvpacket(channel, shut_txf_buf,
> > + PAGE_SIZE, &recvlen, &requestid);
> >
> > if (recvlen > 0) {
> > DPRINT_DBG(VMBUS, "shutdown packet: len=%d, requestid=%lld",
> > recvlen, requestid);
> >
> > - icmsghdrp = (struct icmsg_hdr *)&buf[
> > + icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[
> > sizeof(struct vmbuspipe_hdr)];
> >
> > if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
> > - prep_negotiate_resp(icmsghdrp, negop, buf);
> > + prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf);
> > } else {
> > - shutdown_msg = (struct shutdown_msg_data *)&buf[
> > - sizeof(struct vmbuspipe_hdr) +
> > - sizeof(struct icmsg_hdr)];
> > + shutdown_msg =
> > + (struct shutdown_msg_data *)&shut_txf_buf[
> > + sizeof(struct vmbuspipe_hdr) +
> > + sizeof(struct icmsg_hdr)];
> >
> > switch (shutdown_msg->flags) {
> > case 0:
> > @@ -93,13 +94,11 @@ static void shutdown_onchannelcallback(void *context)
> > icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
> > | ICMSGHDRFLAG_RESPONSE;
> >
> > - vmbus_sendpacket(channel, buf,
> > + vmbus_sendpacket(channel, shut_txf_buf,
> > recvlen, requestid,
> > VmbusPacketTypeDataInBand, 0);
> > }
> >
> > - kfree(buf);
> > -
> > if (execute_shutdown == true)
> > orderly_poweroff(false);
> > }
> > @@ -150,28 +149,25 @@ static inline void adj_guesttime(u64 hosttime, u8
> > flags)
> > static void timesync_onchannelcallback(void *context)
> > {
> > struct vmbus_channel *channel = context;
> > - u8 *buf;
> > - u32 buflen, recvlen;
> > + u32 recvlen;
> > u64 requestid;
> > struct icmsg_hdr *icmsghdrp;
> > struct ictimesync_data *timedatap;
> >
> > - buflen = PAGE_SIZE;
> > - buf = kmalloc(buflen, GFP_ATOMIC);
> > -
> > - vmbus_recvpacket(channel, buf, buflen, &recvlen, &requestid);
> > + vmbus_recvpacket(channel, time_txf_buf,
> > + PAGE_SIZE, &recvlen, &requestid);
> >
> > if (recvlen > 0) {
> > DPRINT_DBG(VMBUS, "timesync packet: recvlen=%d, requestid=%lld",
> > recvlen, requestid);
> >
> > - icmsghdrp = (struct icmsg_hdr *)&buf[
> > + icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[
> > sizeof(struct vmbuspipe_hdr)];
> >
> > if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
> > - prep_negotiate_resp(icmsghdrp, NULL, buf);
> > + prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf);
> > } else {
> > - timedatap = (struct ictimesync_data *)&buf[
> > + timedatap = (struct ictimesync_data *)&time_txf_buf[
> > sizeof(struct vmbuspipe_hdr) +
> > sizeof(struct icmsg_hdr)];
> > adj_guesttime(timedatap->parenttime, timedatap->flags);
> > @@ -180,12 +176,10 @@ static void timesync_onchannelcallback(void *context)
> > icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
> > | ICMSGHDRFLAG_RESPONSE;
> >
> > - vmbus_sendpacket(channel, buf,
> > + vmbus_sendpacket(channel, time_txf_buf,
> > recvlen, requestid,
> > VmbusPacketTypeDataInBand, 0);
> > }
> > -
> > - kfree(buf);
> > }
> >
> > /*
> > @@ -196,30 +190,28 @@ static void timesync_onchannelcallback(void *context)
> > static void heartbeat_onchannelcallback(void *context)
> > {
> > struct vmbus_channel *channel = context;
> > - u8 *buf;
> > - u32 buflen, recvlen;
> > + u32 recvlen;
> > u64 requestid;
> > struct icmsg_hdr *icmsghdrp;
> > struct heartbeat_msg_data *heartbeat_msg;
> >
> > - buflen = PAGE_SIZE;
> > - buf = kmalloc(buflen, GFP_ATOMIC);
> > -
> > - vmbus_recvpacket(channel, buf, buflen, &recvlen, &requestid);
> > + vmbus_recvpacket(channel, hbeat_txf_buf,
> > + PAGE_SIZE, &recvlen, &requestid);
> >
> > if (recvlen > 0) {
> > DPRINT_DBG(VMBUS, "heartbeat packet: len=%d, requestid=%lld",
> > recvlen, requestid);
> >
> > - icmsghdrp = (struct icmsg_hdr *)&buf[
> > + icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
> > sizeof(struct vmbuspipe_hdr)];
> >
> > if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
> > - prep_negotiate_resp(icmsghdrp, NULL, buf);
> > + prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf);
> > } else {
> > - heartbeat_msg = (struct heartbeat_msg_data *)&buf[
> > - sizeof(struct vmbuspipe_hdr) +
> > - sizeof(struct icmsg_hdr)];
> > + heartbeat_msg =
> > + (struct heartbeat_msg_data *)&hbeat_txf_buf[
> > + sizeof(struct vmbuspipe_hdr) +
> > + sizeof(struct icmsg_hdr)];
> >
> > DPRINT_DBG(VMBUS, "heartbeat seq = %lld",
> > heartbeat_msg->seq_num);
> > @@ -230,12 +222,10 @@ static void heartbeat_onchannelcallback(void *context)
> > icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
> > | ICMSGHDRFLAG_RESPONSE;
> >
> > - vmbus_sendpacket(channel, buf,
> > + vmbus_sendpacket(channel, hbeat_txf_buf,
> > recvlen, requestid,
> > VmbusPacketTypeDataInBand, 0);
> > }
> > -
> > - kfree(buf);
> > }
> >
> > static const struct pci_device_id __initconst
> > @@ -268,6 +258,16 @@ static int __init init_hyperv_utils(void)
> > if (!dmi_check_system(hv_utils_dmi_table))
> > return -ENODEV;
> >
> > + shut_txf_buf = kmalloc(PAGE_SIZE, GFP_ATOMIC);
> > + time_txf_buf = kmalloc(PAGE_SIZE, GFP_ATOMIC);
> > + hbeat_txf_buf = kmalloc(PAGE_SIZE, GFP_ATOMIC);
> Why are these allocations GFP_ATOMIC. Clearly this is in module loading context and you can afford to sleep. GFP_KERNEL should be fine.
>
I actually also noticed this when I did my first review of the patch, but
I didn't point it out since I thought that "there must be a good reason".
But now that you point it out and I look at the code once more I can't
actually think of a "good reason",, so I agree with you completely that
these should just be GFP_KERNEL.
--
Jesper Juhl <jj@chaosbits.net> http://www.chaosbits.net/
Don't top-post http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox