1 /*
2  * node_device_driver.c: node device enumeration
3  *
4  * Copyright (C) 2010-2015 Red Hat, Inc.
5  * Copyright (C) 2008 Virtual Iron Software, Inc.
6  * Copyright (C) 2008 David F. Lively
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library.  If not, see
20  * <http://www.gnu.org/licenses/>.
21  */
22 
23 #include <config.h>
24 
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <time.h>
28 
29 #include "virerror.h"
30 #include "datatypes.h"
31 #include "domain_addr.h"
32 #include "viralloc.h"
33 #include "virfile.h"
34 #include "virjson.h"
35 #include "virstring.h"
36 #include "node_device_conf.h"
37 #include "node_device_event.h"
38 #include "node_device_driver.h"
39 #include "node_device_util.h"
40 #include "virvhba.h"
41 #include "viraccessapicheck.h"
42 #include "virnetdev.h"
43 #include "virutil.h"
44 #include "vircommand.h"
45 #include "virlog.h"
46 
47 #define VIR_FROM_THIS VIR_FROM_NODEDEV
48 
49 VIR_LOG_INIT("node_device.node_device_driver");
50 
51 virNodeDeviceDriverState *driver;
52 
53 
54 VIR_ENUM_IMPL(virMdevctlCommand,
55               MDEVCTL_CMD_LAST,
56               "start", "stop", "define", "undefine", "create"
57 );
58 
59 
60 #define MDEVCTL_ERROR(msg) (msg && msg[0] != '\0' ? msg : _("Unknown error"))
61 
62 
63 virDrvOpenStatus
nodeConnectOpen(virConnectPtr conn,virConnectAuthPtr auth G_GNUC_UNUSED,virConf * conf G_GNUC_UNUSED,unsigned int flags)64 nodeConnectOpen(virConnectPtr conn,
65                 virConnectAuthPtr auth G_GNUC_UNUSED,
66                 virConf *conf G_GNUC_UNUSED,
67                 unsigned int flags)
68 {
69     virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);
70 
71     if (driver == NULL) {
72         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
73                        _("nodedev state driver is not active"));
74         return VIR_DRV_OPEN_ERROR;
75     }
76 
77     if (!virConnectValidateURIPath(conn->uri->path,
78                                    "nodedev",
79                                    driver->privileged))
80         return VIR_DRV_OPEN_ERROR;
81 
82     if (virConnectOpenEnsureACL(conn) < 0)
83         return VIR_DRV_OPEN_ERROR;
84 
85     return VIR_DRV_OPEN_SUCCESS;
86 }
87 
nodeConnectClose(virConnectPtr conn G_GNUC_UNUSED)88 int nodeConnectClose(virConnectPtr conn G_GNUC_UNUSED)
89 {
90     return 0;
91 }
92 
93 
nodeConnectIsSecure(virConnectPtr conn G_GNUC_UNUSED)94 int nodeConnectIsSecure(virConnectPtr conn G_GNUC_UNUSED)
95 {
96     /* Trivially secure, since always inside the daemon */
97     return 1;
98 }
99 
100 
nodeConnectIsEncrypted(virConnectPtr conn G_GNUC_UNUSED)101 int nodeConnectIsEncrypted(virConnectPtr conn G_GNUC_UNUSED)
102 {
103     /* Not encrypted, but remote driver takes care of that */
104     return 0;
105 }
106 
107 
nodeConnectIsAlive(virConnectPtr conn G_GNUC_UNUSED)108 int nodeConnectIsAlive(virConnectPtr conn G_GNUC_UNUSED)
109 {
110     return 1;
111 }
112 
113 #if defined (__linux__) && defined(WITH_UDEV)
114 /* NB: It was previously believed that changes in driver name were
115  * relayed to libvirt as "change" events by udev, and the udev event
116  * notification is setup to recognize such events and effectively
117  * recreate the device entry in the cache. However, neither the kernel
118  * nor udev sends such an event, so it is necessary to manually update
119  * the driver name for a device each time its entry is used.
120  */
121 static int
nodeDeviceUpdateDriverName(virNodeDeviceDef * def)122 nodeDeviceUpdateDriverName(virNodeDeviceDef *def)
123 {
124     g_autofree char *driver_link = NULL;
125     g_autofree char *devpath = NULL;
126     char *p;
127 
128     VIR_FREE(def->driver);
129 
130     driver_link = g_strdup_printf("%s/driver", def->sysfs_path);
131 
132     /* Some devices don't have an explicit driver, so just return
133        without a name */
134     if (access(driver_link, R_OK) < 0)
135         return 0;
136 
137     if (virFileResolveLink(driver_link, &devpath) < 0) {
138         virReportSystemError(errno,
139                              _("cannot resolve driver link %s"), driver_link);
140         return -1;
141     }
142 
143     p = strrchr(devpath, '/');
144     if (p)
145         def->driver = g_strdup(p + 1);
146 
147     return 0;
148 }
149 #else
150 /* XXX: Implement me for non-linux */
151 static int
nodeDeviceUpdateDriverName(virNodeDeviceDef * def G_GNUC_UNUSED)152 nodeDeviceUpdateDriverName(virNodeDeviceDef *def G_GNUC_UNUSED)
153 {
154     return 0;
155 }
156 #endif
157 
158 
159 void
nodeDeviceLock(void)160 nodeDeviceLock(void)
161 {
162     virMutexLock(&driver->lock);
163 }
164 
165 
166 void
nodeDeviceUnlock(void)167 nodeDeviceUnlock(void)
168 {
169     virMutexUnlock(&driver->lock);
170 }
171 
172 
173 static int
nodeDeviceInitWait(void)174 nodeDeviceInitWait(void)
175 {
176     nodeDeviceLock();
177     while (!driver->initialized) {
178         if (virCondWait(&driver->initCond, &driver->lock) < 0) {
179             virReportSystemError(errno, "%s",
180                                  _("failed to wait on condition"));
181             nodeDeviceUnlock();
182             return -1;
183         }
184     }
185     nodeDeviceUnlock();
186     return 0;
187 }
188 
189 int
nodeNumOfDevices(virConnectPtr conn,const char * cap,unsigned int flags)190 nodeNumOfDevices(virConnectPtr conn,
191                  const char *cap,
192                  unsigned int flags)
193 {
194     if (virNodeNumOfDevicesEnsureACL(conn) < 0)
195         return -1;
196 
197     virCheckFlags(0, -1);
198 
199     if (nodeDeviceInitWait() < 0)
200         return -1;
201 
202     return virNodeDeviceObjListNumOfDevices(driver->devs, conn, cap,
203                                             virNodeNumOfDevicesCheckACL);
204 }
205 
206 
207 int
nodeListDevices(virConnectPtr conn,const char * cap,char ** const names,int maxnames,unsigned int flags)208 nodeListDevices(virConnectPtr conn,
209                 const char *cap,
210                 char **const names,
211                 int maxnames,
212                 unsigned int flags)
213 {
214     if (virNodeListDevicesEnsureACL(conn) < 0)
215         return -1;
216 
217     virCheckFlags(0, -1);
218 
219     if (nodeDeviceInitWait() < 0)
220         return -1;
221 
222     return virNodeDeviceObjListGetNames(driver->devs, conn,
223                                         virNodeListDevicesCheckACL,
224                                         cap, names, maxnames);
225 }
226 
227 
228 int
nodeConnectListAllNodeDevices(virConnectPtr conn,virNodeDevicePtr ** devices,unsigned int flags)229 nodeConnectListAllNodeDevices(virConnectPtr conn,
230                               virNodeDevicePtr **devices,
231                               unsigned int flags)
232 {
233     virCheckFlags(VIR_CONNECT_LIST_NODE_DEVICES_FILTERS_ALL, -1);
234 
235     if (virConnectListAllNodeDevicesEnsureACL(conn) < 0)
236         return -1;
237 
238     if (nodeDeviceInitWait() < 0)
239         return -1;
240 
241     return virNodeDeviceObjListExport(conn, driver->devs, devices,
242                                       virConnectListAllNodeDevicesCheckACL,
243                                       flags);
244 }
245 
246 
247 static virNodeDeviceObj *
nodeDeviceObjFindByName(const char * name)248 nodeDeviceObjFindByName(const char *name)
249 {
250     virNodeDeviceObj *obj;
251 
252     if (!(obj = virNodeDeviceObjListFindByName(driver->devs, name))) {
253         virReportError(VIR_ERR_NO_NODE_DEVICE,
254                        _("no node device with matching name '%s'"),
255                        name);
256     }
257 
258     return obj;
259 }
260 
261 
262 virNodeDevicePtr
nodeDeviceLookupByName(virConnectPtr conn,const char * name)263 nodeDeviceLookupByName(virConnectPtr conn,
264                        const char *name)
265 {
266     virNodeDeviceObj *obj;
267     virNodeDeviceDef *def;
268     virNodeDevicePtr device = NULL;
269 
270     if (nodeDeviceInitWait() < 0)
271         return NULL;
272 
273     if (!(obj = nodeDeviceObjFindByName(name)))
274         return NULL;
275     def = virNodeDeviceObjGetDef(obj);
276 
277     if (virNodeDeviceLookupByNameEnsureACL(conn, def) < 0)
278         goto cleanup;
279 
280     if ((device = virGetNodeDevice(conn, name)))
281         device->parentName = g_strdup(def->parent);
282 
283  cleanup:
284     virNodeDeviceObjEndAPI(&obj);
285     return device;
286 }
287 
288 
289 virNodeDevicePtr
nodeDeviceLookupSCSIHostByWWN(virConnectPtr conn,const char * wwnn,const char * wwpn,unsigned int flags)290 nodeDeviceLookupSCSIHostByWWN(virConnectPtr conn,
291                               const char *wwnn,
292                               const char *wwpn,
293                               unsigned int flags)
294 {
295     virNodeDeviceObj *obj = NULL;
296     virNodeDeviceDef *def;
297     virNodeDevicePtr device = NULL;
298 
299     virCheckFlags(0, NULL);
300 
301     if (nodeDeviceInitWait() < 0)
302         return NULL;
303 
304     if (!(obj = virNodeDeviceObjListFindSCSIHostByWWNs(driver->devs,
305                                                        wwnn, wwpn)))
306         return NULL;
307 
308     def = virNodeDeviceObjGetDef(obj);
309 
310     if (virNodeDeviceLookupSCSIHostByWWNEnsureACL(conn, def) < 0)
311         goto cleanup;
312 
313     if ((device = virGetNodeDevice(conn, def->name)))
314         device->parentName = g_strdup(def->parent);
315 
316  cleanup:
317     virNodeDeviceObjEndAPI(&obj);
318     return device;
319 }
320 
321 static virNodeDevicePtr
nodeDeviceLookupMediatedDeviceByUUID(virConnectPtr conn,const char * uuid,const char * parent_addr,unsigned int flags)322 nodeDeviceLookupMediatedDeviceByUUID(virConnectPtr conn,
323                                      const char *uuid,
324                                      const char *parent_addr,
325                                      unsigned int flags)
326 {
327     virNodeDeviceObj *obj = NULL;
328     virNodeDeviceDef *def;
329     virNodeDevicePtr device = NULL;
330 
331     virCheckFlags(0, NULL);
332 
333     if (!(obj = virNodeDeviceObjListFindMediatedDeviceByUUID(driver->devs,
334                                                              uuid, parent_addr)))
335         return NULL;
336 
337     def = virNodeDeviceObjGetDef(obj);
338 
339     if ((device = virGetNodeDevice(conn, def->name)))
340         device->parentName = g_strdup(def->parent);
341 
342     virNodeDeviceObjEndAPI(&obj);
343     return device;
344 }
345 
346 
347 char *
nodeDeviceGetXMLDesc(virNodeDevicePtr device,unsigned int flags)348 nodeDeviceGetXMLDesc(virNodeDevicePtr device,
349                      unsigned int flags)
350 {
351     virNodeDeviceObj *obj;
352     virNodeDeviceDef *def;
353     char *ret = NULL;
354 
355     virCheckFlags(0, NULL);
356 
357     if (nodeDeviceInitWait() < 0)
358         return NULL;
359 
360     if (!(obj = nodeDeviceObjFindByName(device->name)))
361         return NULL;
362     def = virNodeDeviceObjGetDef(obj);
363 
364     if (virNodeDeviceGetXMLDescEnsureACL(device->conn, def) < 0)
365         goto cleanup;
366 
367     if (nodeDeviceUpdateDriverName(def) < 0)
368         goto cleanup;
369 
370     if (virNodeDeviceUpdateCaps(def) < 0)
371         goto cleanup;
372 
373     ret = virNodeDeviceDefFormat(def);
374 
375  cleanup:
376     virNodeDeviceObjEndAPI(&obj);
377     return ret;
378 }
379 
380 
381 char *
nodeDeviceGetParent(virNodeDevicePtr device)382 nodeDeviceGetParent(virNodeDevicePtr device)
383 {
384     virNodeDeviceObj *obj;
385     virNodeDeviceDef *def;
386     char *ret = NULL;
387 
388     if (nodeDeviceInitWait() < 0)
389         return NULL;
390 
391     if (!(obj = nodeDeviceObjFindByName(device->name)))
392         return NULL;
393     def = virNodeDeviceObjGetDef(obj);
394 
395     if (virNodeDeviceGetParentEnsureACL(device->conn, def) < 0)
396         goto cleanup;
397 
398     if (def->parent) {
399         ret = g_strdup(def->parent);
400     } else {
401         virReportError(VIR_ERR_INTERNAL_ERROR,
402                        "%s", _("no parent for this device"));
403     }
404 
405  cleanup:
406     virNodeDeviceObjEndAPI(&obj);
407     return ret;
408 }
409 
410 
411 int
nodeDeviceNumOfCaps(virNodeDevicePtr device)412 nodeDeviceNumOfCaps(virNodeDevicePtr device)
413 {
414     virNodeDeviceObj *obj;
415     virNodeDeviceDef *def;
416     int ret = -1;
417 
418     if (nodeDeviceInitWait() < 0)
419         return -1;
420 
421     if (!(obj = nodeDeviceObjFindByName(device->name)))
422         return -1;
423     def = virNodeDeviceObjGetDef(obj);
424 
425     if (virNodeDeviceNumOfCapsEnsureACL(device->conn, def) < 0)
426         goto cleanup;
427 
428     ret = virNodeDeviceCapsListExport(def, NULL);
429 
430  cleanup:
431     virNodeDeviceObjEndAPI(&obj);
432     return ret;
433 }
434 
435 
436 
437 int
nodeDeviceListCaps(virNodeDevicePtr device,char ** const names,int maxnames)438 nodeDeviceListCaps(virNodeDevicePtr device,
439                    char **const names,
440                    int maxnames)
441 {
442     virNodeDeviceObj *obj;
443     virNodeDeviceDef *def;
444     virNodeDevCapType *list = NULL;
445     int ncaps = 0;
446     int ret = -1;
447     size_t i = 0;
448 
449     if (nodeDeviceInitWait() < 0)
450         return -1;
451 
452     if (!(obj = nodeDeviceObjFindByName(device->name)))
453         return -1;
454     def = virNodeDeviceObjGetDef(obj);
455 
456     if (virNodeDeviceListCapsEnsureACL(device->conn, def) < 0)
457         goto cleanup;
458 
459     if ((ncaps = virNodeDeviceCapsListExport(def, &list)) < 0)
460         goto cleanup;
461 
462     if (ncaps > maxnames)
463         ncaps = maxnames;
464 
465     for (i = 0; i < ncaps; i++)
466         names[i] = g_strdup(virNodeDevCapTypeToString(list[i]));
467 
468     ret = ncaps;
469 
470  cleanup:
471     virNodeDeviceObjEndAPI(&obj);
472     if (ret < 0) {
473         size_t j;
474         for (j = 0; j < i; j++)
475             VIR_FREE(names[j]);
476     }
477 
478     VIR_FREE(list);
479     return ret;
480 }
481 
482 
483 static int
nodeDeviceGetTime(time_t * t)484 nodeDeviceGetTime(time_t *t)
485 {
486     int ret = 0;
487 
488     *t = time(NULL);
489     if (*t == (time_t)-1) {
490         virReportError(VIR_ERR_INTERNAL_ERROR,
491                        "%s", _("Could not get current time"));
492 
493         *t = 0;
494         ret = -1;
495     }
496 
497     return ret;
498 }
499 
500 
501 typedef virNodeDevicePtr (*nodeDeviceFindNewDeviceFunc)(virConnectPtr conn,
502                                                         const void* opaque);
503 
504 
505 /* When large numbers of devices are present on the host, it's
506  * possible for udev not to realize that it has work to do before we
507  * get here.  We thus keep trying to find the new device we just
508  * created for up to LINUX_NEW_DEVICE_WAIT_TIME.  Note that udev's
509  * default settle time is 180 seconds, so once udev realizes that it
510  * has work to do, it might take that long for the udev wait to
511  * return.  Thus the total maximum time for this function to return is
512  * the udev settle time plus LINUX_NEW_DEVICE_WAIT_TIME.
513  *
514  * This whole area is a race, but if we retry the udev wait for
515  * LINUX_NEW_DEVICE_WAIT_TIME seconds and there's still no device,
516  * it's probably safe to assume it's not going to appear.
517  */
518 static virNodeDevicePtr
nodeDeviceFindNewDevice(virConnectPtr conn,nodeDeviceFindNewDeviceFunc func,const void * opaque)519 nodeDeviceFindNewDevice(virConnectPtr conn,
520                         nodeDeviceFindNewDeviceFunc func,
521                         const void *opaque)
522 {
523     virNodeDevicePtr device = NULL;
524     time_t start = 0, now = 0;
525 
526     nodeDeviceGetTime(&start);
527 
528     while ((now - start) < LINUX_NEW_DEVICE_WAIT_TIME) {
529 
530         virWaitForDevices();
531 
532         device = func(conn, opaque);
533 
534         if (device != NULL)
535             break;
536 
537         sleep(5);
538         if (nodeDeviceGetTime(&now) == -1)
539             break;
540     }
541 
542     return device;
543 }
544 
545 
546 typedef struct {
547     const char *uuid;
548     const char *parent_addr;
549 } NewMediatedDeviceData;
550 
551 static virNodeDevicePtr
nodeDeviceFindNewMediatedDeviceFunc(virConnectPtr conn,const void * opaque)552 nodeDeviceFindNewMediatedDeviceFunc(virConnectPtr conn,
553                                     const void *opaque)
554 {
555     const NewMediatedDeviceData *data = opaque;
556 
557     return nodeDeviceLookupMediatedDeviceByUUID(conn, data->uuid, data->parent_addr, 0);
558 }
559 
560 
561 static virNodeDevicePtr
nodeDeviceFindNewMediatedDevice(virConnectPtr conn,const char * mdev_uuid,const char * parent_addr)562 nodeDeviceFindNewMediatedDevice(virConnectPtr conn,
563                                 const char *mdev_uuid,
564                                 const char *parent_addr)
565 {
566     NewMediatedDeviceData data = {mdev_uuid, parent_addr};
567     return nodeDeviceFindNewDevice(conn, nodeDeviceFindNewMediatedDeviceFunc,
568                                    &data);
569 }
570 
571 
572 typedef struct _NewSCSIHostFuncData NewSCSIHostFuncData;
573 struct _NewSCSIHostFuncData
574 {
575     const char *wwnn;
576     const char *wwpn;
577 };
578 
579 
580 static virNodeDevicePtr
nodeDeviceFindNewSCSIHostFunc(virConnectPtr conn,const void * opaque)581 nodeDeviceFindNewSCSIHostFunc(virConnectPtr conn,
582                               const void *opaque)
583 {
584     const NewSCSIHostFuncData *data = opaque;
585 
586     return nodeDeviceLookupSCSIHostByWWN(conn, data->wwnn, data->wwpn, 0);
587 }
588 
589 
590 static virNodeDevicePtr
nodeDeviceFindNewSCSIHost(virConnectPtr conn,const char * wwnn,const char * wwpn)591 nodeDeviceFindNewSCSIHost(virConnectPtr conn,
592                           const char *wwnn,
593                           const char *wwpn)
594 {
595     NewSCSIHostFuncData data = { .wwnn = wwnn, .wwpn = wwpn};
596 
597     return nodeDeviceFindNewDevice(conn, nodeDeviceFindNewSCSIHostFunc, &data);
598 }
599 
600 
601 static bool
nodeDeviceHasCapability(virNodeDeviceDef * def,virNodeDevCapType type)602 nodeDeviceHasCapability(virNodeDeviceDef *def, virNodeDevCapType type)
603 {
604     virNodeDevCapsDef *cap = def->caps;
605 
606     while (cap != NULL) {
607         if (cap->data.type == type)
608             return true;
609         cap = cap->next;
610     }
611 
612     return false;
613 }
614 
615 
616 /* format a json string that provides configuration information about this mdev
617  * to the mdevctl utility */
618 static int
nodeDeviceDefToMdevctlConfig(virNodeDeviceDef * def,char ** buf)619 nodeDeviceDefToMdevctlConfig(virNodeDeviceDef *def, char **buf)
620 {
621     size_t i;
622     virNodeDevCapMdev *mdev = &def->caps->data.mdev;
623     g_autoptr(virJSONValue) json = virJSONValueNewObject();
624     const char *startval = mdev->autostart ? "auto" : "manual";
625 
626     if (virJSONValueObjectAppendString(json, "mdev_type", mdev->type) < 0)
627         return -1;
628 
629     if (virJSONValueObjectAppendString(json, "start", startval) < 0)
630         return -1;
631 
632     if (mdev->attributes) {
633         g_autoptr(virJSONValue) attributes = virJSONValueNewArray();
634 
635         for (i = 0; i < mdev->nattributes; i++) {
636             virMediatedDeviceAttr *attr = mdev->attributes[i];
637             g_autoptr(virJSONValue) jsonattr = virJSONValueNewObject();
638 
639             if (virJSONValueObjectAppendString(jsonattr, attr->name, attr->value) < 0)
640                 return -1;
641 
642             if (virJSONValueArrayAppend(attributes, &jsonattr) < 0)
643                 return -1;
644         }
645 
646         if (virJSONValueObjectAppend(json, "attrs", &attributes) < 0)
647             return -1;
648     }
649 
650     *buf = virJSONValueToString(json, false);
651     if (!*buf)
652         return -1;
653 
654     return 0;
655 }
656 
657 
658 static char *
nodeDeviceObjFormatAddress(virNodeDeviceObj * obj)659 nodeDeviceObjFormatAddress(virNodeDeviceObj *obj)
660 {
661     virNodeDevCapsDef *caps = NULL;
662     char *addr = NULL;
663     virNodeDeviceDef *def = virNodeDeviceObjGetDef(obj);
664     for (caps = def->caps; caps != NULL; caps = caps->next) {
665         switch (caps->data.type) {
666         case VIR_NODE_DEV_CAP_PCI_DEV: {
667             virPCIDeviceAddress pci_addr = {
668                 .domain = caps->data.pci_dev.domain,
669                 .bus = caps->data.pci_dev.bus,
670                 .slot = caps->data.pci_dev.slot,
671                 .function = caps->data.pci_dev.function
672             };
673 
674             addr = virPCIDeviceAddressAsString(&pci_addr);
675             break;
676             }
677 
678         case VIR_NODE_DEV_CAP_CSS_DEV: {
679             virDomainDeviceCCWAddress ccw_addr = {
680                 .cssid = caps->data.ccw_dev.cssid,
681                 .ssid = caps->data.ccw_dev.ssid,
682                 .devno = caps->data.ccw_dev.devno
683             };
684 
685             addr = virDomainCCWAddressAsString(&ccw_addr);
686             break;
687             }
688 
689         case VIR_NODE_DEV_CAP_AP_MATRIX:
690             addr = g_strdup(caps->data.ap_matrix.addr);
691             break;
692 
693         case VIR_NODE_DEV_CAP_SYSTEM:
694         case VIR_NODE_DEV_CAP_USB_DEV:
695         case VIR_NODE_DEV_CAP_USB_INTERFACE:
696         case VIR_NODE_DEV_CAP_NET:
697         case VIR_NODE_DEV_CAP_SCSI_HOST:
698         case VIR_NODE_DEV_CAP_SCSI_TARGET:
699         case VIR_NODE_DEV_CAP_SCSI:
700         case VIR_NODE_DEV_CAP_STORAGE:
701         case VIR_NODE_DEV_CAP_FC_HOST:
702         case VIR_NODE_DEV_CAP_VPORTS:
703         case VIR_NODE_DEV_CAP_SCSI_GENERIC:
704         case VIR_NODE_DEV_CAP_DRM:
705         case VIR_NODE_DEV_CAP_MDEV_TYPES:
706         case VIR_NODE_DEV_CAP_MDEV:
707         case VIR_NODE_DEV_CAP_CCW_DEV:
708         case VIR_NODE_DEV_CAP_VDPA:
709         case VIR_NODE_DEV_CAP_AP_CARD:
710         case VIR_NODE_DEV_CAP_AP_QUEUE:
711         case VIR_NODE_DEV_CAP_VPD:
712         case VIR_NODE_DEV_CAP_LAST:
713             break;
714         }
715 
716         if (addr)
717             break;
718     }
719 
720     return addr;
721 }
722 
723 
724 virCommand *
nodeDeviceGetMdevctlCommand(virNodeDeviceDef * def,virMdevctlCommand cmd_type,char ** outbuf,char ** errbuf)725 nodeDeviceGetMdevctlCommand(virNodeDeviceDef *def,
726                             virMdevctlCommand cmd_type,
727                             char **outbuf,
728                             char **errbuf)
729 {
730     g_autoptr(virCommand) cmd = NULL;
731     const char *subcommand = virMdevctlCommandTypeToString(cmd_type);
732     g_autofree char *inbuf = NULL;
733 
734     switch (cmd_type) {
735     case MDEVCTL_CMD_CREATE:
736         /* now is the time to make sure "create" is replaced with "start" on
737          * mdevctl cmdline */
738         cmd = virCommandNewArgList(MDEVCTL, "start", NULL);
739         break;
740     case MDEVCTL_CMD_STOP:
741     case MDEVCTL_CMD_START:
742     case MDEVCTL_CMD_DEFINE:
743     case MDEVCTL_CMD_UNDEFINE:
744         cmd = virCommandNewArgList(MDEVCTL, subcommand, NULL);
745         break;
746     case MDEVCTL_CMD_LAST:
747     default:
748         /* SHOULD NEVER HAPPEN */
749         virReportError(VIR_ERR_INTERNAL_ERROR,
750                        _("Unknown Command '%i'"), cmd_type);
751         return NULL;
752     }
753 
754     switch (cmd_type) {
755     case MDEVCTL_CMD_CREATE:
756     case MDEVCTL_CMD_DEFINE:
757         if (!def->caps->data.mdev.parent_addr) {
758             virReportError(VIR_ERR_INTERNAL_ERROR,
759                            _("unable to find parent device '%s'"), def->parent);
760             return NULL;
761         }
762 
763         if (nodeDeviceDefToMdevctlConfig(def, &inbuf) < 0) {
764             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
765                            _("couldn't convert node device def to mdevctl JSON"));
766             return NULL;
767         }
768 
769         virCommandAddArgPair(cmd, "--parent", def->caps->data.mdev.parent_addr);
770         virCommandAddArgPair(cmd, "--jsonfile", "/dev/stdin");
771 
772         virCommandSetInputBuffer(cmd, inbuf);
773         virCommandSetOutputBuffer(cmd, outbuf);
774         break;
775 
776     case MDEVCTL_CMD_UNDEFINE:
777     case MDEVCTL_CMD_STOP:
778     case MDEVCTL_CMD_START:
779         /* No special handling here, we only need to pass UUID with these */
780         break;
781     case MDEVCTL_CMD_LAST:
782     default:
783         /* SHOULD NEVER HAPPEN */
784         break;
785     }
786 
787     /* Fill in UUID for commands that need it */
788     if (def->caps->data.mdev.uuid)
789         virCommandAddArgPair(cmd, "--uuid", def->caps->data.mdev.uuid);
790 
791     virCommandSetErrorBuffer(cmd, errbuf);
792 
793     return g_steal_pointer(&cmd);
794 }
795 
796 
797 static int
virMdevctlCreate(virNodeDeviceDef * def,char ** uuid)798 virMdevctlCreate(virNodeDeviceDef *def, char **uuid)
799 {
800     int status;
801     g_autofree char *errmsg = NULL;
802     g_autoptr(virCommand) cmd = nodeDeviceGetMdevctlCommand(def,
803                                                             MDEVCTL_CMD_CREATE,
804                                                             uuid,
805                                                             &errmsg);
806 
807     if (!cmd)
808         return -1;
809 
810     /* an auto-generated uuid is returned via stdout if no uuid is specified in
811      * the mdevctl args */
812     if (virCommandRun(cmd, &status) < 0)
813         return -1;
814 
815     if (status != 0) {
816         virReportError(VIR_ERR_INTERNAL_ERROR,
817                        _("Unable to start mediated device: %s"),
818                        MDEVCTL_ERROR(errmsg));
819         return -1;
820     }
821 
822     /* remove newline */
823     *uuid = g_strstrip(*uuid);
824     return 0;
825 }
826 
827 
828 static int
virMdevctlDefine(virNodeDeviceDef * def,char ** uuid)829 virMdevctlDefine(virNodeDeviceDef *def, char **uuid)
830 {
831     int status;
832     g_autofree char *errmsg = NULL;
833     g_autoptr(virCommand) cmd = nodeDeviceGetMdevctlCommand(def,
834                                                             MDEVCTL_CMD_DEFINE,
835                                                             uuid, &errmsg);
836 
837     if (!cmd)
838         return -1;
839 
840     /* an auto-generated uuid is returned via stdout if no uuid is specified in
841      * the mdevctl args */
842     if (virCommandRun(cmd, &status) < 0)
843         return -1;
844 
845     if (status != 0) {
846         virReportError(VIR_ERR_INTERNAL_ERROR,
847                        _("Unable to define mediated device: %s"),
848                        MDEVCTL_ERROR(errmsg));
849         return -1;
850     }
851 
852     /* remove newline */
853     *uuid = g_strstrip(*uuid);
854     return 0;
855 }
856 
857 
858 static virNodeDevicePtr
nodeDeviceCreateXMLMdev(virConnectPtr conn,virNodeDeviceDef * def)859 nodeDeviceCreateXMLMdev(virConnectPtr conn,
860                         virNodeDeviceDef *def)
861 {
862     g_autofree char *uuid = NULL;
863 
864     if (!def->parent) {
865         virReportError(VIR_ERR_XML_ERROR, "%s",
866                        _("cannot create a mediated device without a parent"));
867         return NULL;
868     }
869 
870     if (virMdevctlCreate(def, &uuid) < 0) {
871         return NULL;
872     }
873 
874     if (uuid && uuid[0]) {
875         g_free(def->caps->data.mdev.uuid);
876         def->caps->data.mdev.uuid = g_steal_pointer(&uuid);
877     }
878 
879     return nodeDeviceFindNewMediatedDevice(conn, def->caps->data.mdev.uuid,
880                                            def->caps->data.mdev.parent_addr);
881 }
882 
883 
884 virNodeDevicePtr
nodeDeviceCreateXML(virConnectPtr conn,const char * xmlDesc,unsigned int flags)885 nodeDeviceCreateXML(virConnectPtr conn,
886                     const char *xmlDesc,
887                     unsigned int flags)
888 {
889     g_autoptr(virNodeDeviceDef) def = NULL;
890     g_autofree char *wwnn = NULL;
891     g_autofree char *wwpn = NULL;
892     virNodeDevicePtr device = NULL;
893     const char *virt_type = NULL;
894 
895     virCheckFlags(0, NULL);
896 
897     if (nodeDeviceInitWait() < 0)
898         return NULL;
899 
900     virt_type  = virConnectGetType(conn);
901 
902     if (!(def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, virt_type,
903                                             &driver->parserCallbacks, NULL)))
904         return NULL;
905 
906     if (virNodeDeviceCreateXMLEnsureACL(conn, def) < 0)
907         return NULL;
908 
909     if (nodeDeviceHasCapability(def, VIR_NODE_DEV_CAP_SCSI_HOST)) {
910         int parent_host;
911 
912         if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1)
913             return NULL;
914 
915         if ((parent_host = virNodeDeviceObjListGetParentHost(driver->devs, def)) < 0)
916             return NULL;
917 
918         if (virVHBAManageVport(parent_host, wwpn, wwnn, VPORT_CREATE) < 0)
919             return NULL;
920 
921         device = nodeDeviceFindNewSCSIHost(conn, wwnn, wwpn);
922         /* We don't check the return value, because one way or another,
923          * we're returning what we get... */
924 
925         if (device == NULL)
926             virReportError(VIR_ERR_NO_NODE_DEVICE,
927                            _("no node device for '%s' with matching "
928                              "wwnn '%s' and wwpn '%s'"),
929                            def->name, wwnn, wwpn);
930     } else if (nodeDeviceHasCapability(def, VIR_NODE_DEV_CAP_MDEV)) {
931         device = nodeDeviceCreateXMLMdev(conn, def);
932     } else {
933         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
934                        _("Unsupported device type"));
935     }
936 
937     return device;
938 }
939 
940 
941 static int
virMdevctlStop(virNodeDeviceDef * def)942 virMdevctlStop(virNodeDeviceDef *def)
943 {
944     int status;
945     g_autoptr(virCommand) cmd = NULL;
946     g_autofree char *errmsg = NULL;
947 
948     cmd = nodeDeviceGetMdevctlCommand(def, MDEVCTL_CMD_STOP, NULL, &errmsg);
949 
950     if (!cmd)
951         return -1;
952 
953     if (virCommandRun(cmd, &status) < 0)
954         return -1;
955 
956     if (status != 0) {
957         virReportError(VIR_ERR_INTERNAL_ERROR,
958                        _("Unable to destroy '%s': %s"), def->name,
959                        MDEVCTL_ERROR(errmsg));
960         return -1;
961     }
962 
963     return 0;
964 }
965 
966 
967 static int
virMdevctlUndefine(virNodeDeviceDef * def)968 virMdevctlUndefine(virNodeDeviceDef *def)
969 {
970     int status;
971     g_autoptr(virCommand) cmd = NULL;
972     g_autofree char *errmsg = NULL;
973 
974     cmd = nodeDeviceGetMdevctlCommand(def, MDEVCTL_CMD_UNDEFINE, NULL, &errmsg);
975 
976     if (!cmd)
977         return -1;
978 
979     if (virCommandRun(cmd, &status) < 0)
980         return -1;
981 
982     if (status != 0) {
983         virReportError(VIR_ERR_INTERNAL_ERROR,
984                        _("Unable to undefine mediated device: %s"),
985                        MDEVCTL_ERROR(errmsg));
986         return -1;
987     }
988 
989     return 0;
990 }
991 
992 
993 static int
virMdevctlStart(virNodeDeviceDef * def)994 virMdevctlStart(virNodeDeviceDef *def)
995 {
996     int status;
997     g_autoptr(virCommand) cmd = NULL;
998     g_autofree char *errmsg = NULL;
999 
1000     cmd = nodeDeviceGetMdevctlCommand(def, MDEVCTL_CMD_START, NULL, &errmsg);
1001 
1002     if (!cmd)
1003         return -1;
1004 
1005     if (virCommandRun(cmd, &status) < 0)
1006         return -1;
1007 
1008     if (status != 0) {
1009         virReportError(VIR_ERR_INTERNAL_ERROR,
1010                        _("Unable to create mediated device: %s"),
1011                        MDEVCTL_ERROR(errmsg));
1012         return -1;
1013     }
1014 
1015     return 0;
1016 }
1017 
1018 
1019 /* gets a virCommand object that executes a mdevctl command to set the
1020  * 'autostart' property of the device to the specified value
1021  */
1022 virCommand*
nodeDeviceGetMdevctlSetAutostartCommand(virNodeDeviceDef * def,bool autostart,char ** errmsg)1023 nodeDeviceGetMdevctlSetAutostartCommand(virNodeDeviceDef *def,
1024                                         bool autostart,
1025                                         char **errmsg)
1026 {
1027     virCommand *cmd = virCommandNewArgList(MDEVCTL,
1028                                            "modify",
1029                                            "--uuid",
1030                                            def->caps->data.mdev.uuid,
1031                                            NULL);
1032 
1033     if (autostart)
1034         virCommandAddArg(cmd, "--auto");
1035     else
1036         virCommandAddArg(cmd, "--manual");
1037 
1038     virCommandSetErrorBuffer(cmd, errmsg);
1039 
1040     return cmd;
1041 }
1042 
1043 
1044 static int
virMdevctlSetAutostart(virNodeDeviceDef * def,bool autostart,char ** errmsg)1045 virMdevctlSetAutostart(virNodeDeviceDef *def, bool autostart, char **errmsg)
1046 {
1047     int status;
1048     g_autoptr(virCommand) cmd = NULL;
1049 
1050     cmd = nodeDeviceGetMdevctlSetAutostartCommand(def, autostart, errmsg);
1051 
1052     if (virCommandRun(cmd, &status) < 0 || status != 0)
1053         return -1;
1054 
1055     return 0;
1056 }
1057 
1058 
1059 virCommand*
nodeDeviceGetMdevctlListCommand(bool defined,char ** output,char ** errmsg)1060 nodeDeviceGetMdevctlListCommand(bool defined,
1061                                 char **output,
1062                                 char **errmsg)
1063 {
1064     virCommand *cmd = virCommandNewArgList(MDEVCTL,
1065                                            "list",
1066                                            "--dumpjson",
1067                                            NULL);
1068 
1069     if (defined)
1070         virCommandAddArg(cmd, "--defined");
1071 
1072     virCommandSetOutputBuffer(cmd, output);
1073     virCommandSetErrorBuffer(cmd, errmsg);
1074 
1075     return cmd;
1076 }
1077 
1078 
mdevGenerateDeviceName(virNodeDeviceDef * dev)1079 static void mdevGenerateDeviceName(virNodeDeviceDef *dev)
1080 {
1081     nodeDeviceGenerateName(dev, "mdev", dev->caps->data.mdev.uuid,
1082                            dev->caps->data.mdev.parent_addr);
1083 }
1084 
1085 
1086 static bool
matchDeviceAddress(virNodeDeviceObj * obj,const void * opaque)1087 matchDeviceAddress(virNodeDeviceObj *obj,
1088                    const void *opaque)
1089 {
1090     g_autofree char *addr = NULL;
1091     bool want = false;
1092 
1093     virObjectLock(obj);
1094     addr = nodeDeviceObjFormatAddress(obj);
1095     want = STREQ_NULLABLE(addr, opaque);
1096     virObjectUnlock(obj);
1097     return want;
1098 }
1099 
1100 
1101 static virNodeDeviceDef*
nodeDeviceParseMdevctlChildDevice(const char * parent,virJSONValue * json)1102 nodeDeviceParseMdevctlChildDevice(const char *parent,
1103                                   virJSONValue *json)
1104 {
1105     virNodeDevCapMdev *mdev;
1106     const char *uuid;
1107     virJSONValue *props;
1108     virJSONValue *attrs;
1109     g_autoptr(virNodeDeviceDef) child = g_new0(virNodeDeviceDef, 1);
1110     virNodeDeviceObj *parent_obj;
1111     const char *start = NULL;
1112 
1113     /* the child object should have a single key equal to its uuid.
1114      * The value is an object describing the properties of the mdev */
1115     if (virJSONValueObjectKeysNumber(json) != 1)
1116         return NULL;
1117 
1118     uuid = virJSONValueObjectGetKey(json, 0);
1119     props = virJSONValueObjectGetValue(json, 0);
1120 
1121     /* Look up id of parent device. mdevctl supports defining mdevs for parent
1122      * devices that are not present on the system (to support starting mdevs on
1123      * hotplug, etc) so the parent may not actually exist. */
1124     if ((parent_obj = virNodeDeviceObjListFind(driver->devs, matchDeviceAddress,
1125                                                (void *)parent))) {
1126         virNodeDeviceDef *parentdef = virNodeDeviceObjGetDef(parent_obj);
1127         child->parent = g_strdup(parentdef->name);
1128         virNodeDeviceObjEndAPI(&parent_obj);
1129     };
1130     if (!child->parent)
1131         child->parent = g_strdup("computer");
1132     child->caps = g_new0(virNodeDevCapsDef, 1);
1133     child->caps->data.type = VIR_NODE_DEV_CAP_MDEV;
1134 
1135     mdev = &child->caps->data.mdev;
1136     mdev->uuid = g_strdup(uuid);
1137     mdev->parent_addr = g_strdup(parent);
1138     mdev->type =
1139         g_strdup(virJSONValueObjectGetString(props, "mdev_type"));
1140     start = virJSONValueObjectGetString(props, "start");
1141     mdev->autostart = STREQ_NULLABLE(start, "auto");
1142 
1143     attrs = virJSONValueObjectGet(props, "attrs");
1144 
1145     if (attrs && virJSONValueIsArray(attrs)) {
1146         size_t i;
1147         int nattrs = virJSONValueArraySize(attrs);
1148 
1149         mdev->attributes = g_new0(virMediatedDeviceAttr*, nattrs);
1150         mdev->nattributes = nattrs;
1151 
1152         for (i = 0; i < nattrs; i++) {
1153             virJSONValue *attr = virJSONValueArrayGet(attrs, i);
1154             virMediatedDeviceAttr *attribute;
1155             virJSONValue *value;
1156 
1157             if (!virJSONValueIsObject(attr) ||
1158                 virJSONValueObjectKeysNumber(attr) != 1)
1159                 return NULL;
1160 
1161             attribute = g_new0(virMediatedDeviceAttr, 1);
1162             attribute->name = g_strdup(virJSONValueObjectGetKey(attr, 0));
1163             value = virJSONValueObjectGetValue(attr, 0);
1164             attribute->value = g_strdup(virJSONValueGetString(value));
1165             mdev->attributes[i] = attribute;
1166         }
1167     }
1168     mdevGenerateDeviceName(child);
1169 
1170     return g_steal_pointer(&child);
1171 }
1172 
1173 
1174 int
nodeDeviceParseMdevctlJSON(const char * jsonstring,virNodeDeviceDef *** devs)1175 nodeDeviceParseMdevctlJSON(const char *jsonstring,
1176                            virNodeDeviceDef ***devs)
1177 {
1178     int n;
1179     g_autoptr(virJSONValue) json_devicelist = NULL;
1180     virNodeDeviceDef **outdevs = NULL;
1181     size_t noutdevs = 0;
1182     size_t i;
1183     size_t j;
1184     virJSONValue *obj;
1185 
1186     json_devicelist = virJSONValueFromString(jsonstring);
1187 
1188     if (!json_devicelist || !virJSONValueIsArray(json_devicelist)) {
1189         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1190                        _("mdevctl JSON response contains no devices"));
1191         goto error;
1192     }
1193 
1194     if (virJSONValueArraySize(json_devicelist) == 0) {
1195         VIR_DEBUG("mdevctl has no defined mediated devices");
1196         *devs = NULL;
1197         return 0;
1198     }
1199 
1200     /* mdevctl list --dumpjson produces an output that is an array that
1201      * contains only a single object which contains a property for each parent
1202      * device */
1203     if (virJSONValueArraySize(json_devicelist) != 1) {
1204         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1205                        _("Unexpected format for mdevctl response"));
1206         goto error;
1207     }
1208 
1209     obj = virJSONValueArrayGet(json_devicelist, 0);
1210 
1211     if (!virJSONValueIsObject(obj)) {
1212         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1213                        _("device list is not an object"));
1214         goto error;
1215     }
1216 
1217     n = virJSONValueObjectKeysNumber(obj);
1218     for (i = 0; i < n; i++) {
1219         const char *parent;
1220         virJSONValue *child_array;
1221         int nchildren;
1222 
1223         /* The key of each object property is the name of a parent device
1224          * which maps to an array of child devices */
1225         parent = virJSONValueObjectGetKey(obj, i);
1226         child_array = virJSONValueObjectGetValue(obj, i);
1227 
1228         if (!virJSONValueIsArray(child_array)) {
1229             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1230                            _("Parent device's JSON object data is not an array"));
1231             goto error;
1232         }
1233 
1234         nchildren = virJSONValueArraySize(child_array);
1235 
1236         for (j = 0; j < nchildren; j++) {
1237             g_autoptr(virNodeDeviceDef) child = NULL;
1238             virJSONValue *child_obj = virJSONValueArrayGet(child_array, j);
1239 
1240             if (!(child = nodeDeviceParseMdevctlChildDevice(parent, child_obj))) {
1241                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1242                                _("Unable to parse child device"));
1243                 goto error;
1244             }
1245 
1246             VIR_APPEND_ELEMENT(outdevs, noutdevs, child);
1247         }
1248     }
1249 
1250     *devs = outdevs;
1251     return noutdevs;
1252 
1253  error:
1254     for (i = 0; i < noutdevs; i++)
1255         virNodeDeviceDefFree(outdevs[i]);
1256     VIR_FREE(outdevs);
1257     return -1;
1258 }
1259 
1260 
1261 int
nodeDeviceDestroy(virNodeDevicePtr device)1262 nodeDeviceDestroy(virNodeDevicePtr device)
1263 {
1264     int ret = -1;
1265     virNodeDeviceObj *obj = NULL;
1266     virNodeDeviceDef *def;
1267     g_autofree char *parent = NULL;
1268     g_autofree char *wwnn = NULL;
1269     g_autofree char *wwpn = NULL;
1270     unsigned int parent_host;
1271 
1272     if (nodeDeviceInitWait() < 0)
1273         return -1;
1274 
1275     if (!(obj = nodeDeviceObjFindByName(device->name)))
1276         return -1;
1277     def = virNodeDeviceObjGetDef(obj);
1278 
1279     if (virNodeDeviceDestroyEnsureACL(device->conn, def) < 0)
1280         goto cleanup;
1281 
1282     if (nodeDeviceHasCapability(def, VIR_NODE_DEV_CAP_SCSI_HOST)) {
1283         if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) < 0)
1284             goto cleanup;
1285 
1286         /* Because we're about to release the lock and thus run into a race
1287          * possibility (however improbable) with a udevAddOneDevice change
1288          * event which would essentially free the existing @def (obj->def) and
1289          * replace it with something new, we need to grab the parent field
1290          * and then find the parent obj in order to manage the vport */
1291         parent = g_strdup(def->parent);
1292 
1293         virNodeDeviceObjEndAPI(&obj);
1294 
1295         if (!(obj = virNodeDeviceObjListFindByName(driver->devs, parent))) {
1296             virReportError(VIR_ERR_INTERNAL_ERROR,
1297                            _("cannot find parent '%s' definition"), parent);
1298             goto cleanup;
1299         }
1300 
1301         if (virSCSIHostGetNumber(parent, &parent_host) < 0)
1302             goto cleanup;
1303 
1304         if (virVHBAManageVport(parent_host, wwpn, wwnn, VPORT_DELETE) < 0)
1305             goto cleanup;
1306 
1307         ret = 0;
1308     } else if (nodeDeviceHasCapability(def, VIR_NODE_DEV_CAP_MDEV)) {
1309         g_autofree char *vfiogroup = NULL;
1310         VIR_AUTOCLOSE fd = -1;
1311 
1312         if (!virNodeDeviceObjIsActive(obj)) {
1313             virReportError(VIR_ERR_OPERATION_INVALID,
1314                            _("Device '%s' is not active"), def->name);
1315             goto cleanup;
1316         }
1317 
1318         /* If this mediated device is in use by a vm, attempting to stop it
1319          * will block until the vm closes the device. The nodedev driver
1320          * cannot query the hypervisor driver to determine whether the device
1321          * is in use by any active domains, since that would introduce circular
1322          * dependencies between daemons and add a risk of deadlocks. So we need
1323          * to resort to a workaround.  vfio only allows the group for a device
1324          * to be opened by one user at a time. So if we get EBUSY when opening
1325          * the group, we infer that the device is in use and therefore we
1326          * shouldn't try to remove the device. */
1327         vfiogroup = virMediatedDeviceGetIOMMUGroupDev(def->caps->data.mdev.uuid);
1328         if (!vfiogroup)
1329             goto cleanup;
1330 
1331         fd = open(vfiogroup, O_RDONLY);
1332 
1333         if (fd < 0 && errno == EBUSY) {
1334             virReportError(VIR_ERR_INTERNAL_ERROR,
1335                            _("Unable to destroy '%s': device in use"),
1336                            def->name);
1337             goto cleanup;
1338         }
1339 
1340         if (virMdevctlStop(def) < 0)
1341             goto cleanup;
1342 
1343         ret = 0;
1344     } else {
1345         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1346                        _("Unsupported device type"));
1347     }
1348 
1349  cleanup:
1350     virNodeDeviceObjEndAPI(&obj);
1351     return ret;
1352 }
1353 
1354 
1355 /* takes ownership of @def and potentially frees it. @def should not be used
1356  * after returning from this function */
1357 static int
nodeDeviceUpdateMediatedDevice(virNodeDeviceDef * def)1358 nodeDeviceUpdateMediatedDevice(virNodeDeviceDef *def)
1359 {
1360     virNodeDeviceObj *obj;
1361     virObjectEvent *event;
1362     bool defined = false;
1363     g_autoptr(virNodeDeviceDef) owned = def;
1364     g_autofree char *name = g_strdup(owned->name);
1365 
1366     owned->driver = g_strdup("vfio_mdev");
1367 
1368     if (!(obj = virNodeDeviceObjListFindByName(driver->devs, owned->name))) {
1369         virNodeDeviceDef *d = g_steal_pointer(&owned);
1370         if (!(obj = virNodeDeviceObjListAssignDef(driver->devs, d))) {
1371             virNodeDeviceDefFree(d);
1372             return -1;
1373         }
1374     } else {
1375         bool changed;
1376         virNodeDeviceDef *olddef = virNodeDeviceObjGetDef(obj);
1377 
1378         defined = virNodeDeviceObjIsPersistent(obj);
1379         /* Active devices contain some additional information (e.g. sysfs
1380          * path) that is not provided by mdevctl, so re-use the existing
1381          * definition and copy over new mdev data */
1382         changed = nodeDeviceDefCopyFromMdevctl(olddef, owned);
1383 
1384         if (defined && !changed) {
1385             /* if this device was already defined and the definition
1386              * hasn't changed, there's nothing to do for this device */
1387             virNodeDeviceObjEndAPI(&obj);
1388             return 0;
1389         }
1390     }
1391 
1392     /* all devices returned by virMdevctlListDefined() are persistent */
1393     virNodeDeviceObjSetPersistent(obj, true);
1394     virNodeDeviceObjSetAutostart(obj, def->caps->data.mdev.autostart);
1395 
1396     if (!defined)
1397         event = virNodeDeviceEventLifecycleNew(name,
1398                                                VIR_NODE_DEVICE_EVENT_DEFINED,
1399                                                0);
1400     else
1401         event = virNodeDeviceEventUpdateNew(name);
1402 
1403     virNodeDeviceObjEndAPI(&obj);
1404     virObjectEventStateQueue(driver->nodeDeviceEventState, event);
1405 
1406     return 0;
1407 }
1408 
1409 
1410 virNodeDevice*
nodeDeviceDefineXML(virConnect * conn,const char * xmlDesc,unsigned int flags)1411 nodeDeviceDefineXML(virConnect *conn,
1412                     const char *xmlDesc,
1413                     unsigned int flags)
1414 {
1415     g_autoptr(virNodeDeviceDef) def = NULL;
1416     const char *virt_type = NULL;
1417     g_autofree char *uuid = NULL;
1418     g_autofree char *name = NULL;
1419 
1420     virCheckFlags(0, NULL);
1421 
1422     if (nodeDeviceInitWait() < 0)
1423         return NULL;
1424 
1425     virt_type  = virConnectGetType(conn);
1426 
1427     if (!(def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, virt_type,
1428                                             &driver->parserCallbacks, NULL)))
1429         return NULL;
1430 
1431     if (virNodeDeviceDefineXMLEnsureACL(conn, def) < 0)
1432         return NULL;
1433 
1434     if (!nodeDeviceHasCapability(def, VIR_NODE_DEV_CAP_MDEV)) {
1435         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1436                        _("Unsupported device type"));
1437         return NULL;
1438     }
1439 
1440     if (!def->parent) {
1441         virReportError(VIR_ERR_XML_ERROR, "%s",
1442                        _("cannot define a mediated device without a parent"));
1443         return NULL;
1444     }
1445 
1446     if (virMdevctlDefine(def, &uuid) < 0) {
1447         return NULL;
1448     }
1449 
1450     if (uuid && uuid[0]) {
1451         g_free(def->caps->data.mdev.uuid);
1452         def->caps->data.mdev.uuid = g_steal_pointer(&uuid);
1453     }
1454 
1455     mdevGenerateDeviceName(def);
1456     name = g_strdup(def->name);
1457 
1458     /* Normally we would call nodeDeviceFindNewMediatedDevice() here to wait
1459      * for the new device to appear. But mdevctl can take a while to query
1460      * devices, and if nodeDeviceFindNewMediatedDevice() doesn't find the new
1461      * device immediately it will wait for 5s before checking again. Since we
1462      * have already received the uuid from virMdevctlDefine(), we can simply
1463      * add the provisional device to the list and return it immediately and
1464      * avoid this long delay. */
1465     if (nodeDeviceUpdateMediatedDevice(g_steal_pointer(&def)) < 0)
1466         return NULL;
1467 
1468     return virGetNodeDevice(conn, name);
1469 }
1470 
1471 
1472 int
nodeDeviceUndefine(virNodeDevice * device,unsigned int flags)1473 nodeDeviceUndefine(virNodeDevice *device,
1474                    unsigned int flags)
1475 {
1476     int ret = -1;
1477     virNodeDeviceObj *obj = NULL;
1478     virNodeDeviceDef *def;
1479 
1480     virCheckFlags(0, -1);
1481 
1482     if (nodeDeviceInitWait() < 0)
1483         return -1;
1484 
1485     if (!(obj = nodeDeviceObjFindByName(device->name)))
1486         return -1;
1487 
1488     def = virNodeDeviceObjGetDef(obj);
1489 
1490     if (virNodeDeviceUndefineEnsureACL(device->conn, def) < 0)
1491         goto cleanup;
1492 
1493     if (!virNodeDeviceObjIsPersistent(obj)) {
1494         virReportError(VIR_ERR_OPERATION_INVALID,
1495                        _("Node device '%s' is not defined"),
1496                        def->name);
1497         goto cleanup;
1498     }
1499 
1500     if (nodeDeviceHasCapability(def, VIR_NODE_DEV_CAP_MDEV)) {
1501         if (virMdevctlUndefine(def) < 0)
1502             goto cleanup;
1503 
1504         ret = 0;
1505     } else {
1506         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1507                        _("Unsupported device type"));
1508     }
1509 
1510  cleanup:
1511     virNodeDeviceObjEndAPI(&obj);
1512     return ret;
1513 }
1514 
1515 
1516 int
nodeDeviceCreate(virNodeDevice * device,unsigned int flags)1517 nodeDeviceCreate(virNodeDevice *device,
1518                  unsigned int flags)
1519 {
1520     int ret = -1;
1521     virNodeDeviceObj *obj = NULL;
1522     virNodeDeviceDef *def = NULL;
1523 
1524     virCheckFlags(0, -1);
1525 
1526     if (nodeDeviceInitWait() < 0)
1527         return -1;
1528 
1529     if (!(obj = nodeDeviceObjFindByName(device->name)))
1530         return -1;
1531 
1532     if (virNodeDeviceObjIsActive(obj)) {
1533         virReportError(VIR_ERR_OPERATION_INVALID, "%s",
1534                        _("Device is already active"));
1535         goto cleanup;
1536     }
1537     def = virNodeDeviceObjGetDef(obj);
1538 
1539     if (virNodeDeviceCreateEnsureACL(device->conn, def) < 0)
1540         goto cleanup;
1541 
1542     if (nodeDeviceHasCapability(def, VIR_NODE_DEV_CAP_MDEV)) {
1543         if (virMdevctlStart(def) < 0)
1544             goto cleanup;
1545 
1546         ret = 0;
1547     } else {
1548         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1549                        _("Unsupported device type"));
1550     }
1551 
1552  cleanup:
1553     virNodeDeviceObjEndAPI(&obj);
1554     return ret;
1555 }
1556 
1557 
1558 int
nodeConnectNodeDeviceEventRegisterAny(virConnectPtr conn,virNodeDevicePtr device,int eventID,virConnectNodeDeviceEventGenericCallback callback,void * opaque,virFreeCallback freecb)1559 nodeConnectNodeDeviceEventRegisterAny(virConnectPtr conn,
1560                                       virNodeDevicePtr device,
1561                                       int eventID,
1562                                       virConnectNodeDeviceEventGenericCallback callback,
1563                                       void *opaque,
1564                                       virFreeCallback freecb)
1565 {
1566     int callbackID = -1;
1567 
1568     if (virConnectNodeDeviceEventRegisterAnyEnsureACL(conn) < 0)
1569         return -1;
1570 
1571     if (nodeDeviceInitWait() < 0)
1572         return -1;
1573 
1574     if (virNodeDeviceEventStateRegisterID(conn, driver->nodeDeviceEventState,
1575                                           device, eventID, callback,
1576                                           opaque, freecb, &callbackID) < 0)
1577         callbackID = -1;
1578 
1579     return callbackID;
1580 }
1581 
1582 
1583 int
nodeConnectNodeDeviceEventDeregisterAny(virConnectPtr conn,int callbackID)1584 nodeConnectNodeDeviceEventDeregisterAny(virConnectPtr conn,
1585                                         int callbackID)
1586 {
1587     if (virConnectNodeDeviceEventDeregisterAnyEnsureACL(conn) < 0)
1588         return -1;
1589 
1590     if (nodeDeviceInitWait() < 0)
1591         return -1;
1592 
1593     if (virObjectEventStateDeregisterID(conn,
1594                                         driver->nodeDeviceEventState,
1595                                         callbackID, true) < 0)
1596         return -1;
1597 
1598     return 0;
1599 }
1600 
1601 int
nodedevRegister(void)1602 nodedevRegister(void)
1603 {
1604 #ifdef WITH_UDEV
1605     return udevNodeRegister();
1606 #endif
1607 }
1608 
1609 
1610 void
nodeDeviceGenerateName(virNodeDeviceDef * def,const char * subsystem,const char * sysname,const char * s)1611 nodeDeviceGenerateName(virNodeDeviceDef *def,
1612                        const char *subsystem,
1613                        const char *sysname,
1614                        const char *s)
1615 {
1616     size_t i;
1617     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
1618 
1619     virBufferAsprintf(&buf, "%s_%s",
1620                       subsystem,
1621                       sysname);
1622 
1623     if (s != NULL)
1624         virBufferAsprintf(&buf, "_%s", s);
1625 
1626     g_free(def->name);
1627     def->name = virBufferContentAndReset(&buf);
1628 
1629     for (i = 0; i < strlen(def->name); i++) {
1630         if (!(g_ascii_isalnum(*(def->name + i))))
1631             *(def->name + i) = '_';
1632     }
1633 }
1634 
1635 
1636 static int
virMdevctlListDefined(virNodeDeviceDef *** devs,char ** errmsg)1637 virMdevctlListDefined(virNodeDeviceDef ***devs, char **errmsg)
1638 {
1639     int status;
1640     g_autofree char *output = NULL;
1641     g_autoptr(virCommand) cmd = nodeDeviceGetMdevctlListCommand(true, &output, errmsg);
1642 
1643     if (virCommandRun(cmd, &status) < 0 || status != 0) {
1644         return -1;
1645     }
1646 
1647     if (!output)
1648         return -1;
1649 
1650     return nodeDeviceParseMdevctlJSON(output, devs);
1651 }
1652 
1653 
1654 typedef struct _virMdevctlForEachData virMdevctlForEachData;
1655 struct _virMdevctlForEachData {
1656     int ndefs;
1657     virNodeDeviceDef **defs;
1658 };
1659 
1660 
1661 /* This function keeps the list of persistent mediated devices consistent
1662  * between the nodedev driver and mdevctl.
1663  * @obj is a device that is currently known by the nodedev driver, and @opaque
1664  * contains the most recent list of devices defined by mdevctl. If @obj is no
1665  * longer defined in mdevctl, mark it as undefined and possibly remove it from
1666  * the driver as well. Returning 'true' from this function indicates that the
1667  * device should be removed from the nodedev driver list. */
1668 static bool
removeMissingPersistentMdev(virNodeDeviceObj * obj,const void * opaque)1669 removeMissingPersistentMdev(virNodeDeviceObj *obj,
1670                             const void *opaque)
1671 {
1672     bool remove = false;
1673     const virMdevctlForEachData *data = opaque;
1674     size_t i;
1675     virNodeDeviceDef *def = virNodeDeviceObjGetDef(obj);
1676     virObjectEvent *event;
1677 
1678     if (def->caps->data.type != VIR_NODE_DEV_CAP_MDEV)
1679         return false;
1680 
1681     /* transient mdevs are populated via udev, so don't remove them from the
1682      * nodedev driver just because they are not reported by by mdevctl */
1683     if (!virNodeDeviceObjIsPersistent(obj))
1684         return false;
1685 
1686     for (i = 0; i < data->ndefs; i++) {
1687         /* OK, this mdev is still defined by mdevctl */
1688         if (STREQ(data->defs[i]->name, def->name))
1689             return false;
1690     }
1691 
1692     event = virNodeDeviceEventLifecycleNew(def->name,
1693                                            VIR_NODE_DEVICE_EVENT_UNDEFINED,
1694                                            0);
1695 
1696     /* The device is active, but no longer defined by mdevctl. Keep the device
1697      * in the list, but mark it as non-persistent */
1698     if (virNodeDeviceObjIsActive(obj)) {
1699         virNodeDeviceObjSetAutostart(obj, false);
1700         virNodeDeviceObjSetPersistent(obj, false);
1701     } else {
1702         remove = true;
1703     }
1704 
1705     virObjectEventStateQueue(driver->nodeDeviceEventState, event);
1706 
1707     return remove;
1708 }
1709 
1710 
1711 int
nodeDeviceUpdateMediatedDevices(void)1712 nodeDeviceUpdateMediatedDevices(void)
1713 {
1714     g_autofree virNodeDeviceDef **defs = NULL;
1715     g_autofree char *errmsg = NULL;
1716     g_autofree char *mdevctl = NULL;
1717     virMdevctlForEachData data = { 0, };
1718     size_t i;
1719 
1720     if (!(mdevctl = virFindFileInPath(MDEVCTL))) {
1721         VIR_DEBUG(MDEVCTL " not found. Skipping update of mediated devices.");
1722         return 0;
1723     }
1724 
1725     if ((data.ndefs = virMdevctlListDefined(&defs, &errmsg)) < 0) {
1726         virReportError(VIR_ERR_INTERNAL_ERROR,
1727                        _("failed to query mdevs from mdevctl: %s"), errmsg);
1728         return -1;
1729     }
1730 
1731     /* Any mdevs that were previously defined but were not returned in the
1732      * latest mdevctl query should be removed from the device list */
1733     data.defs = defs;
1734     virNodeDeviceObjListForEachRemove(driver->devs,
1735                                       removeMissingPersistentMdev, &data);
1736 
1737     for (i = 0; i < data.ndefs; i++)
1738         if (nodeDeviceUpdateMediatedDevice(defs[i]) < 0)
1739             return -1;
1740 
1741     return 0;
1742 }
1743 
1744 
1745 /* returns true if any attributes were copied, else returns false */
1746 static bool
virMediatedDeviceAttrsCopy(virNodeDevCapMdev * dst,virNodeDevCapMdev * src)1747 virMediatedDeviceAttrsCopy(virNodeDevCapMdev *dst,
1748                            virNodeDevCapMdev *src)
1749 {
1750     bool ret = false;
1751     size_t i;
1752 
1753     if (src->nattributes != dst->nattributes) {
1754         ret = true;
1755         for (i = 0; i < dst->nattributes; i++)
1756             virMediatedDeviceAttrFree(dst->attributes[i]);
1757         g_free(dst->attributes);
1758 
1759         dst->nattributes = src->nattributes;
1760         dst->attributes = g_new0(virMediatedDeviceAttr*,
1761                                  src->nattributes);
1762         for (i = 0; i < dst->nattributes; i++)
1763             dst->attributes[i] = virMediatedDeviceAttrNew();
1764     }
1765 
1766     for (i = 0; i < src->nattributes; i++) {
1767         if (STRNEQ_NULLABLE(src->attributes[i]->name,
1768                             dst->attributes[i]->name)) {
1769             ret = true;
1770             g_free(dst->attributes[i]->name);
1771             dst->attributes[i]->name =
1772                 g_strdup(src->attributes[i]->name);
1773         }
1774         if (STRNEQ_NULLABLE(src->attributes[i]->value,
1775                             dst->attributes[i]->value)) {
1776             ret = true;
1777             g_free(dst->attributes[i]->value);
1778             dst->attributes[i]->value =
1779                 g_strdup(src->attributes[i]->value);
1780         }
1781     }
1782 
1783     return ret;
1784 }
1785 
1786 
1787 /* A mediated device definitions from mdevctl contains additional info that is
1788  * not available from udev. Transfer this data to the new definition.
1789  * Returns true if anything was copied, else returns false */
1790 bool
nodeDeviceDefCopyFromMdevctl(virNodeDeviceDef * dst,virNodeDeviceDef * src)1791 nodeDeviceDefCopyFromMdevctl(virNodeDeviceDef *dst,
1792                              virNodeDeviceDef *src)
1793 {
1794     bool ret = false;
1795     virNodeDevCapMdev *srcmdev = &src->caps->data.mdev;
1796     virNodeDevCapMdev *dstmdev = &dst->caps->data.mdev;
1797 
1798     if (STRNEQ_NULLABLE(dstmdev->type, srcmdev->type)) {
1799         ret = true;
1800         g_free(dstmdev->type);
1801         dstmdev->type = g_strdup(srcmdev->type);
1802     }
1803 
1804     if (STRNEQ_NULLABLE(dstmdev->uuid, srcmdev->uuid)) {
1805         ret = true;
1806         g_free(dstmdev->uuid);
1807         dstmdev->uuid = g_strdup(srcmdev->uuid);
1808     }
1809 
1810     if (virMediatedDeviceAttrsCopy(dstmdev, srcmdev))
1811         ret = true;
1812 
1813     if (dstmdev->autostart != srcmdev->autostart) {
1814         ret = true;
1815         dstmdev->autostart = srcmdev->autostart;
1816     }
1817 
1818     return ret;
1819 }
1820 
1821 
1822 int
nodeDeviceSetAutostart(virNodeDevice * device,int autostart)1823 nodeDeviceSetAutostart(virNodeDevice *device,
1824                        int autostart)
1825 {
1826     int ret = -1;
1827     virNodeDeviceObj *obj = NULL;
1828     virNodeDeviceDef *def = NULL;
1829 
1830     if (nodeDeviceInitWait() < 0)
1831         return -1;
1832 
1833     if (!(obj = nodeDeviceObjFindByName(device->name)))
1834         return -1;
1835     def = virNodeDeviceObjGetDef(obj);
1836 
1837     if (virNodeDeviceSetAutostartEnsureACL(device->conn, def) < 0)
1838         goto cleanup;
1839 
1840     if (nodeDeviceHasCapability(def, VIR_NODE_DEV_CAP_MDEV)) {
1841         if (!virNodeDeviceObjIsPersistent(obj)) {
1842             virReportError(VIR_ERR_OPERATION_INVALID,
1843                            "%s", _("cannot set autostart for transient device"));
1844             goto cleanup;
1845         }
1846 
1847         if (autostart != virNodeDeviceObjIsAutostart(obj)) {
1848             g_autofree char *errmsg = NULL;
1849 
1850             if (virMdevctlSetAutostart(def, autostart, &errmsg) < 0) {
1851                 virReportError(VIR_ERR_INTERNAL_ERROR,
1852                                _("Unable to set autostart on '%s': %s"),
1853                                def->name,
1854                                errmsg && errmsg[0] != '\0' ? errmsg : _("Unknown Error"));
1855                 goto cleanup;
1856             }
1857             /* Due to mdevctl performance issues, it may take several seconds
1858              * to re-query mdevctl for the defined devices. Because the mdevctl
1859              * command returned without an error status, assume it was
1860              * successful and set the object status directly here rather than
1861              * waiting for the next query */
1862             virNodeDeviceObjSetAutostart(obj, autostart);
1863         }
1864         ret = 0;
1865     } else {
1866         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
1867                        _("Unsupported device type"));
1868     }
1869 
1870  cleanup:
1871     virNodeDeviceObjEndAPI(&obj);
1872     return ret;
1873 }
1874 
1875 
1876 int
nodeDeviceGetAutostart(virNodeDevice * device,int * autostart)1877 nodeDeviceGetAutostart(virNodeDevice *device,
1878                        int *autostart)
1879 {
1880     virNodeDeviceObj *obj = NULL;
1881     virNodeDeviceDef *def = NULL;
1882     int ret = -1;
1883 
1884     if (nodeDeviceInitWait() < 0)
1885         return -1;
1886 
1887     if (!(obj = nodeDeviceObjFindByName(device->name)))
1888         return -1;
1889     def = virNodeDeviceObjGetDef(obj);
1890 
1891     if (virNodeDeviceGetAutostartEnsureACL(device->conn, def) < 0)
1892         goto cleanup;
1893 
1894     *autostart = virNodeDeviceObjIsAutostart(obj);
1895     ret = 0;
1896 
1897  cleanup:
1898     virNodeDeviceObjEndAPI(&obj);
1899     return ret;
1900 }
1901 
1902 
nodeDeviceDefPostParse(virNodeDeviceDef * def,G_GNUC_UNUSED void * opaque)1903 int nodeDeviceDefPostParse(virNodeDeviceDef *def,
1904                            G_GNUC_UNUSED void *opaque)
1905 {
1906     virNodeDevCapsDef *caps = NULL;
1907     for (caps = def->caps; caps != NULL; caps = caps->next) {
1908         if (caps->data.type == VIR_NODE_DEV_CAP_MDEV) {
1909             virNodeDeviceObj *obj = NULL;
1910 
1911             if (def->parent)
1912                 obj = virNodeDeviceObjListFindByName(driver->devs, def->parent);
1913 
1914             if (obj) {
1915                 caps->data.mdev.parent_addr = nodeDeviceObjFormatAddress(obj);
1916                 virNodeDeviceObjEndAPI(&obj);
1917             }
1918         }
1919     }
1920     return 0;
1921 }
1922 
1923 
1924 /* validate that parent exists */
nodeDeviceDefValidateMdev(virNodeDeviceDef * def,virNodeDevCapMdev * mdev,G_GNUC_UNUSED void * opaque)1925 static int nodeDeviceDefValidateMdev(virNodeDeviceDef *def,
1926                                      virNodeDevCapMdev *mdev,
1927                                      G_GNUC_UNUSED void *opaque)
1928 {
1929     virNodeDeviceObj *obj = NULL;
1930     if (!def->parent) {
1931         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1932                        _("missing parent device"));
1933         return -1;
1934     }
1935     obj = virNodeDeviceObjListFindByName(driver->devs, def->parent);
1936     if (!obj) {
1937         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1938                        _("invalid parent device '%s'"),
1939                        def->parent);
1940         return -1;
1941     }
1942     virNodeDeviceObjEndAPI(&obj);
1943 
1944     /* the post-parse callback should have found the address of the parent
1945      * device and stored it in the mdev caps */
1946     if (!mdev->parent_addr) {
1947         virReportError(VIR_ERR_PARSE_FAILED,
1948                        _("Unable to find address for parent device '%s'"),
1949                        def->parent);
1950         return -1;
1951     }
1952 
1953     return 0;
1954 }
1955 
nodeDeviceDefValidate(virNodeDeviceDef * def,G_GNUC_UNUSED void * opaque)1956 int nodeDeviceDefValidate(virNodeDeviceDef *def,
1957                           G_GNUC_UNUSED void *opaque)
1958 {
1959     virNodeDevCapsDef *caps = NULL;
1960     for (caps = def->caps; caps != NULL; caps = caps->next) {
1961         switch (caps->data.type) {
1962             case VIR_NODE_DEV_CAP_MDEV:
1963                 if (nodeDeviceDefValidateMdev(def, &caps->data.mdev, opaque) < 0)
1964                     return -1;
1965                 break;
1966 
1967             case VIR_NODE_DEV_CAP_SYSTEM:
1968             case VIR_NODE_DEV_CAP_PCI_DEV:
1969             case VIR_NODE_DEV_CAP_USB_DEV:
1970             case VIR_NODE_DEV_CAP_USB_INTERFACE:
1971             case VIR_NODE_DEV_CAP_NET:
1972             case VIR_NODE_DEV_CAP_SCSI_HOST:
1973             case VIR_NODE_DEV_CAP_SCSI_TARGET:
1974             case VIR_NODE_DEV_CAP_SCSI:
1975             case VIR_NODE_DEV_CAP_STORAGE:
1976             case VIR_NODE_DEV_CAP_FC_HOST:
1977             case VIR_NODE_DEV_CAP_VPORTS:
1978             case VIR_NODE_DEV_CAP_SCSI_GENERIC:
1979             case VIR_NODE_DEV_CAP_DRM:
1980             case VIR_NODE_DEV_CAP_MDEV_TYPES:
1981             case VIR_NODE_DEV_CAP_CCW_DEV:
1982             case VIR_NODE_DEV_CAP_CSS_DEV:
1983             case VIR_NODE_DEV_CAP_VDPA:
1984             case VIR_NODE_DEV_CAP_AP_CARD:
1985             case VIR_NODE_DEV_CAP_AP_QUEUE:
1986             case VIR_NODE_DEV_CAP_AP_MATRIX:
1987             case VIR_NODE_DEV_CAP_VPD:
1988             case VIR_NODE_DEV_CAP_LAST:
1989                 break;
1990         }
1991     }
1992     return 0;
1993 }
1994 
1995 
1996 int
nodeDeviceIsPersistent(virNodeDevice * device)1997 nodeDeviceIsPersistent(virNodeDevice *device)
1998 {
1999     virNodeDeviceObj *obj = NULL;
2000     virNodeDeviceDef *def = NULL;
2001     int ret = -1;
2002 
2003     if (nodeDeviceInitWait() < 0)
2004         return -1;
2005 
2006     if (!(obj = nodeDeviceObjFindByName(device->name)))
2007         return -1;
2008     def = virNodeDeviceObjGetDef(obj);
2009 
2010     if (virNodeDeviceIsPersistentEnsureACL(device->conn, def) < 0)
2011         goto cleanup;
2012 
2013     ret = virNodeDeviceObjIsPersistent(obj);
2014 
2015  cleanup:
2016     virNodeDeviceObjEndAPI(&obj);
2017     return ret;
2018 }
2019 
2020 
2021 int
nodeDeviceIsActive(virNodeDevice * device)2022 nodeDeviceIsActive(virNodeDevice *device)
2023 {
2024     virNodeDeviceObj *obj = NULL;
2025     virNodeDeviceDef *def = NULL;
2026     int ret = -1;
2027 
2028     if (nodeDeviceInitWait() < 0)
2029         return -1;
2030 
2031     if (!(obj = nodeDeviceObjFindByName(device->name)))
2032         return -1;
2033     def = virNodeDeviceObjGetDef(obj);
2034 
2035     if (virNodeDeviceIsActiveEnsureACL(device->conn, def) < 0)
2036         goto cleanup;
2037 
2038     ret = virNodeDeviceObjIsActive(obj);
2039 
2040  cleanup:
2041     virNodeDeviceObjEndAPI(&obj);
2042     return ret;
2043 }
2044