[libvirt] doc: write separate module for hostdev passthrough and in-use tracking

Hi, List, As the mail I've sent a week before: https://www.redhat.com/archives/libvir-list/2013-March/msg00730.html I'm willing to push this work forward so that the passthrough APIs could be reused by qemu driver and libxl driver (which doesn't support pci passthrough yet and tries to add this function recently), or other drivers. But since this work affacts a lot, I'm not sure if I can control it in a correct way. I write a draft to describe what I'm considering how to do, as in the following and in attachment. Hope to get your review, comment and guidence to improve the work before start coding. Any feedback will be very appreciated! Thanks! Chunyan ------------------------ DRAFT: Write separate module for hostdev passthrough 1. Purposes: * Move hostdev passthrough APIs from qemu_hostdev.ch to separate module so that they could be reused by other hypervisors too * Maintain global in-use state of hostdevs 2. Module design (draft): * New module name: hostdev_driver * New module files: hostdev_driver.ch hostdev_conf.ch * New Definitions: ## [src/driver.h] typedef struct _virHostdevDriver virHostdevDriver; typedef virHostdevDriver *virHostdevDriverPtr; struct _virHosedevDriver { const char *name; virDrvOpen open; virDrvClose close; virDrvPrepareHostdevs prepareHostdevs; virDrvPreparePciHostdevs preparePciHostdevs; virDrvprepareUsbHostdevs prepareUsbHostdevs; virDrvReattachHostdevs reattachHostdevs; virDrvReattachPciHostdevs reattachPciHostdevs; virDrvReattachUsbHostdevs reattachUsbHostdevs; virDrvGetActivePciHostdevList getActivePciHostdevList; virDrvGetActiveUsbHostdevList getActiveUsbHostdevList; virDrvGetDomainActivePciHostdevList getDomainActivePciHostdevList; virDrvGetDomainActiveUsbHostdevList getDomainActiveUsbHostdevList; }; ## [src/hostdev/hostdev_conf.h] typedef struct _virHostdevDriverState virHostdevDriverState; typedef virHostdevDriverState *virHostdevDriverStatePtr; struct _virHostdevDriverState { virMutex lock; virPCIDeviceListPtr activePciHostdevs; virPCIDeviceListPtr inactivePciHostdevs; virUSBDeviceListPtr activeUsbHostdevs; }; ## [src/hostdev/hostdev_driver.c] static virHostdevDriver hostdevDriver = { .name = "hostdev", .open = hostdevDriverOpen, .close = hostdevDriverClose, .prepareHostdevs = virPrepareHostdevs, .preparePciHostdevs = virPreparePciHostdevs, .prepareUsbHostdevs = virPrepareUsbHostdevs .reattachHostdevs = virReattachHostdevs, .reattachPciHostdevs = virReattachPciHostdevs, .reattachUsbHostdevs = virReattachUsbHostdevs, .getActivePciHostdevList = virGetActivePciHostdevList, .getActiveUsbHostdevList = virGetActiveUsbHostdevList, .getDomainActivePciHostdevList = virGetDomainActivePciHostdevList, .getDomainActiveUsbHostdevList = virGetDomainActiveUsbHostdevList, }; static virStateDriver hostdevStateDriver = { .name = "hostdev", .initialize = hostdevDriverStartup, .cleanup = hostdevDriverCleanup, .reload = hostdevDriverReload, }; * Changed Definitions: struct _virPCIDevice { ...... --- const char *used_by; /* The domain which uses the device */ +++ virDomainObjPtr used_by; /* include domname and conn info */ ...... }; struct _virUSBDevice { ...... --- const char *used_by; /* name of the domain using this dev */ +++ virDomainObjPtr used_by; /* include domname and conn info */ }; * APIs: typedef int (*virDrvPrepareHostdevs)(virHostdevDriverPtr driver, virDomainObjPtr vm, unsigned int flags); /* - workflow: call PrepareHostdevPciDevices and PrepareHostdevUsbDevices to do specific work. - reference: int qemuPrepareHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def, bool coldBoot); - new parameter: - flags: - could set "coldBoot" for usb usage - could set hypervisor tag since for qemu it will use pci-stub, for libxl, it will use pciback. */ typedef int (*virDrvPreparePciHostdevs)(virHostdevDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr *hostdevs, int nhostdevs, unsigned int flags); /* - workflow: 1. check things (e.g. assignability to non-managed device) 2. detach managed device and reset work 3. set usedby to 'vm', update activePciHostdevs and inactivePciHostdevs - reference: int qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, const char *name, const unsigned char *uuid, virDomainHostdevDefPtr *hostdevs, int nhostdevs); */ typedef int (*virDrvprepareUsbHostdevs)((virHostdevDriverPtr driver, virDomainObjPtr vm, virUSBDeviceListPtr list); /* - workflow: check usb device, set usedby to 'vm', update activeUsbHostdevs - reference: int qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver, const char *name, virUSBDeviceListPtr list); */ typedef void (*virDrvReattachHostdevs)(virHostdevDriverPtr driver, virDomainObjPtr vm); /* - workflow: call reattachPciHostDevices and reattachUsbHostDevices to do specific work. - reference: void qemuDomainReAttachHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def) */ typedef void (*virDrvReattachPciHostdevs) (virHostdevDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr *hostdevs, int nhostdevs); /* - workflow: unbind and bind to original driver, free usedby, activePciHostdevs and inactivePciHostdevs. - reference: void qemuDomainReAttachHostdevDevices(virQEMUDriverPtrdriver, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs) */ typedef void (*virDrvReattachUsbHostdevs) (virHostdevDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr *hostdevs, int nhostdevs); /* - workflow: free usedby, activePciHostdevs and inactivePciHostdevs. - reference: static void qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs) */ typedef virPCIDeviceListPtr (*virDrvGetActivePciHostdevList) (virHostdevDriverPtr driver); /* - could be used to check if a pci hostdev is already in-use. */ typedef virUSBDeviceListPtr (*virDrvGetActiveUsbHostdevList) (virHostdevDriverPtr driver); /* - could be used to check if a usb hostdev is already in-use. */ typedef virPCIDeviceListPtr (*virDrvGetDomainActivePciHostdevList) (virHostdevDriverPtr driver); /* - could be used to reattach all in-use pci hostdevs by a domain (e.g. when a domain shutdown) */ typedef virPCIDeviceListPtr (*virDrvGetDomainActiveUsbHostdevList) (virHostdevDriverPtr driver); /* - could be used to reattach all in-use usb hostdevs by a domain */ 3. Use the module * Register hostdev driver - define 'virHostdevDriverTab' and 'virHostdevDriverTabCount' - add hostdev driver register work in libvirtd.c daemonInitialize() * add hostdev driver areas to _virConnect struct _virConnect { ....... virNWFilterDriverPtr nwfilterDriver; +++ virHostdevDriverPtr hostdevDriver; ....... void * nwfilterPrivateData; +++ void * hostdevPrivateData; ....... } * add conn->hostdevDriver parser in libvirt.c: do_open() Then hypervisor drivers can get use of hostdev driver APIs. * moments that could be affacted: - domain start/shutoff - attach/detach hostdev to domain --------------------------------------------

On 2013年03月22日 17:36, Chunyan Liu wrote:
Hi, List,
As the mail I've sent a week before: https://www.redhat.com/archives/libvir-list/2013-March/msg00730.html I'm willing to push this work forward so that the passthrough APIs could be reused by qemu driver and libxl driver (which doesn't support pci passthrough yet and tries to add this function recently), or other drivers.
But since this work affacts a lot, I'm not sure if I can control it in a correct way. I write a draft to describe what I'm considering how to do, as in the following and in attachment. Hope to get your review, comment and guidence to improve the work before start coding. Any feedback will be very appreciated!
Thanks! Chunyan
------------------------ DRAFT:
Write separate module for hostdev passthrough
Cool. we lacked this for a time.
1. Purposes:
* Move hostdev passthrough APIs from qemu_hostdev.ch to separate module so that they could be reused by other hypervisors too
* Maintain global in-use state of hostdevs
This is more important than the code-reuse.
2. Module design (draft):
* New module name: hostdev_driver
* New module files: hostdev_driver.ch hostdev_conf.ch
* New Definitions:
## [src/driver.h]
typedef struct _virHostdevDriver virHostdevDriver;
typedef virHostdevDriver *virHostdevDriverPtr;
struct _virHosedevDriver { const char *name; virDrvOpen open; virDrvClose close;
virDrvPrepareHostdevs prepareHostdevs; virDrvPreparePciHostdevs preparePciHostdevs; virDrvprepareUsbHostdevs prepareUsbHostdevs;
In case of you want to expose prepareHostdevs, no need to expose preparePciHostdevs and prepareUsbHostdevs?
virDrvReattachHostdevs reattachHostdevs; virDrvReattachPciHostdevs reattachPciHostdevs; virDrvReattachUsbHostdevs reattachUsbHostdevs;
Likewise.
virDrvGetActivePciHostdevList getActivePciHostdevList; virDrvGetActiveUsbHostdevList getActiveUsbHostdevList; virDrvGetDomainActivePciHostdevList getDomainActivePciHostdevList; virDrvGetDomainActiveUsbHostdevList getDomainActiveUsbHostdevList;
These APIs are useful for upper layer management too. I have once wanted to create similiar APIs, but only tended for qemu driver at that time. But except these 4 get APIs, others are only useful for other drivers (internally), useless for upper layer management. Do we really want a driver instead of just an internal share module? Like src/nodeinfo.[ch], and with it we still can expose APIs like the 4 get APIs.
};
## [src/hostdev/hostdev_conf.h]
typedef struct _virHostdevDriverState virHostdevDriverState;
typedef virHostdevDriverState *virHostdevDriverStatePtr;
struct _virHostdevDriverState { virMutex lock; virPCIDeviceListPtr activePciHostdevs; virPCIDeviceListPtr inactivePciHostdevs; virUSBDeviceListPtr activeUsbHostdevs; };
## [src/hostdev/hostdev_driver.c]
static virHostdevDriver hostdevDriver = { .name = "hostdev", .open = hostdevDriverOpen, .close = hostdevDriverClose, .prepareHostdevs = virPrepareHostdevs, .preparePciHostdevs = virPreparePciHostdevs, .prepareUsbHostdevs = virPrepareUsbHostdevs .reattachHostdevs = virReattachHostdevs, .reattachPciHostdevs = virReattachPciHostdevs, .reattachUsbHostdevs = virReattachUsbHostdevs, .getActivePciHostdevList = virGetActivePciHostdevList, .getActiveUsbHostdevList = virGetActiveUsbHostdevList, .getDomainActivePciHostdevList = virGetDomainActivePciHostdevList, .getDomainActiveUsbHostdevList = virGetDomainActiveUsbHostdevList, };
static virStateDriver hostdevStateDriver = { .name = "hostdev", .initialize = hostdevDriverStartup, .cleanup = hostdevDriverCleanup, .reload = hostdevDriverReload, };
* Changed Definitions:
struct _virPCIDevice { ......
--- const char *used_by; /* The domain which uses the device */ +++ virDomainObjPtr used_by; /* include domname and conn info */
Why need the "conn info"? Isn't a driver name enough here?
...... };
struct _virUSBDevice { ...... --- const char *used_by; /* name of the domain using this dev */ +++ virDomainObjPtr used_by; /* include domname and conn info */ };
* APIs:
typedef int (*virDrvPrepareHostdevs)(virHostdevDriverPtr driver, virDomainObjPtr vm, unsigned int flags); /* - workflow: call PrepareHostdevPciDevices and PrepareHostdevUsbDevices to do specific work.
- reference: int qemuPrepareHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def, bool coldBoot);
- new parameter: - flags: - could set "coldBoot" for usb usage - could set hypervisor tag since for qemu it will use pci-stub, for libxl, it will use pciback. */
typedef int (*virDrvPreparePciHostdevs)(virHostdevDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr *hostdevs, int nhostdevs, unsigned int flags); /* - workflow: 1. check things (e.g. assignability to non-managed device) 2. detach managed device and reset work 3. set usedby to 'vm', update activePciHostdevs and inactivePciHostdevs
- reference: int qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, const char *name, const unsigned char *uuid, virDomainHostdevDefPtr *hostdevs, int nhostdevs); */
typedef int (*virDrvprepareUsbHostdevs)((virHostdevDriverPtr driver, virDomainObjPtr vm, virUSBDeviceListPtr list); /* - workflow: check usb device, set usedby to 'vm', update activeUsbHostdevs
- reference: int qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver, const char *name, virUSBDeviceListPtr list); */
typedef void (*virDrvReattachHostdevs)(virHostdevDriverPtr driver, virDomainObjPtr vm); /* - workflow: call reattachPciHostDevices and reattachUsbHostDevices to do specific work.
- reference: void qemuDomainReAttachHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def) */
typedef void (*virDrvReattachPciHostdevs) (virHostdevDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr *hostdevs, int nhostdevs); /* - workflow: unbind and bind to original driver, free usedby, activePciHostdevs and inactivePciHostdevs.
- reference: void qemuDomainReAttachHostdevDevices(virQEMUDriverPtrdriver, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs) */
typedef void (*virDrvReattachUsbHostdevs) (virHostdevDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr *hostdevs, int nhostdevs); /* - workflow: free usedby, activePciHostdevs and inactivePciHostdevs.
- reference: static void qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs) */
typedef virPCIDeviceListPtr (*virDrvGetActivePciHostdevList) (virHostdevDriverPtr driver); /* - could be used to check if a pci hostdev is already in-use. */
typedef virUSBDeviceListPtr (*virDrvGetActiveUsbHostdevList) (virHostdevDriverPtr driver); /* - could be used to check if a usb hostdev is already in-use. */
typedef virPCIDeviceListPtr (*virDrvGetDomainActivePciHostdevList) (virHostdevDriverPtr driver); /* - could be used to reattach all in-use pci hostdevs by a domain (e.g. when a domain shutdown) */
typedef virPCIDeviceListPtr (*virDrvGetDomainActiveUsbHostdevList) (virHostdevDriverPtr driver); /* - could be used to reattach all in-use usb hostdevs by a domain */
So it needs to expose the virPCI{USB}DeviceList to public. Not sure how useful it will be to expose the struct, instead of the ID of the devices. These APIs could be used for node device driver. To filter the active/ inactive devices.
3. Use the module
* Register hostdev driver - define 'virHostdevDriverTab' and 'virHostdevDriverTabCount' - add hostdev driver register work in libvirtd.c daemonInitialize()
* add hostdev driver areas to _virConnect struct _virConnect { ....... virNWFilterDriverPtr nwfilterDriver; +++ virHostdevDriverPtr hostdevDriver;
....... void * nwfilterPrivateData; +++ void * hostdevPrivateData; ....... }
* add conn->hostdevDriver parser in libvirt.c: do_open() Then hypervisor drivers can get use of hostdev driver APIs.
* moments that could be affacted: - domain start/shutoff - attach/detach hostdev to domain
And libvirt restarting.
--------------------------------------------
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

2013/3/22 Osier Yang <jyang@redhat.com>:
On 2013年03月22日 17:36, Chunyan Liu wrote:
Hi, List,
As the mail I've sent a week before: https://www.redhat.com/archives/libvir-list/2013-March/msg00730.html I'm willing to push this work forward so that the passthrough APIs could be reused by qemu driver and libxl driver (which doesn't support pci passthrough yet and tries to add this function recently), or other drivers.
But since this work affacts a lot, I'm not sure if I can control it in a correct way. I write a draft to describe what I'm considering how to do, as in the following and in attachment. Hope to get your review, comment and guidence to improve the work before start coding. Any feedback will be very appreciated!
Thanks! Chunyan
------------------------ DRAFT:
Write separate module for hostdev passthrough
Cool. we lacked this for a time.
1. Purposes:
* Move hostdev passthrough APIs from qemu_hostdev.ch to separate module so that they could be reused by other hypervisors too
* Maintain global in-use state of hostdevs
This is more important than the code-reuse.
2. Module design (draft):
* New module name: hostdev_driver
* New module files: hostdev_driver.ch hostdev_conf.ch
* New Definitions:
## [src/driver.h]
typedef struct _virHostdevDriver virHostdevDriver;
typedef virHostdevDriver *virHostdevDriverPtr;
struct _virHosedevDriver { const char *name; virDrvOpen open; virDrvClose close;
virDrvPrepareHostdevs prepareHostdevs; virDrvPreparePciHostdevs preparePciHostdevs; virDrvprepareUsbHostdevs prepareUsbHostdevs;
In case of you want to expose prepareHostdevs, no need to expose preparePciHostdevs and prepareUsbHostdevs?
Thanks very much for your comments. Exposing these two APIs is considering that some driver may supports one but not another, so that it could call specific API. But we can use support flag in prepareHostdevs to control that, in this way not need these two APIs.
virDrvReattachHostdevs reattachHostdevs; virDrvReattachPciHostdevs reattachPciHostdevs; virDrvReattachUsbHostdevs reattachUsbHostdevs;
Likewise.
virDrvGetActivePciHostdevList getActivePciHostdevList; virDrvGetActiveUsbHostdevList getActiveUsbHostdevList; virDrvGetDomainActivePciHostdevList getDomainActivePciHostdevList; virDrvGetDomainActiveUsbHostdevList getDomainActiveUsbHostdevList;
These APIs are useful for upper layer management too. I have once wanted to create similiar APIs, but only tended for qemu driver at that time.
But except these 4 get APIs, others are only useful for other drivers (internally), useless for upper layer management.
That's true.
Do we really want a driver instead of just an internal share module? Like src/nodeinfo.[ch], and with it we still can expose APIs like the 4 get APIs.
Do you mean add src/hostdev.[ch] and do all work there? Think a while, I think it can achieve too. Then do we need to differentiate 4 get APIs and other APIs?
};
## [src/hostdev/hostdev_conf.h]
typedef struct _virHostdevDriverState virHostdevDriverState;
typedef virHostdevDriverState *virHostdevDriverStatePtr;
struct _virHostdevDriverState { virMutex lock; virPCIDeviceListPtr activePciHostdevs; virPCIDeviceListPtr inactivePciHostdevs; virUSBDeviceListPtr activeUsbHostdevs; };
## [src/hostdev/hostdev_driver.c]
static virHostdevDriver hostdevDriver = { .name = "hostdev", .open = hostdevDriverOpen, .close = hostdevDriverClose, .prepareHostdevs = virPrepareHostdevs, .preparePciHostdevs = virPreparePciHostdevs, .prepareUsbHostdevs = virPrepareUsbHostdevs .reattachHostdevs = virReattachHostdevs, .reattachPciHostdevs = virReattachPciHostdevs, .reattachUsbHostdevs = virReattachUsbHostdevs, .getActivePciHostdevList = virGetActivePciHostdevList, .getActiveUsbHostdevList = virGetActiveUsbHostdevList, .getDomainActivePciHostdevList = virGetDomainActivePciHostdevList, .getDomainActiveUsbHostdevList = virGetDomainActiveUsbHostdevList, };
static virStateDriver hostdevStateDriver = { .name = "hostdev", .initialize = hostdevDriverStartup, .cleanup = hostdevDriverCleanup, .reload = hostdevDriverReload, };
* Changed Definitions:
struct _virPCIDevice { ......
--- const char *used_by; /* The domain which uses the device */ +++ virDomainObjPtr used_by; /* include domname and conn info */
Why need the "conn info"? Isn't a driver name enough here?
Driver name is OK. Just need to fill unique info about the device is used by which driver which domain. So I try to store virDomainObjPtr to the used_by area, from this pointer, we can get driver name and domain name. Do you think that's OK?
...... };
struct _virUSBDevice { ...... --- const char *used_by; /* name of the domain using this dev */ +++ virDomainObjPtr used_by; /* include domname and conn info */ };
* APIs:
typedef int (*virDrvPrepareHostdevs)(virHostdevDriverPtr driver, virDomainObjPtr vm, unsigned int flags); /* - workflow: call PrepareHostdevPciDevices and PrepareHostdevUsbDevices to do specific work.
- reference: int qemuPrepareHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def, bool coldBoot);
- new parameter: - flags: - could set "coldBoot" for usb usage - could set hypervisor tag since for qemu it will use pci-stub, for libxl, it will use pciback. */
typedef int (*virDrvPreparePciHostdevs)(virHostdevDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr *hostdevs, int nhostdevs, unsigned int flags); /* - workflow: 1. check things (e.g. assignability to non-managed device) 2. detach managed device and reset work 3. set usedby to 'vm', update activePciHostdevs and inactivePciHostdevs
- reference: int qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, const char *name, const unsigned char *uuid, virDomainHostdevDefPtr *hostdevs, int nhostdevs); */
typedef int (*virDrvprepareUsbHostdevs)((virHostdevDriverPtr driver, virDomainObjPtr vm, virUSBDeviceListPtr list); /* - workflow: check usb device, set usedby to 'vm', update activeUsbHostdevs
- reference: int qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver, const char *name, virUSBDeviceListPtr list); */
typedef void (*virDrvReattachHostdevs)(virHostdevDriverPtr driver, virDomainObjPtr vm); /* - workflow: call reattachPciHostDevices and reattachUsbHostDevices to do specific work.
- reference: void qemuDomainReAttachHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def) */
typedef void (*virDrvReattachPciHostdevs) (virHostdevDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr *hostdevs, int nhostdevs); /* - workflow: unbind and bind to original driver, free usedby, activePciHostdevs and inactivePciHostdevs.
- reference: void qemuDomainReAttachHostdevDevices(virQEMUDriverPtrdriver, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs) */
typedef void (*virDrvReattachUsbHostdevs) (virHostdevDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr *hostdevs, int nhostdevs); /* - workflow: free usedby, activePciHostdevs and inactivePciHostdevs.
- reference: static void qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs) */
typedef virPCIDeviceListPtr (*virDrvGetActivePciHostdevList) (virHostdevDriverPtr driver); /* - could be used to check if a pci hostdev is already in-use. */
typedef virUSBDeviceListPtr (*virDrvGetActiveUsbHostdevList) (virHostdevDriverPtr driver); /* - could be used to check if a usb hostdev is already in-use. */
typedef virPCIDeviceListPtr (*virDrvGetDomainActivePciHostdevList) (virHostdevDriverPtr driver); /* - could be used to reattach all in-use pci hostdevs by a domain (e.g. when a domain shutdown) */
typedef virUSBDeviceListPtr (*virDrvGetDomainActiveUsbHostdevList) (virHostdevDriverPtr driver); /* - could be used to reattach all in-use usb hostdevs by a domain */
So it needs to expose the virPCI{USB}DeviceList to public. Not sure how useful it will be to expose the struct, instead of the ID of the devices.
The case I was considering here is: when reattaching hostdevs in vm shutoff, 'managed' or 'non-managed' info is also needed. But in this case, it is internally used, we can also handle that in virDrvReattachHostdevs. Could "managed=yes/no" info be used somewhere else? If not, then seems ID is enough.
These APIs could be used for node device driver. To filter the active/ inactive devices.
3. Use the module
* Register hostdev driver - define 'virHostdevDriverTab' and 'virHostdevDriverTabCount' - add hostdev driver register work in libvirtd.c daemonInitialize()
* add hostdev driver areas to _virConnect struct _virConnect { ....... virNWFilterDriverPtr nwfilterDriver; +++ virHostdevDriverPtr hostdevDriver;
....... void * nwfilterPrivateData; +++ void * hostdevPrivateData; ....... }
* add conn->hostdevDriver parser in libvirt.c: do_open() Then hypervisor drivers can get use of hostdev driver APIs.
* moments that could be affacted: - domain start/shutoff - attach/detach hostdev to domain
And libvirt restarting.
--------------------------------------------
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

On 25/03/13 14:51, Chunyan Liu wrote:
2013/3/22 Osier Yang <jyang@redhat.com>:
On 2013年03月22日 17:36, Chunyan Liu wrote:
Hi, List,
As the mail I've sent a week before: https://www.redhat.com/archives/libvir-list/2013-March/msg00730.html I'm willing to push this work forward so that the passthrough APIs could be reused by qemu driver and libxl driver (which doesn't support pci passthrough yet and tries to add this function recently), or other drivers.
But since this work affacts a lot, I'm not sure if I can control it in a correct way. I write a draft to describe what I'm considering how to do, as in the following and in attachment. Hope to get your review, comment and guidence to improve the work before start coding. Any feedback will be very appreciated!
Thanks! Chunyan
------------------------ DRAFT:
Write separate module for hostdev passthrough
Cool. we lacked this for a time.
1. Purposes:
* Move hostdev passthrough APIs from qemu_hostdev.ch to separate module so that they could be reused by other hypervisors too
* Maintain global in-use state of hostdevs
This is more important than the code-reuse.
2. Module design (draft):
* New module name: hostdev_driver
* New module files: hostdev_driver.ch hostdev_conf.ch
* New Definitions:
## [src/driver.h]
typedef struct _virHostdevDriver virHostdevDriver;
typedef virHostdevDriver *virHostdevDriverPtr;
struct _virHosedevDriver { const char *name; virDrvOpen open; virDrvClose close;
virDrvPrepareHostdevs prepareHostdevs; virDrvPreparePciHostdevs preparePciHostdevs; virDrvprepareUsbHostdevs prepareUsbHostdevs;
In case of you want to expose prepareHostdevs, no need to expose preparePciHostdevs and prepareUsbHostdevs? Thanks very much for your comments.
Exposing these two APIs is considering that some driver may supports one but not another, so that it could call specific API. But we can use support flag in prepareHostdevs to control that, in this way not need these two APIs
virDrvReattachHostdevs reattachHostdevs; virDrvReattachPciHostdevs reattachPciHostdevs; virDrvReattachUsbHostdevs reattachUsbHostdevs;
Likewise.
virDrvGetActivePciHostdevList getActivePciHostdevList; virDrvGetActiveUsbHostdevList getActiveUsbHostdevList; virDrvGetDomainActivePciHostdevList getDomainActivePciHostdevList; virDrvGetDomainActiveUsbHostdevList getDomainActiveUsbHostdevList;
These APIs are useful for upper layer management too. I have once wanted to create similiar APIs, but only tended for qemu driver at that time.
But except these 4 get APIs, others are only useful for other drivers (internally), useless for upper layer management. That's true.
Do we really want a driver instead of just an internal share module? Like src/nodeinfo.[ch], and with it we still can expose APIs like the 4 get APIs. Do you mean add src/hostdev.[ch] and do all work there? Think a while, I think it can achieve too.
Yes.
Then do we need to differentiate 4 get APIs and other APIs?
Not sure about you meaning here. But you can take the existing APIs like virNodeSetMemoryParameters as examples. The API is implemented in src/nodeinfo.[ch], but each driver can use it.
};
## [src/hostdev/hostdev_conf.h]
typedef struct _virHostdevDriverState virHostdevDriverState;
typedef virHostdevDriverState *virHostdevDriverStatePtr;
struct _virHostdevDriverState { virMutex lock; virPCIDeviceListPtr activePciHostdevs; virPCIDeviceListPtr inactivePciHostdevs; virUSBDeviceListPtr activeUsbHostdevs; };
## [src/hostdev/hostdev_driver.c]
static virHostdevDriver hostdevDriver = { .name = "hostdev", .open = hostdevDriverOpen, .close = hostdevDriverClose, .prepareHostdevs = virPrepareHostdevs, .preparePciHostdevs = virPreparePciHostdevs, .prepareUsbHostdevs = virPrepareUsbHostdevs .reattachHostdevs = virReattachHostdevs, .reattachPciHostdevs = virReattachPciHostdevs, .reattachUsbHostdevs = virReattachUsbHostdevs, .getActivePciHostdevList = virGetActivePciHostdevList, .getActiveUsbHostdevList = virGetActiveUsbHostdevList, .getDomainActivePciHostdevList = virGetDomainActivePciHostdevList, .getDomainActiveUsbHostdevList = virGetDomainActiveUsbHostdevList, };
static virStateDriver hostdevStateDriver = { .name = "hostdev", .initialize = hostdevDriverStartup, .cleanup = hostdevDriverCleanup, .reload = hostdevDriverReload, };
* Changed Definitions:
struct _virPCIDevice { ......
--- const char *used_by; /* The domain which uses the device */ +++ virDomainObjPtr used_by; /* include domname and conn info */
Why need the "conn info"? Isn't a driver name enough here?
Driver name is OK. Just need to fill unique info about the device is used by which driver which domain. So I try to store virDomainObjPtr to the used_by area, from this pointer, we can get driver name and domain name. Do you think that's OK?
Yeah, I think virDomainObjPtr is just overkill, you have to maintain the object's lifecycle.
...... };
struct _virUSBDevice { ...... --- const char *used_by; /* name of the domain using this dev */ +++ virDomainObjPtr used_by; /* include domname and conn info */ };
* APIs:
typedef int (*virDrvPrepareHostdevs)(virHostdevDriverPtr driver, virDomainObjPtr vm, unsigned int flags); /* - workflow: call PrepareHostdevPciDevices and PrepareHostdevUsbDevices to do specific work.
- reference: int qemuPrepareHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def, bool coldBoot);
- new parameter: - flags: - could set "coldBoot" for usb usage - could set hypervisor tag since for qemu it will use pci-stub, for libxl, it will use pciback. */
typedef int (*virDrvPreparePciHostdevs)(virHostdevDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr *hostdevs, int nhostdevs, unsigned int flags); /* - workflow: 1. check things (e.g. assignability to non-managed device) 2. detach managed device and reset work 3. set usedby to 'vm', update activePciHostdevs and inactivePciHostdevs
- reference: int qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, const char *name, const unsigned char *uuid, virDomainHostdevDefPtr *hostdevs, int nhostdevs); */
typedef int (*virDrvprepareUsbHostdevs)((virHostdevDriverPtr driver, virDomainObjPtr vm, virUSBDeviceListPtr list); /* - workflow: check usb device, set usedby to 'vm', update activeUsbHostdevs
- reference: int qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver, const char *name, virUSBDeviceListPtr list); */
typedef void (*virDrvReattachHostdevs)(virHostdevDriverPtr driver, virDomainObjPtr vm); /* - workflow: call reattachPciHostDevices and reattachUsbHostDevices to do specific work.
- reference: void qemuDomainReAttachHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def) */
typedef void (*virDrvReattachPciHostdevs) (virHostdevDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr *hostdevs, int nhostdevs); /* - workflow: unbind and bind to original driver, free usedby, activePciHostdevs and inactivePciHostdevs.
- reference: void qemuDomainReAttachHostdevDevices(virQEMUDriverPtrdriver, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs) */
typedef void (*virDrvReattachUsbHostdevs) (virHostdevDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr *hostdevs, int nhostdevs); /* - workflow: free usedby, activePciHostdevs and inactivePciHostdevs.
- reference: static void qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs) */
typedef virPCIDeviceListPtr (*virDrvGetActivePciHostdevList) (virHostdevDriverPtr driver); /* - could be used to check if a pci hostdev is already in-use. */
typedef virUSBDeviceListPtr (*virDrvGetActiveUsbHostdevList) (virHostdevDriverPtr driver); /* - could be used to check if a usb hostdev is already in-use. */
typedef virPCIDeviceListPtr (*virDrvGetDomainActivePciHostdevList) (virHostdevDriverPtr driver); /* - could be used to reattach all in-use pci hostdevs by a domain (e.g. when a domain shutdown) */
typedef virUSBDeviceListPtr (*virDrvGetDomainActiveUsbHostdevList) (virHostdevDriverPtr driver); /* - could be used to reattach all in-use usb hostdevs by a domain */
So it needs to expose the virPCI{USB}DeviceList to public. Not sure how useful it will be to expose the struct, instead of the ID of the devices.
The case I was considering here is: when reattaching hostdevs in vm shutoff, 'managed' or 'non-managed' info is also needed. But in this case, it is internally used, we can also handle that in virDrvReattachHostdevs. Could "managed=yes/no" info be used somewhere else? If not, then seems ID is enough.
"managed=yes/no" is only used by attaching/detaching, nodedev-dettach and nodedev-reattach.
These APIs could be used for node device driver. To filter the active/ inactive devices.
3. Use the module
* Register hostdev driver - define 'virHostdevDriverTab' and 'virHostdevDriverTabCount' - add hostdev driver register work in libvirtd.c daemonInitialize()
* add hostdev driver areas to _virConnect struct _virConnect { ....... virNWFilterDriverPtr nwfilterDriver; +++ virHostdevDriverPtr hostdevDriver;
....... void * nwfilterPrivateData; +++ void * hostdevPrivateData; ....... }
* add conn->hostdevDriver parser in libvirt.c: do_open() Then hypervisor drivers can get use of hostdev driver APIs.
* moments that could be affacted: - domain start/shutoff - attach/detach hostdev to domain
And libvirt restarting.
--------------------------------------------
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

2013/3/26 Osier Yang <jyang@redhat.com>:
On 25/03/13 14:51, Chunyan Liu wrote:
2013/3/22 Osier Yang <jyang@redhat.com>:
On 2013年03月22日 17:36, Chunyan Liu wrote:
Hi, List,
As the mail I've sent a week before: https://www.redhat.com/archives/libvir-list/2013-March/msg00730.html I'm willing to push this work forward so that the passthrough APIs could be reused by qemu driver and libxl driver (which doesn't support pci passthrough yet and tries to add this function recently), or other drivers.
But since this work affacts a lot, I'm not sure if I can control it in a correct way. I write a draft to describe what I'm considering how to do, as in the following and in attachment. Hope to get your review, comment and guidence to improve the work before start coding. Any feedback will be very appreciated!
Thanks! Chunyan
------------------------ DRAFT:
Write separate module for hostdev passthrough
Cool. we lacked this for a time.
1. Purposes:
* Move hostdev passthrough APIs from qemu_hostdev.ch to separate module so that they could be reused by other hypervisors too
* Maintain global in-use state of hostdevs
This is more important than the code-reuse.
2. Module design (draft):
* New module name: hostdev_driver
* New module files: hostdev_driver.ch hostdev_conf.ch
* New Definitions:
## [src/driver.h]
typedef struct _virHostdevDriver virHostdevDriver;
typedef virHostdevDriver *virHostdevDriverPtr;
struct _virHosedevDriver { const char *name; virDrvOpen open; virDrvClose close;
virDrvPrepareHostdevs prepareHostdevs; virDrvPreparePciHostdevs preparePciHostdevs; virDrvprepareUsbHostdevs prepareUsbHostdevs;
In case of you want to expose prepareHostdevs, no need to expose preparePciHostdevs and prepareUsbHostdevs?
Thanks very much for your comments.
Exposing these two APIs is considering that some driver may supports one but not another, so that it could call specific API. But we can use support flag in prepareHostdevs to control that, in this way not need these two APIs
virDrvReattachHostdevs reattachHostdevs; virDrvReattachPciHostdevs reattachPciHostdevs; virDrvReattachUsbHostdevs reattachUsbHostdevs;
Likewise.
virDrvGetActivePciHostdevList getActivePciHostdevList; virDrvGetActiveUsbHostdevList getActiveUsbHostdevList; virDrvGetDomainActivePciHostdevList getDomainActivePciHostdevList; virDrvGetDomainActiveUsbHostdevList getDomainActiveUsbHostdevList;
These APIs are useful for upper layer management too. I have once wanted to create similiar APIs, but only tended for qemu driver at that time.
But except these 4 get APIs, others are only useful for other drivers (internally), useless for upper layer management.
That's true.
Do we really want a driver instead of just an internal share module? Like src/nodeinfo.[ch], and with it we still can expose APIs like the 4 get APIs.
Do you mean add src/hostdev.[ch] and do all work there? Think a while, I think it can achieve too.
Yes.
Then do we need to differentiate 4 get APIs and other APIs?
Not sure about you meaning here. Sorry, I meant: since the 4 get APIs could be used by upper layer management, other APIs like prepareHostdevs and reattachHostdevs are only used internally, should we place them separately, like in separate header files? or trace them no difference?
But you can take the existing APIs like virNodeSetMemoryParameters as examples. The API is implemented in src/nodeinfo.[ch], but each driver can use it.
};
## [src/hostdev/hostdev_conf.h]
typedef struct _virHostdevDriverState virHostdevDriverState;
typedef virHostdevDriverState *virHostdevDriverStatePtr;
struct _virHostdevDriverState { virMutex lock; virPCIDeviceListPtr activePciHostdevs; virPCIDeviceListPtr inactivePciHostdevs; virUSBDeviceListPtr activeUsbHostdevs; };
## [src/hostdev/hostdev_driver.c]
static virHostdevDriver hostdevDriver = { .name = "hostdev", .open = hostdevDriverOpen, .close = hostdevDriverClose, .prepareHostdevs = virPrepareHostdevs, .preparePciHostdevs = virPreparePciHostdevs, .prepareUsbHostdevs = virPrepareUsbHostdevs .reattachHostdevs = virReattachHostdevs, .reattachPciHostdevs = virReattachPciHostdevs, .reattachUsbHostdevs = virReattachUsbHostdevs, .getActivePciHostdevList = virGetActivePciHostdevList, .getActiveUsbHostdevList = virGetActiveUsbHostdevList, .getDomainActivePciHostdevList = virGetDomainActivePciHostdevList, .getDomainActiveUsbHostdevList = virGetDomainActiveUsbHostdevList, };
static virStateDriver hostdevStateDriver = { .name = "hostdev", .initialize = hostdevDriverStartup, .cleanup = hostdevDriverCleanup, .reload = hostdevDriverReload, };
* Changed Definitions:
struct _virPCIDevice { ......
--- const char *used_by; /* The domain which uses the device */ +++ virDomainObjPtr used_by; /* include domname and conn info */
Why need the "conn info"? Isn't a driver name enough here?
Driver name is OK. Just need to fill unique info about the device is used by which driver which domain. So I try to store virDomainObjPtr to the used_by area, from this pointer, we can get driver name and domain name. Do you think that's OK?
Yeah, I think virDomainObjPtr is just overkill, you have to maintain the object's lifecycle. OK. We can change 'used_by' to 'used_by_drvname' and 'used_by_domname'. --- const char *used_by; /* The domain which uses the device */ +++ const char *used_by_drvname; +++ const char *used_by_domname;
Thanks, Chunyan
...... };
struct _virUSBDevice { ...... --- const char *used_by; /* name of the domain using this dev */ +++ virDomainObjPtr used_by; /* include domname and conn info */ };
* APIs:
typedef int (*virDrvPrepareHostdevs)(virHostdevDriverPtr driver, virDomainObjPtr vm, unsigned int flags); /* - workflow: call PrepareHostdevPciDevices and PrepareHostdevUsbDevices to do specific work.
- reference: int qemuPrepareHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def, bool coldBoot);
- new parameter: - flags: - could set "coldBoot" for usb usage - could set hypervisor tag since for qemu it will use pci-stub, for libxl, it will use pciback. */
typedef int (*virDrvPreparePciHostdevs)(virHostdevDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr *hostdevs, int nhostdevs, unsigned int flags); /* - workflow: 1. check things (e.g. assignability to non-managed device) 2. detach managed device and reset work 3. set usedby to 'vm', update activePciHostdevs and inactivePciHostdevs
- reference: int qemuPrepareHostdevPCIDevices(virQEMUDriverPtr driver, const char *name, const unsigned char *uuid, virDomainHostdevDefPtr *hostdevs, int nhostdevs); */
typedef int (*virDrvprepareUsbHostdevs)((virHostdevDriverPtr driver, virDomainObjPtr vm, virUSBDeviceListPtr list); /* - workflow: check usb device, set usedby to 'vm', update activeUsbHostdevs
- reference: int qemuPrepareHostdevUSBDevices(virQEMUDriverPtr driver, const char *name, virUSBDeviceListPtr list); */
typedef void (*virDrvReattachHostdevs)(virHostdevDriverPtr driver, virDomainObjPtr vm); /* - workflow: call reattachPciHostDevices and reattachUsbHostDevices to do specific work.
- reference: void qemuDomainReAttachHostDevices(virQEMUDriverPtr driver, virDomainDefPtr def) */
typedef void (*virDrvReattachPciHostdevs) (virHostdevDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr *hostdevs, int nhostdevs); /* - workflow: unbind and bind to original driver, free usedby, activePciHostdevs and inactivePciHostdevs.
- reference: void qemuDomainReAttachHostdevDevices(virQEMUDriverPtrdriver, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs) */
typedef void (*virDrvReattachUsbHostdevs) (virHostdevDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr *hostdevs, int nhostdevs); /* - workflow: free usedby, activePciHostdevs and inactivePciHostdevs.
- reference: static void qemuDomainReAttachHostUsbDevices(virQEMUDriverPtr driver, const char *name, virDomainHostdevDefPtr *hostdevs, int nhostdevs) */
typedef virPCIDeviceListPtr (*virDrvGetActivePciHostdevList) (virHostdevDriverPtr driver); /* - could be used to check if a pci hostdev is already in-use. */
typedef virUSBDeviceListPtr (*virDrvGetActiveUsbHostdevList) (virHostdevDriverPtr driver); /* - could be used to check if a usb hostdev is already in-use. */
typedef virPCIDeviceListPtr (*virDrvGetDomainActivePciHostdevList) (virHostdevDriverPtr driver); /* - could be used to reattach all in-use pci hostdevs by a domain (e.g. when a domain shutdown) */
typedef virUSBDeviceListPtr (*virDrvGetDomainActiveUsbHostdevList) (virHostdevDriverPtr driver); /* - could be used to reattach all in-use usb hostdevs by a domain */
So it needs to expose the virPCI{USB}DeviceList to public. Not sure how useful it will be to expose the struct, instead of the ID of the devices.
The case I was considering here is: when reattaching hostdevs in vm shutoff, 'managed' or 'non-managed' info is also needed. But in this case, it is internally used, we can also handle that in virDrvReattachHostdevs. Could "managed=yes/no" info be used somewhere else? If not, then seems ID is enough.
"managed=yes/no" is only used by attaching/detaching, nodedev-dettach and nodedev-reattach.
These APIs could be used for node device driver. To filter the active/ inactive devices.
3. Use the module
* Register hostdev driver - define 'virHostdevDriverTab' and 'virHostdevDriverTabCount' - add hostdev driver register work in libvirtd.c daemonInitialize()
* add hostdev driver areas to _virConnect struct _virConnect { ....... virNWFilterDriverPtr nwfilterDriver; +++ virHostdevDriverPtr hostdevDriver;
....... void * nwfilterPrivateData; +++ void * hostdevPrivateData; ....... }
* add conn->hostdevDriver parser in libvirt.c: do_open() Then hypervisor drivers can get use of hostdev driver APIs.
* moments that could be affacted: - domain start/shutoff - attach/detach hostdev to domain
And libvirt restarting.
--------------------------------------------
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

On Fri, Mar 22, 2013 at 05:36:09PM +0800, Chunyan Liu wrote:
Hi, List,
As the mail I've sent a week before: https://www.redhat.com/archives/libvir-list/2013-March/msg00730.html I'm willing to push this work forward so that the passthrough APIs could be reused by qemu driver and libxl driver (which doesn't support pci passthrough yet and tries to add this function recently), or other drivers.
But since this work affacts a lot, I'm not sure if I can control it in a correct way. I write a draft to describe what I'm considering how to do, as in the following and in attachment. Hope to get your review, comment and guidence to improve the work before start coding. Any feedback will be very appreciated!
Thanks! Chunyan
------------------------ DRAFT:
Write separate module for hostdev passthrough
1. Purposes:
* Move hostdev passthrough APIs from qemu_hostdev.ch to separate module so that they could be reused by other hypervisors too
* Maintain global in-use state of hostdevs
2. Module design (draft):
* New module name: hostdev_driver
* New module files: hostdev_driver.ch hostdev_conf.ch
* New Definitions:
## [src/driver.h]
typedef struct _virHostdevDriver virHostdevDriver;
typedef virHostdevDriver *virHostdevDriverPtr;
struct _virHosedevDriver { const char *name; virDrvOpen open; virDrvClose close;
virDrvPrepareHostdevs prepareHostdevs; virDrvPreparePciHostdevs preparePciHostdevs; virDrvprepareUsbHostdevs prepareUsbHostdevs; virDrvReattachHostdevs reattachHostdevs; virDrvReattachPciHostdevs reattachPciHostdevs; virDrvReattachUsbHostdevs reattachUsbHostdevs; virDrvGetActivePciHostdevList getActivePciHostdevList; virDrvGetActiveUsbHostdevList getActiveUsbHostdevList; virDrvGetDomainActivePciHostdevList getDomainActivePciHostdevList; virDrvGetDomainActiveUsbHostdevList getDomainActiveUsbHostdevList; };
This is real overkill - we only need to do the driver table design for things which are public APIs with multiple pluggable implementations. For this scenario, we simply need one single set of internal APIs that any of the stateful hypervisor drivers can directly call into. Basically you just need to define some object to maintain the state eg virHostdevManagerPtr and a method to get the default shared instance of it virHostdevManagerPtr virHostdevManagerGetDefault(); and then the various APIs for interacting with it virHostdevManagerPrepareHostdevs(virHostdevManagerPtr mgr, ....); ...etc.. I'd just put this is all in a src/util/virhostdevmanager.{c,h} file. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

2013/4/17 Daniel P. Berrange <berrange@redhat.com>
On Fri, Mar 22, 2013 at 05:36:09PM +0800, Chunyan Liu wrote:
Hi, List,
As the mail I've sent a week before: https://www.redhat.com/archives/libvir-list/2013-March/msg00730.html I'm willing to push this work forward so that the passthrough APIs could be reused by qemu driver and libxl driver (which doesn't support pci passthrough yet and tries to add this function recently), or other drivers.
But since this work affacts a lot, I'm not sure if I can control it in a correct way. I write a draft to describe what I'm considering how to do, as in the following and in attachment. Hope to get your review, comment and guidence to improve the work before start coding. Any feedback will be very appreciated!
Thanks! Chunyan
------------------------ DRAFT:
Write separate module for hostdev passthrough
1. Purposes:
* Move hostdev passthrough APIs from qemu_hostdev.ch to separate module so that they could be reused by other hypervisors too
* Maintain global in-use state of hostdevs
2. Module design (draft):
* New module name: hostdev_driver
* New module files: hostdev_driver.ch hostdev_conf.ch
* New Definitions:
## [src/driver.h]
typedef struct _virHostdevDriver virHostdevDriver;
typedef virHostdevDriver *virHostdevDriverPtr;
struct _virHosedevDriver { const char *name; virDrvOpen open; virDrvClose close;
virDrvPrepareHostdevs prepareHostdevs; virDrvPreparePciHostdevs preparePciHostdevs; virDrvprepareUsbHostdevs prepareUsbHostdevs; virDrvReattachHostdevs reattachHostdevs; virDrvReattachPciHostdevs reattachPciHostdevs; virDrvReattachUsbHostdevs reattachUsbHostdevs; virDrvGetActivePciHostdevList getActivePciHostdevList; virDrvGetActiveUsbHostdevList getActiveUsbHostdevList; virDrvGetDomainActivePciHostdevList getDomainActivePciHostdevList; virDrvGetDomainActiveUsbHostdevList getDomainActiveUsbHostdevList; };
This is real overkill - we only need to do the driver table design for things which are public APIs with multiple pluggable implementations.
For this scenario, we simply need one single set of internal APIs that any of the stateful hypervisor drivers can directly call into. Basically you just need to define some object to maintain the state eg
virHostdevManagerPtr
and a method to get the default shared instance of it
virHostdevManagerPtr virHostdevManagerGetDefault();
and then the various APIs for interacting with it
virHostdevManagerPrepareHostdevs(virHostdevManagerPtr mgr, ....); ...etc..
I'd just put this is all in a src/util/virhostdevmanager.{c,h} file.
Got it. I'm writing it in the way you pointed, as a shared module instead of a driver, as Osier has pointed out too. Thanks for your suggestion about detail, I'll change code to follow that.
Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/:| |: http://libvirt.org -o- http://virt-manager.org:| |: http://autobuild.org -o- http://search.cpan.org/~danberr/:| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc:|
participants (3)
-
Chunyan Liu
-
Daniel P. Berrange
-
Osier Yang