node_device_udev.c 56.6 KB
Newer Older
1 2 3
/*
 * node_device_udev.c: node device enumeration - libudev implementation
 *
4
 * Copyright (C) 2009-2015 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library.  If not, see
O
Osier Yang 已提交
18
 * <http://www.gnu.org/licenses/>.
19 20 21 22 23 24
 *
 * Author: Dave Allan <dallan@redhat.com>
 */

#include <config.h>
#include <libudev.h>
25
#include <pciaccess.h>
26 27 28
#include <scsi/scsi.h>
#include <c-ctype.h>

29
#include "dirname.h"
30
#include "node_device_conf.h"
31
#include "node_device_event.h"
32
#include "node_device_driver.h"
33 34 35
#include "node_device_linux_sysfs.h"
#include "node_device_udev.h"
#include "virerror.h"
36 37
#include "driver.h"
#include "datatypes.h"
38
#include "virlog.h"
39
#include "viralloc.h"
40
#include "viruuid.h"
41
#include "virbuffer.h"
42
#include "virfile.h"
43
#include "virpci.h"
44
#include "virstring.h"
45
#include "virnetdev.h"
46
#include "virmdev.h"
47 48 49

#define VIR_FROM_THIS VIR_FROM_NODEDEV

50 51
VIR_LOG_INIT("node_device.node_device_udev");

52 53 54 55
#ifndef TYPE_RAID
# define TYPE_RAID 12
#endif

56 57 58 59 60 61
typedef struct _udevEventData udevEventData;
typedef udevEventData *udevEventDataPtr;

struct _udevEventData {
    virObjectLockable parent;

62 63
    struct udev_monitor *udev_monitor;
    int watch;
64 65 66 67 68 69

    /* Thread data */
    virThread th;
    virCond threadCond;
    bool threadQuit;
    bool dataReady;
70 71
};

72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
static virClassPtr udevEventDataClass;

static void
udevEventDataDispose(void *obj)
{
    struct udev *udev = NULL;
    udevEventDataPtr priv = obj;

    if (priv->watch != -1)
        virEventRemoveHandle(priv->watch);

    if (!priv->udev_monitor)
        return;

    udev = udev_monitor_get_udev(priv->udev_monitor);
    udev_monitor_unref(priv->udev_monitor);
    udev_unref(udev);
89 90

    virCondDestroy(&priv->threadCond);
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
}


static int
udevEventDataOnceInit(void)
{
    if (!(udevEventDataClass = virClassNew(virClassForObjectLockable(),
                                           "udevEventData",
                                           sizeof(udevEventData),
                                           udevEventDataDispose)))
        return -1;

    return 0;
}

VIR_ONCE_GLOBAL_INIT(udevEventData)

static udevEventDataPtr
udevEventDataNew(void)
{
    udevEventDataPtr ret = NULL;

    if (udevEventDataInitialize() < 0)
        return NULL;

    if (!(ret = virObjectLockableNew(udevEventDataClass)))
        return NULL;

119 120 121 122 123
    if (virCondInit(&ret->threadCond) < 0) {
        virObjectUnref(ret);
        return NULL;
    }

124 125 126 127
    ret->watch = -1;
    return ret;
}

128

J
Ján Tomko 已提交
129 130 131 132 133 134 135 136 137 138 139
static bool
udevHasDeviceProperty(struct udev_device *dev,
                      const char *key)
{
    if (udev_device_get_property_value(dev, key))
        return true;

    return false;
}


140 141 142
static const char *
udevGetDeviceProperty(struct udev_device *udev_device,
                      const char *property_key)
143
{
144
    const char *ret = NULL;
145

146
    ret = udev_device_get_property_value(udev_device, property_key);
147

148 149
    VIR_DEBUG("Found property key '%s' value '%s' for device with sysname '%s'",
              property_key, NULLSTR(ret), udev_device_get_sysname(udev_device));
150 151 152 153 154

    return ret;
}


155 156 157 158
static int
udevGetStringProperty(struct udev_device *udev_device,
                      const char *property_key,
                      char **value)
159
{
160 161
    if (VIR_STRDUP(*value,
                   udevGetDeviceProperty(udev_device, property_key)) < 0)
162
        return -1;
163

164
    return 0;
165 166 167
}


168 169 170 171 172
static int
udevGetIntProperty(struct udev_device *udev_device,
                   const char *property_key,
                   int *value,
                   int base)
173
{
174
    const char *str = NULL;
175

176
    str = udevGetDeviceProperty(udev_device, property_key);
177

178
    if (str && virStrToLong_i(str, NULL, base, value) < 0) {
179 180
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to convert '%s' to int"), str);
181
        return -1;
182
    }
183
    return 0;
184 185 186
}


187 188 189 190 191
static int
udevGetUintProperty(struct udev_device *udev_device,
                    const char *property_key,
                    unsigned int *value,
                    int base)
192
{
193
    const char *str = NULL;
194

195
    str = udevGetDeviceProperty(udev_device, property_key);
196

197
    if (str && virStrToLong_ui(str, NULL, base, value) < 0) {
198 199
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to convert '%s' to int"), str);
200
        return -1;
201
    }
202
    return 0;
203 204 205
}


206 207 208
static const char *
udevGetDeviceSysfsAttr(struct udev_device *udev_device,
                       const char *attr_name)
209
{
210
    const char *ret = NULL;
211

212
    ret = udev_device_get_sysattr_value(udev_device, attr_name);
213 214

    VIR_DEBUG("Found sysfs attribute '%s' value '%s' "
215
              "for device with sysname '%s'",
216
              attr_name, NULLSTR(ret),
217 218 219 220 221
              udev_device_get_sysname(udev_device));
    return ret;
}


222 223 224 225
static int
udevGetStringSysfsAttr(struct udev_device *udev_device,
                       const char *attr_name,
                       char **value)
226
{
227
    if (VIR_STRDUP(*value, udevGetDeviceSysfsAttr(udev_device, attr_name)) < 0)
228
        return -1;
229

230
    virStringStripControlChars(*value);
231

232 233
    if (*value != NULL && (STREQ(*value, "")))
        VIR_FREE(*value);
234

235
    return 0;
236 237 238
}


239 240 241 242 243
static int
udevGetIntSysfsAttr(struct udev_device *udev_device,
                    const char *attr_name,
                    int *value,
                    int base)
244
{
245
    const char *str = NULL;
246

247
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
248

249
    if (str && virStrToLong_i(str, NULL, base, value) < 0) {
250 251
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to convert '%s' to int"), str);
252
        return -1;
253 254
    }

255
    return 0;
256 257 258
}


259 260 261 262 263
static int
udevGetUintSysfsAttr(struct udev_device *udev_device,
                     const char *attr_name,
                     unsigned int *value,
                     int base)
264
{
265
    const char *str = NULL;
266

267
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
268

269
    if (str && virStrToLong_ui(str, NULL, base, value) < 0) {
270 271
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to convert '%s' to unsigned int"), str);
272
        return -1;
273 274
    }

275
    return 0;
276 277 278
}


279 280 281 282
static int
udevGetUint64SysfsAttr(struct udev_device *udev_device,
                       const char *attr_name,
                       unsigned long long *value)
283
{
284
    const char *str = NULL;
285

286
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
287

288
    if (str && virStrToLong_ull(str, NULL, 0, value) < 0) {
289 290
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to convert '%s' to unsigned long long"), str);
J
Ján Tomko 已提交
291
        return -1;
292 293
    }

J
Ján Tomko 已提交
294
    return 0;
295 296 297
}


298 299 300 301
static int
udevGenerateDeviceName(struct udev_device *device,
                       virNodeDeviceDefPtr def,
                       const char *s)
302
{
303
    size_t i;
304 305
    virBuffer buf = VIR_BUFFER_INITIALIZER;

306
    virBufferAsprintf(&buf, "%s_%s",
307 308 309
                      udev_device_get_subsystem(device),
                      udev_device_get_sysname(device));

310
    if (s != NULL)
311
        virBufferAsprintf(&buf, "_%s", s);
312

313 314
    if (virBufferCheckError(&buf) < 0)
        return -1;
315 316 317

    def->name = virBufferContentAndReset(&buf);

318
    for (i = 0; i < strlen(def->name); i++) {
319
        if (!(c_isalnum(*(def->name + i))))
320 321 322
            *(def->name + i) = '_';
    }

323
    return 0;
324 325
}

326

327
#if HAVE_UDEV_LOGGING
328 329 330 331 332 333 334 335
typedef void
(*udevLogFunctionPtr)(struct udev *udev,
                      int priority,
                      const char *file,
                      int line,
                      const char *fn,
                      const char *format,
                      va_list args);
J
Ján Tomko 已提交
336 337

static void
338
ATTRIBUTE_FMT_PRINTF(6, 0)
J
Ján Tomko 已提交
339 340 341 342 343 344 345
udevLogFunction(struct udev *udev ATTRIBUTE_UNUSED,
                int priority,
                const char *file,
                int line,
                const char *fn,
                const char *fmt,
                va_list args)
346
{
J
Ján Tomko 已提交
347
    virBuffer buf = VIR_BUFFER_INITIALIZER;
348
    char *format = NULL;
J
Ján Tomko 已提交
349 350 351 352 353 354

    virBufferAdd(&buf, fmt, -1);
    virBufferTrim(&buf, "\n", -1);

    format = virBufferContentAndReset(&buf);

355
    virLogVMessage(&virLogSelf,
J
Ján Tomko 已提交
356 357 358 359
                   virLogPriorityFromSyslog(priority),
                   file, line, fn, NULL, format ? format : fmt, args);

    VIR_FREE(format);
360
}
361
#endif
362 363


364 365 366 367 368
static int
udevTranslatePCIIds(unsigned int vendor,
                    unsigned int product,
                    char **vendor_string,
                    char **product_string)
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
{
    struct pci_id_match m;
    const char *vendor_name = NULL, *device_name = NULL;

    m.vendor_id = vendor;
    m.device_id = product;
    m.subvendor_id = PCI_MATCH_ANY;
    m.subdevice_id = PCI_MATCH_ANY;
    m.device_class = 0;
    m.device_class_mask = 0;
    m.match_data = 0;

    /* pci_get_strings returns void */
    pci_get_strings(&m,
                    &device_name,
384
                    &vendor_name,
385 386 387
                    NULL,
                    NULL);

388
    if (VIR_STRDUP(*vendor_string, vendor_name) < 0 ||
389
        VIR_STRDUP(*product_string, device_name) < 0)
390
        return -1;
391

392
    return 0;
393 394 395
}


396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508
static int
udevFillMdevType(struct udev_device *device,
                 const char *dir,
                 virNodeDevCapMdevTypePtr type)
{
    int ret = -1;
    char *attrpath = NULL;

#define MDEV_GET_SYSFS_ATTR(attr_name, cb, ...)                             \
    do {                                                                    \
        if (virAsprintf(&attrpath, "%s/%s", dir, #attr_name) < 0)           \
            goto cleanup;                                                   \
                                                                            \
        if (cb(device, attrpath, __VA_ARGS__) < 0)                          \
            goto cleanup;                                                   \
                                                                            \
        VIR_FREE(attrpath);                                                 \
    } while (0)                                                             \

    if (VIR_STRDUP(type->id, last_component(dir)) < 0)
        goto cleanup;

    /* query udev for the attributes under subdirectories using the relative
     * path stored in @dir, i.e. 'mdev_supported_types/<type_id>'
     */
    MDEV_GET_SYSFS_ATTR(name, udevGetStringSysfsAttr, &type->name);
    MDEV_GET_SYSFS_ATTR(device_api, udevGetStringSysfsAttr, &type->device_api);
    MDEV_GET_SYSFS_ATTR(available_instances, udevGetUintSysfsAttr,
                        &type->available_instances, 10);

#undef MDEV_GET_SYSFS_ATTR

    ret = 0;
 cleanup:
    VIR_FREE(attrpath);
    return ret;
}


static int
udevPCIGetMdevTypesCap(struct udev_device *device,
                       virNodeDevCapPCIDevPtr pcidata)
{
    int ret = -1;
    int dirret = -1;
    DIR *dir = NULL;
    struct dirent *entry;
    char *path = NULL;
    char *tmppath = NULL;
    virNodeDevCapMdevTypePtr type = NULL;
    virNodeDevCapMdevTypePtr *types = NULL;
    size_t ntypes = 0;
    size_t i;

    if (virAsprintf(&path, "%s/mdev_supported_types",
                    udev_device_get_syspath(device)) < 0)
        return -1;

    if ((dirret = virDirOpenIfExists(&dir, path)) < 0)
        goto cleanup;

    if (dirret == 0) {
        ret = 0;
        goto cleanup;
    }

    if (VIR_ALLOC(types) < 0)
        goto cleanup;

    /* UDEV doesn't report attributes under subdirectories by default but is
     * able to query them if the path to the attribute is relative to the
     * device's base path, e.g. /sys/devices/../0000:00:01.0/ is the device's
     * base path as udev reports it, but we're interested in attributes under
     * /sys/devices/../0000:00:01.0/mdev_supported_types/<type>/. So, we need to
     * scan the subdirectories ourselves.
     */
    while ((dirret = virDirRead(dir, &entry, path)) > 0) {
        if (VIR_ALLOC(type) < 0)
            goto cleanup;

        /* construct the relative mdev type path bit for udev */
        if (virAsprintf(&tmppath, "mdev_supported_types/%s", entry->d_name) < 0)
            goto cleanup;

        if (udevFillMdevType(device, tmppath, type) < 0)
            goto cleanup;

        if (VIR_APPEND_ELEMENT(types, ntypes, type) < 0)
            goto cleanup;

        VIR_FREE(tmppath);
    }

    if (dirret < 0)
        goto cleanup;

    VIR_STEAL_PTR(pcidata->mdev_types, types);
    pcidata->nmdev_types = ntypes;
    pcidata->flags |= VIR_NODE_DEV_CAP_FLAG_PCI_MDEV;
    ntypes = 0;
    ret = 0;
 cleanup:
    virNodeDevCapMdevTypeFree(type);
    for (i = 0; i < ntypes; i++)
        virNodeDevCapMdevTypeFree(types[i]);
    VIR_FREE(types);
    VIR_FREE(path);
    VIR_FREE(tmppath);
    VIR_DIR_CLOSE(dir);
    return ret;
}


509 510 511
static int
udevProcessPCI(struct udev_device *device,
               virNodeDeviceDefPtr def)
512
{
513
    virNodeDevCapPCIDevPtr pci_dev = &def->caps->data.pci_dev;
514 515
    virPCIEDeviceInfoPtr pci_express = NULL;
    virPCIDevicePtr pciDev = NULL;
516
    int ret = -1;
517
    char *p;
518 519 520 521 522
    bool privileged;

    nodeDeviceLock();
    privileged = driver->privileged;
    nodeDeviceUnlock();
523

524
    if (udevGetUintProperty(device, "PCI_CLASS", &pci_dev->class, 16) < 0)
525
        goto cleanup;
526

527
    if ((p = strrchr(def->sysfs_path, '/')) == NULL ||
528 529 530 531
        virStrToLong_ui(p + 1, &p, 16, &pci_dev->domain) < 0 || p == NULL ||
        virStrToLong_ui(p + 1, &p, 16, &pci_dev->bus) < 0 || p == NULL ||
        virStrToLong_ui(p + 1, &p, 16, &pci_dev->slot) < 0 || p == NULL ||
        virStrToLong_ui(p + 1, &p, 16, &pci_dev->function) < 0) {
532 533
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to parse the PCI address from sysfs path: '%s'"),
534
                       def->sysfs_path);
535
        goto cleanup;
536 537
    }

538
    if (udevGetUintSysfsAttr(device, "vendor", &pci_dev->vendor, 16) < 0)
539
        goto cleanup;
540

541
    if (udevGetUintSysfsAttr(device, "device", &pci_dev->product, 16) < 0)
542
        goto cleanup;
543

544 545 546 547
    if (udevTranslatePCIIds(pci_dev->vendor,
                            pci_dev->product,
                            &pci_dev->vendor_name,
                            &pci_dev->product_name) != 0) {
548
        goto cleanup;
549
    }
550

551
    if (udevGenerateDeviceName(device, def, NULL) != 0)
552
        goto cleanup;
553

554 555
    /* The default value is -1, because it can't be 0
     * as zero is valid node number. */
556
    pci_dev->numa_node = -1;
557
    if (udevGetIntSysfsAttr(device, "numa_node",
558
                            &pci_dev->numa_node, 10) < 0)
559
        goto cleanup;
560

561
    if (nodeDeviceSysfsGetPCIRelatedDevCaps(def->sysfs_path, pci_dev) < 0)
562
        goto cleanup;
563

564 565 566 567
    if (!(pciDev = virPCIDeviceNew(pci_dev->domain,
                                   pci_dev->bus,
                                   pci_dev->slot,
                                   pci_dev->function)))
568
        goto cleanup;
569

570
    /* We need to be root to read PCI device configs */
571
    if (privileged) {
572
        if (virPCIGetHeaderType(pciDev, &pci_dev->hdrType) < 0)
573
            goto cleanup;
574

575 576
        if (virPCIDeviceIsPCIExpress(pciDev) > 0) {
            if (VIR_ALLOC(pci_express) < 0)
577
                goto cleanup;
578

579 580 581
            if (virPCIDeviceHasPCIExpressLink(pciDev) > 0) {
                if (VIR_ALLOC(pci_express->link_cap) < 0 ||
                    VIR_ALLOC(pci_express->link_sta) < 0)
582
                    goto cleanup;
583 584 585 586 587 588 589

                if (virPCIDeviceGetLinkCapSta(pciDev,
                                              &pci_express->link_cap->port,
                                              &pci_express->link_cap->speed,
                                              &pci_express->link_cap->width,
                                              &pci_express->link_sta->speed,
                                              &pci_express->link_sta->width) < 0)
590
                    goto cleanup;
591 592 593

                pci_express->link_sta->port = -1; /* PCIe can't negotiate port. Yet :) */
            }
594 595
            pci_dev->flags |= VIR_NODE_DEV_CAP_FLAG_PCIE;
            pci_dev->pci_express = pci_express;
596
            pci_express = NULL;
597 598 599
        }
    }

600 601 602 603 604 605
    /* check whether the device is mediated devices framework capable, if so,
     * process it
     */
    if (udevPCIGetMdevTypesCap(device, pci_dev) < 0)
        goto cleanup;

606 607
    ret = 0;

608
 cleanup:
609
    virPCIDeviceFree(pciDev);
610
    virPCIEDeviceInfoFree(pci_express);
611 612 613
    return ret;
}

614 615 616

static int
drmGetMinorType(int minor)
M
Marc-André Lureau 已提交
617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
{
    int type = minor >> 6;

    if (minor < 0)
        return -1;

    switch (type) {
    case VIR_NODE_DEV_DRM_PRIMARY:
    case VIR_NODE_DEV_DRM_CONTROL:
    case VIR_NODE_DEV_DRM_RENDER:
        return type;
    default:
        return -1;
    }
}

633 634 635 636

static int
udevProcessDRMDevice(struct udev_device *device,
                     virNodeDeviceDefPtr def)
M
Marc-André Lureau 已提交
637
{
638
    virNodeDevCapDRMPtr drm = &def->caps->data.drm;
M
Marc-André Lureau 已提交
639 640 641 642 643 644 645 646 647 648 649
    int minor;

    if (udevGenerateDeviceName(device, def, NULL) != 0)
        return -1;

    if (udevGetIntProperty(device, "MINOR", &minor, 10) < 0)
        return -1;

    if ((minor = drmGetMinorType(minor)) == -1)
        return -1;

650
    drm->type = minor;
M
Marc-André Lureau 已提交
651 652 653

    return 0;
}
654

655 656 657 658

static int
udevProcessUSBDevice(struct udev_device *device,
                     virNodeDeviceDefPtr def)
659
{
660
    virNodeDevCapUSBDevPtr usb_dev = &def->caps->data.usb_dev;
661

662
    if (udevGetUintProperty(device, "BUSNUM", &usb_dev->bus, 10) < 0)
663
        return -1;
664
    if (udevGetUintProperty(device, "DEVNUM", &usb_dev->device, 10) < 0)
665
        return -1;
666
    if (udevGetUintProperty(device, "ID_VENDOR_ID", &usb_dev->vendor, 16) < 0)
667
        return -1;
668

669 670
    if (udevGetStringProperty(device,
                              "ID_VENDOR_FROM_DATABASE",
671
                              &usb_dev->vendor_name) < 0)
672
        return -1;
673

674
    if (!usb_dev->vendor_name &&
675
        udevGetStringSysfsAttr(device, "manufacturer",
676
                               &usb_dev->vendor_name) < 0)
677
        return -1;
678

679
    if (udevGetUintProperty(device, "ID_MODEL_ID", &usb_dev->product, 16) < 0)
680
        return -1;
681

682 683
    if (udevGetStringProperty(device,
                              "ID_MODEL_FROM_DATABASE",
684
                              &usb_dev->product_name) < 0)
685
        return -1;
686

687
    if (!usb_dev->product_name &&
688
        udevGetStringSysfsAttr(device, "product",
689
                               &usb_dev->product_name) < 0)
690
        return -1;
691

692
    if (udevGenerateDeviceName(device, def, NULL) != 0)
693
        return -1;
694

695
    return 0;
696 697 698
}


699 700 701
static int
udevProcessUSBInterface(struct udev_device *device,
                        virNodeDeviceDefPtr def)
702
{
703
    virNodeDevCapUSBIfPtr usb_if = &def->caps->data.usb_if;
704

705
    if (udevGetUintSysfsAttr(device, "bInterfaceNumber",
706
                             &usb_if->number, 16) < 0)
707
        return -1;
708

709
    if (udevGetUintSysfsAttr(device, "bInterfaceClass",
710
                             &usb_if->_class, 16) < 0)
711
        return -1;
712

713
    if (udevGetUintSysfsAttr(device, "bInterfaceSubClass",
714
                             &usb_if->subclass, 16) < 0)
715
        return -1;
716

717
    if (udevGetUintSysfsAttr(device, "bInterfaceProtocol",
718
                             &usb_if->protocol, 16) < 0)
719
        return -1;
720

721
    if (udevGenerateDeviceName(device, def, NULL) != 0)
722
        return -1;
723

724
    return 0;
725 726 727
}


728 729 730
static int
udevProcessNetworkInterface(struct udev_device *device,
                            virNodeDeviceDefPtr def)
731
{
D
David Allan 已提交
732
    const char *devtype = udev_device_get_devtype(device);
733
    virNodeDevCapNetPtr net = &def->caps->data.net;
734

D
David Allan 已提交
735
    if (devtype && STREQ(devtype, "wlan")) {
736
        net->subtype = VIR_NODE_DEV_CAP_NET_80211;
D
David Allan 已提交
737
    } else {
738
        net->subtype = VIR_NODE_DEV_CAP_NET_80203;
D
David Allan 已提交
739 740
    }

741 742
    if (udevGetStringProperty(device,
                              "INTERFACE",
743
                              &net->ifname) < 0)
744
        return -1;
745

746
    if (udevGetStringSysfsAttr(device, "address",
747
                               &net->address) < 0)
748
        return -1;
749

750
    if (udevGetUintSysfsAttr(device, "addr_len", &net->address_len, 0) < 0)
751
        return -1;
752

753
    if (udevGenerateDeviceName(device, def, net->address) != 0)
754
        return -1;
755

756
    if (virNetDevGetLinkInfo(net->ifname, &net->lnk) < 0)
757
        return -1;
758

759
    if (virNetDevGetFeatures(net->ifname, &net->features) < 0)
760
        return -1;
761

762
    return 0;
763 764 765
}


766 767 768
static int
udevProcessSCSIHost(struct udev_device *device ATTRIBUTE_UNUSED,
                    virNodeDeviceDefPtr def)
769
{
770
    virNodeDevCapSCSIHostPtr scsi_host = &def->caps->data.scsi_host;
771
    char *filename = NULL;
J
Ján Tomko 已提交
772
    char *str;
773

774
    filename = last_component(def->sysfs_path);
775

776
    if (!(str = STRSKIP(filename, "host")) ||
777
        virStrToLong_ui(str, NULL, 0, &scsi_host->host) < 0) {
778 779 780
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to parse SCSI host '%s'"),
                       filename);
781
        return -1;
782 783
    }

784
    nodeDeviceSysfsGetSCSIHostCaps(&def->caps->data.scsi_host);
785

786
    if (udevGenerateDeviceName(device, def, NULL) != 0)
787
        return -1;
788

789
    return 0;
790 791 792
}


793 794 795
static int
udevProcessSCSITarget(struct udev_device *device,
                      virNodeDeviceDefPtr def)
D
David Allan 已提交
796 797
{
    const char *sysname = NULL;
798
    virNodeDevCapSCSITargetPtr scsi_target = &def->caps->data.scsi_target;
D
David Allan 已提交
799 800 801

    sysname = udev_device_get_sysname(device);

802
    if (VIR_STRDUP(scsi_target->name, sysname) < 0)
803
        return -1;
D
David Allan 已提交
804

805 806
    nodeDeviceSysfsGetSCSITargetCaps(def->sysfs_path, &def->caps->data.scsi_target);

807
    if (udevGenerateDeviceName(device, def, NULL) != 0)
808
        return -1;
D
David Allan 已提交
809

810
    return 0;
D
David Allan 已提交
811 812 813
}


814 815 816 817
static int
udevGetSCSIType(virNodeDeviceDefPtr def ATTRIBUTE_UNUSED,
                unsigned int type,
                char **typestring)
818 819 820 821 822 823 824 825
{
    int ret = 0;
    int foundtype = 1;

    *typestring = NULL;

    switch (type) {
    case TYPE_DISK:
826
        ignore_value(VIR_STRDUP(*typestring, "disk"));
827 828
        break;
    case TYPE_TAPE:
829
        ignore_value(VIR_STRDUP(*typestring, "tape"));
830 831
        break;
    case TYPE_PROCESSOR:
832
        ignore_value(VIR_STRDUP(*typestring, "processor"));
833 834
        break;
    case TYPE_WORM:
835
        ignore_value(VIR_STRDUP(*typestring, "worm"));
836 837
        break;
    case TYPE_ROM:
838
        ignore_value(VIR_STRDUP(*typestring, "cdrom"));
839 840
        break;
    case TYPE_SCANNER:
841
        ignore_value(VIR_STRDUP(*typestring, "scanner"));
842 843
        break;
    case TYPE_MOD:
844
        ignore_value(VIR_STRDUP(*typestring, "mod"));
845 846
        break;
    case TYPE_MEDIUM_CHANGER:
847
        ignore_value(VIR_STRDUP(*typestring, "changer"));
848 849
        break;
    case TYPE_ENCLOSURE:
850
        ignore_value(VIR_STRDUP(*typestring, "enclosure"));
851
        break;
852
    case TYPE_RAID:
853
        ignore_value(VIR_STRDUP(*typestring, "raid"));
854
        break;
855 856 857 858 859 860 861 862 863 864
    case TYPE_NO_LUN:
    default:
        foundtype = 0;
        break;
    }

    if (*typestring == NULL) {
        if (foundtype == 1) {
            ret = -1;
        } else {
865 866
            VIR_DEBUG("Failed to find SCSI device type %d for %s",
                      type, def->sysfs_path);
867 868 869 870 871 872 873
        }
    }

    return ret;
}


874 875 876
static int
udevProcessSCSIDevice(struct udev_device *device ATTRIBUTE_UNUSED,
                      virNodeDeviceDefPtr def)
877 878 879
{
    int ret = -1;
    unsigned int tmp = 0;
880
    virNodeDevCapSCSIPtr scsi = &def->caps->data.scsi;
881 882
    char *filename = NULL, *p = NULL;

883
    filename = last_component(def->sysfs_path);
884

885 886 887 888
    if (virStrToLong_ui(filename, &p, 10, &scsi->host) < 0 || p == NULL ||
        virStrToLong_ui(p + 1, &p, 10, &scsi->bus) < 0 || p == NULL ||
        virStrToLong_ui(p + 1, &p, 10, &scsi->target) < 0 || p == NULL ||
        virStrToLong_ui(p + 1, &p, 10, &scsi->lun) < 0) {
889 890 891 892
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to parse the SCSI address from filename: '%s'"),
                       filename);
        return -1;
893 894
    }

895 896
    if (udev_device_get_sysattr_value(device, "type")) {
        if (udevGetUintSysfsAttr(device, "type", &tmp, 0) < 0)
897
            goto cleanup;
898

899
        if (udevGetSCSIType(def, tmp, &scsi->type) < 0)
900
            goto cleanup;
901 902
    }

903
    if (udevGenerateDeviceName(device, def, NULL) != 0)
904
        goto cleanup;
905 906 907

    ret = 0;

908
 cleanup:
909
    if (ret != 0) {
910 911 912
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to process SCSI device with sysfs path '%s'"),
                       def->sysfs_path);
913 914 915 916 917
    }
    return ret;
}


918 919 920
static int
udevProcessDisk(struct udev_device *device,
                virNodeDeviceDefPtr def)
921
{
922
    virNodeDevCapStoragePtr storage = &def->caps->data.storage;
923

924
    if (udevGetUint64SysfsAttr(device, "size", &storage->num_blocks) < 0)
925
        return -1;
926

J
Ján Tomko 已提交
927
    if (udevGetUint64SysfsAttr(device, "queue/logical_block_size",
928
                               &storage->logical_block_size) < 0)
929
        return -1;
930

931
    storage->size = storage->num_blocks * storage->logical_block_size;
932

933
    return 0;
934 935 936
}


937 938 939 940
static int
udevProcessRemoveableMedia(struct udev_device *device,
                           virNodeDeviceDefPtr def,
                           int has_media)
941
{
942
    virNodeDevCapStoragePtr storage = &def->caps->data.storage;
J
Ján Tomko 已提交
943
    int is_removable = 0;
944

945 946 947
    if (udevGetIntSysfsAttr(device, "removable", &is_removable, 0) < 0)
        return -1;
    if (is_removable == 1)
948 949
        def->caps->data.storage.flags |= VIR_NODE_DEV_CAP_STORAGE_REMOVABLE;

J
Ján Tomko 已提交
950 951
    if (!has_media)
        return 0;
952

J
Ján Tomko 已提交
953 954
    def->caps->data.storage.flags |=
        VIR_NODE_DEV_CAP_STORAGE_REMOVABLE_MEDIA_AVAILABLE;
955

J
Ján Tomko 已提交
956
    if (udevGetStringProperty(device, "ID_FS_LABEL",
957
                              &storage->media_label) < 0)
J
Ján Tomko 已提交
958
        return -1;
959

J
Ján Tomko 已提交
960
    if (udevGetUint64SysfsAttr(device, "size",
961
                               &storage->num_blocks) < 0)
J
Ján Tomko 已提交
962
        return -1;
963

J
Ján Tomko 已提交
964
    if (udevGetUint64SysfsAttr(device, "queue/logical_block_size",
965
                               &storage->logical_block_size) < 0)
J
Ján Tomko 已提交
966
        return -1;
967

J
Ján Tomko 已提交
968 969 970 971 972 973 974
    /* XXX This calculation is wrong for the qemu virtual cdrom
     * which reports the size in 512 byte blocks, but the logical
     * block size as 2048.  I don't have a physical cdrom on a
     * devel system to see how they behave. */
    def->caps->data.storage.removable_media_size =
        def->caps->data.storage.num_blocks *
        def->caps->data.storage.logical_block_size;
975

J
Ján Tomko 已提交
976
    return 0;
977 978
}

979 980 981 982

static int
udevProcessCDROM(struct udev_device *device,
                 virNodeDeviceDefPtr def)
983 984 985 986 987 988 989 990
{
    int has_media = 0;

    /* NB: the drive_type string provided by udev is different from
     * that provided by HAL; now it's "cd" instead of "cdrom" We
     * change it to cdrom to preserve compatibility with earlier
     * versions of libvirt.  */
    VIR_FREE(def->caps->data.storage.drive_type);
991
    if (VIR_STRDUP(def->caps->data.storage.drive_type, "cdrom") < 0)
992
        return -1;
993

994 995
    if (udevHasDeviceProperty(device, "ID_CDROM_MEDIA") &&
        udevGetIntProperty(device, "ID_CDROM_MEDIA", &has_media, 0) < 0)
996
        return -1;
997

998
    return udevProcessRemoveableMedia(device, def, has_media);
999 1000
}

1001 1002 1003 1004

static int
udevProcessFloppy(struct udev_device *device,
                  virNodeDeviceDefPtr def)
1005 1006 1007
{
    int has_media = 0;

1008
    if (udevHasDeviceProperty(device, "ID_CDROM_MEDIA")) {
1009
        /* USB floppy */
1010 1011
        if (udevGetIntProperty(device, "DKD_MEDIA_AVAILABLE", &has_media, 0) < 0)
            return -1;
1012
    } else if (udevHasDeviceProperty(device, "ID_FS_LABEL")) {
1013 1014 1015 1016 1017 1018
        /* Legacy floppy */
        has_media = 1;
    }

    return udevProcessRemoveableMedia(device, def, has_media);
}
1019

1020

1021 1022 1023
static int
udevProcessSD(struct udev_device *device,
              virNodeDeviceDefPtr def)
1024
{
1025
    virNodeDevCapStoragePtr storage = &def->caps->data.storage;
1026

J
Ján Tomko 已提交
1027
    if (udevGetUint64SysfsAttr(device, "size",
1028
                               &storage->num_blocks) < 0)
1029
        return -1;
1030

J
Ján Tomko 已提交
1031
    if (udevGetUint64SysfsAttr(device, "queue/logical_block_size",
1032
                               &storage->logical_block_size) < 0)
1033
        return -1;
1034

1035
    storage->size = storage->num_blocks * storage->logical_block_size;
1036

1037
    return 0;
1038 1039 1040
}


1041 1042 1043 1044
/* This function exists to deal with the case in which a driver does
 * not provide a device type in the usual place, but udev told us it's
 * a storage device, and we can make a good guess at what kind of
 * storage device it is from other information that is provided. */
1045 1046
static int
udevKludgeStorageType(virNodeDeviceDefPtr def)
1047
{
1048 1049 1050
    VIR_DEBUG("Could not find definitive storage type for device "
              "with sysfs path '%s', trying to guess it",
              def->sysfs_path);
1051

1052 1053 1054
    /* virtio disk */
    if (STRPREFIX(def->caps->data.storage.block, "/dev/vd") &&
        VIR_STRDUP(def->caps->data.storage.drive_type, "disk") > 0) {
1055
        VIR_DEBUG("Found storage type '%s' for device "
1056
                  "with sysfs path '%s'",
1057 1058
                  def->caps->data.storage.drive_type,
                  def->sysfs_path);
1059
        return 0;
1060
    }
1061 1062 1063
    VIR_DEBUG("Could not determine storage type "
              "for device with sysfs path '%s'", def->sysfs_path);
    return -1;
1064 1065 1066
}


1067 1068 1069
static int
udevProcessStorage(struct udev_device *device,
                   virNodeDeviceDefPtr def)
1070
{
1071
    virNodeDevCapStoragePtr storage = &def->caps->data.storage;
1072
    int ret = -1;
1073
    const char* devnode;
1074

1075
    devnode = udev_device_get_devnode(device);
1076
    if (!devnode) {
1077
        VIR_DEBUG("No devnode for '%s'", udev_device_get_devpath(device));
1078
        goto cleanup;
1079
    }
1080

1081
    if (VIR_STRDUP(storage->block, devnode) < 0)
1082
        goto cleanup;
1083

1084
    if (udevGetStringProperty(device, "ID_BUS", &storage->bus) < 0)
1085
        goto cleanup;
1086
    if (udevGetStringProperty(device, "ID_SERIAL", &storage->serial) < 0)
1087
        goto cleanup;
1088

1089
    if (udevGetStringSysfsAttr(device, "device/vendor", &storage->vendor) < 0)
1090
        goto cleanup;
1091 1092 1093
    if (def->caps->data.storage.vendor)
        virTrimSpaces(def->caps->data.storage.vendor, NULL);

1094
    if (udevGetStringSysfsAttr(device, "device/model", &storage->model) < 0)
1095
        goto cleanup;
1096 1097
    if (def->caps->data.storage.model)
        virTrimSpaces(def->caps->data.storage.model, NULL);
1098 1099 1100 1101 1102
    /* There is no equivalent of the hotpluggable property in libudev,
     * but storage is going toward a world in which hotpluggable is
     * expected, so I don't see a problem with not having a property
     * for it. */

1103
    if (udevGetStringProperty(device, "ID_TYPE", &storage->drive_type) < 0)
1104
        goto cleanup;
1105

1106
    if (!storage->drive_type ||
1107
        STREQ(def->caps->data.storage.drive_type, "generic")) {
1108 1109
        int val = 0;
        const char *str = NULL;
1110 1111 1112

        /* All floppy drives have the ID_DRIVE_FLOPPY prop. This is
         * needed since legacy floppies don't have a drive_type */
1113
        if (udevGetIntProperty(device, "ID_DRIVE_FLOPPY", &val, 0) < 0)
1114
            goto cleanup;
1115 1116
        else if (val == 1)
            str = "floppy";
1117

1118
        if (!str) {
1119
            if (udevGetIntProperty(device, "ID_CDROM", &val, 0) < 0)
1120
                goto cleanup;
1121 1122 1123
            else if (val == 1)
                str = "cd";
        }
1124

1125
        if (!str) {
1126
            if (udevGetIntProperty(device, "ID_DRIVE_FLASH_SD", &val, 0) < 0)
1127
                goto cleanup;
1128 1129 1130
            if (val == 1)
                str = "sd";
        }
1131

1132
        if (str) {
1133
            if (VIR_STRDUP(storage->drive_type, str) < 0)
1134
                goto cleanup;
1135 1136
        } else {
            /* If udev doesn't have it, perhaps we can guess it. */
1137
            if (udevKludgeStorageType(def) != 0)
1138
                goto cleanup;
1139 1140 1141 1142 1143 1144 1145
        }
    }

    if (STREQ(def->caps->data.storage.drive_type, "cd")) {
        ret = udevProcessCDROM(device, def);
    } else if (STREQ(def->caps->data.storage.drive_type, "disk")) {
        ret = udevProcessDisk(device, def);
1146 1147
    } else if (STREQ(def->caps->data.storage.drive_type, "floppy")) {
        ret = udevProcessFloppy(device, def);
1148 1149
    } else if (STREQ(def->caps->data.storage.drive_type, "sd")) {
        ret = udevProcessSD(device, def);
1150
    } else {
1151 1152
        VIR_DEBUG("Unsupported storage type '%s'",
                  def->caps->data.storage.drive_type);
1153
        goto cleanup;
1154 1155
    }

1156
    if (udevGenerateDeviceName(device, def, storage->serial) != 0)
1157
        goto cleanup;
1158

1159
 cleanup:
1160
    VIR_DEBUG("Storage ret=%d", ret);
1161 1162 1163
    return ret;
}

1164

1165
static int
1166
udevProcessSCSIGeneric(struct udev_device *dev,
1167 1168
                       virNodeDeviceDefPtr def)
{
1169 1170
    if (udevGetStringProperty(dev, "DEVNAME", &def->caps->data.sg.path) < 0 ||
        !def->caps->data.sg.path)
1171 1172 1173 1174 1175 1176 1177 1178
        return -1;

    if (udevGenerateDeviceName(dev, def, NULL) != 0)
        return -1;

    return 0;
}

1179

1180 1181 1182 1183 1184 1185 1186 1187
static int
udevProcessMediatedDevice(struct udev_device *dev,
                          virNodeDeviceDefPtr def)
{
    int ret = -1;
    const char *uuidstr = NULL;
    int iommugrp = -1;
    char *linkpath = NULL;
1188
    char *canonicalpath = NULL;
1189 1190 1191 1192 1193
    virNodeDevCapMdevPtr data = &def->caps->data.mdev;

    if (virAsprintf(&linkpath, "%s/mdev_type", udev_device_get_syspath(dev)) < 0)
        goto cleanup;

1194 1195
    if (virFileResolveLink(linkpath, &canonicalpath) < 0) {
        virReportSystemError(errno, _("failed to resolve '%s'"), linkpath);
1196
        goto cleanup;
1197
    }
1198

1199
    if (VIR_STRDUP(data->type, last_component(canonicalpath)) < 0)
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
        goto cleanup;

    uuidstr = udev_device_get_sysname(dev);
    if ((iommugrp = virMediatedDeviceGetIOMMUGroupNum(uuidstr)) < 0)
        goto cleanup;

    if (udevGenerateDeviceName(dev, def, NULL) != 0)
        goto cleanup;

    data->iommuGroupNumber = iommugrp;

    ret = 0;
 cleanup:
    VIR_FREE(linkpath);
1214
    VIR_FREE(canonicalpath);
1215 1216 1217
    return ret;
}

B
Bjoern Walk 已提交
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247

static int
udevProcessCCW(struct udev_device *device,
               virNodeDeviceDefPtr def)
{
    int online;
    char *p;
    virNodeDevCapDataPtr data = &def->caps->data;

    /* process only online devices to keep the list sane */
    if (udevGetIntSysfsAttr(device, "online", &online, 0) < 0 || online != 1)
        return -1;

    if ((p = strrchr(def->sysfs_path, '/')) == NULL ||
        virStrToLong_ui(p + 1, &p, 16, &data->ccw_dev.cssid) < 0 || p == NULL ||
        virStrToLong_ui(p + 1, &p, 16, &data->ccw_dev.ssid) < 0 || p == NULL ||
        virStrToLong_ui(p + 1, &p, 16, &data->ccw_dev.devno) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to parse the CCW address from sysfs path: '%s'"),
                       def->sysfs_path);
        return -1;
    }

    if (udevGenerateDeviceName(device, def, NULL) != 0)
        return -1;

    return 0;
}


1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275
static int
udevGetDeviceNodes(struct udev_device *device,
                   virNodeDeviceDefPtr def)
{
    const char *devnode = NULL;
    struct udev_list_entry *list_entry = NULL;
    int n = 0;

    devnode = udev_device_get_devnode(device);

    if (VIR_STRDUP(def->devnode, devnode) < 0)
        return -1;

    udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device))
        n++;

    if (VIR_ALLOC_N(def->devlinks, n + 1) < 0)
        return -1;

    n = 0;
    udev_list_entry_foreach(list_entry, udev_device_get_devlinks_list_entry(device)) {
        if (VIR_STRDUP(def->devlinks[n++], udev_list_entry_get_name(list_entry)) < 0)
            return -1;
    }

    return 0;
}

1276

1277 1278
static int
udevGetDeviceType(struct udev_device *device,
1279
                  virNodeDevCapType *type)
1280 1281
{
    const char *devtype = NULL;
1282
    char *subsystem = NULL;
1283
    int ret = -1;
D
David Allan 已提交
1284

1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302
    devtype = udev_device_get_devtype(device);
    *type = 0;

    if (devtype) {
        if (STREQ(devtype, "usb_device"))
            *type = VIR_NODE_DEV_CAP_USB_DEV;
        else if (STREQ(devtype, "usb_interface"))
            *type = VIR_NODE_DEV_CAP_USB_INTERFACE;
        else if (STREQ(devtype, "scsi_host"))
            *type = VIR_NODE_DEV_CAP_SCSI_HOST;
        else if (STREQ(devtype, "scsi_target"))
            *type = VIR_NODE_DEV_CAP_SCSI_TARGET;
        else if (STREQ(devtype, "scsi_device"))
            *type = VIR_NODE_DEV_CAP_SCSI;
        else if (STREQ(devtype, "disk"))
            *type = VIR_NODE_DEV_CAP_STORAGE;
        else if (STREQ(devtype, "wlan"))
            *type = VIR_NODE_DEV_CAP_NET;
M
Marc-André Lureau 已提交
1303 1304
        else if (STREQ(devtype, "drm_minor"))
            *type = VIR_NODE_DEV_CAP_DRM;
1305 1306
    } else {
        /* PCI devices don't set the DEVTYPE property. */
1307
        if (udevHasDeviceProperty(device, "PCI_CLASS"))
1308
            *type = VIR_NODE_DEV_CAP_PCI_DEV;
1309

1310 1311 1312 1313
        /* Wired network interfaces don't set the DEVTYPE property,
         * USB devices also have an INTERFACE property, but they do
         * set DEVTYPE, so if devtype is NULL and the INTERFACE
         * property exists, we have a network device. */
1314
        if (udevHasDeviceProperty(device, "INTERFACE"))
1315
            *type = VIR_NODE_DEV_CAP_NET;
1316

B
Bjoern Walk 已提交
1317 1318
        /* The following devices do not set the DEVTYPE property, therefore
         * we need to rely on the SUBSYSTEM property */
1319 1320 1321 1322
        if (udevGetStringProperty(device, "SUBSYSTEM", &subsystem) < 0)
            return -1;

        if (STREQ_NULLABLE(subsystem, "scsi_generic"))
1323
            *type = VIR_NODE_DEV_CAP_SCSI_GENERIC;
1324 1325
        else if (STREQ_NULLABLE(subsystem, "mdev"))
            *type = VIR_NODE_DEV_CAP_MDEV;
B
Bjoern Walk 已提交
1326 1327
        else if (STREQ_NULLABLE(subsystem, "ccw"))
            *type = VIR_NODE_DEV_CAP_CCW_DEV;
1328

1329
        VIR_FREE(subsystem);
1330 1331
    }

1332 1333 1334 1335 1336 1337
    if (!*type)
        VIR_DEBUG("Could not determine device type for device "
                  "with sysfs name '%s'",
                  udev_device_get_sysname(device));
    else
        ret = 0;
1338 1339 1340 1341 1342

    return ret;
}


1343 1344 1345
static int
udevGetDeviceDetails(struct udev_device *device,
                     virNodeDeviceDefPtr def)
1346
{
1347
    switch (def->caps->data.type) {
1348
    case VIR_NODE_DEV_CAP_PCI_DEV:
1349
        return udevProcessPCI(device, def);
1350
    case VIR_NODE_DEV_CAP_USB_DEV:
1351
        return udevProcessUSBDevice(device, def);
1352
    case VIR_NODE_DEV_CAP_USB_INTERFACE:
1353
        return udevProcessUSBInterface(device, def);
1354
    case VIR_NODE_DEV_CAP_NET:
1355
        return udevProcessNetworkInterface(device, def);
1356
    case VIR_NODE_DEV_CAP_SCSI_HOST:
1357
        return udevProcessSCSIHost(device, def);
D
David Allan 已提交
1358
    case VIR_NODE_DEV_CAP_SCSI_TARGET:
1359
        return udevProcessSCSITarget(device, def);
1360
    case VIR_NODE_DEV_CAP_SCSI:
1361
        return udevProcessSCSIDevice(device, def);
1362
    case VIR_NODE_DEV_CAP_STORAGE:
1363
        return udevProcessStorage(device, def);
1364
    case VIR_NODE_DEV_CAP_SCSI_GENERIC:
1365
        return udevProcessSCSIGeneric(device, def);
M
Marc-André Lureau 已提交
1366
    case VIR_NODE_DEV_CAP_DRM:
1367
        return udevProcessDRMDevice(device, def);
1368
    case VIR_NODE_DEV_CAP_MDEV:
1369
        return udevProcessMediatedDevice(device, def);
B
Bjoern Walk 已提交
1370 1371
    case VIR_NODE_DEV_CAP_CCW_DEV:
        return udevProcessCCW(device, def);
1372
    case VIR_NODE_DEV_CAP_MDEV_TYPES:
1373 1374 1375 1376
    case VIR_NODE_DEV_CAP_SYSTEM:
    case VIR_NODE_DEV_CAP_FC_HOST:
    case VIR_NODE_DEV_CAP_VPORTS:
    case VIR_NODE_DEV_CAP_LAST:
1377 1378 1379
        break;
    }

1380
    return 0;
1381 1382 1383
}


1384 1385
static int
udevRemoveOneDevice(struct udev_device *device)
1386
{
1387
    virNodeDeviceObjPtr obj = NULL;
1388
    virNodeDeviceDefPtr def;
1389
    virObjectEventPtr event = NULL;
1390 1391 1392
    const char *name = NULL;

    name = udev_device_get_syspath(device);
1393
    if (!(obj = virNodeDeviceObjListFindBySysfsPath(driver->devs, name))) {
1394 1395
        VIR_DEBUG("Failed to find device to remove that has udev name '%s'",
                  name);
1396
        return -1;
1397
    }
1398
    def = virNodeDeviceObjGetDef(obj);
1399

1400
    event = virNodeDeviceEventLifecycleNew(def->name,
1401 1402 1403 1404
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

    VIR_DEBUG("Removing device '%s' with sysfs path '%s'",
1405
              def->name, name);
1406
    virNodeDeviceObjListRemove(driver->devs, obj);
1407
    virObjectUnref(obj);
1408 1409 1410

    if (event)
        virObjectEventStateQueue(driver->nodeDeviceEventState, event);
1411
    return 0;
1412 1413 1414
}


1415 1416 1417
static int
udevSetParent(struct udev_device *device,
              virNodeDeviceDefPtr def)
1418 1419 1420
{
    struct udev_device *parent_device = NULL;
    const char *parent_sysfs_path = NULL;
1421
    virNodeDeviceObjPtr obj = NULL;
1422
    virNodeDeviceDefPtr objdef;
1423 1424
    int ret = -1;

1425 1426
    parent_device = device;
    do {
1427

1428
        parent_device = udev_device_get_parent(parent_device);
1429
        if (parent_device == NULL)
1430
            break;
1431

1432 1433
        parent_sysfs_path = udev_device_get_syspath(parent_device);
        if (parent_sysfs_path == NULL) {
1434 1435 1436
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not get syspath for parent of '%s'"),
                           udev_device_get_syspath(parent_device));
1437
            goto cleanup;
1438 1439
        }

1440 1441
        if ((obj = virNodeDeviceObjListFindBySysfsPath(driver->devs,
                                                       parent_sysfs_path))) {
1442
            objdef = virNodeDeviceObjGetDef(obj);
1443
            if (VIR_STRDUP(def->parent, objdef->name) < 0) {
1444
                virNodeDeviceObjEndAPI(&obj);
1445
                goto cleanup;
1446
            }
1447
            virNodeDeviceObjEndAPI(&obj);
1448

1449
            if (VIR_STRDUP(def->parent_sysfs_path, parent_sysfs_path) < 0)
1450
                goto cleanup;
1451 1452 1453 1454
        }

    } while (def->parent == NULL && parent_device != NULL);

1455
    if (!def->parent && VIR_STRDUP(def->parent, "computer") < 0)
1456
        goto cleanup;
1457 1458 1459

    ret = 0;

1460
 cleanup:
1461 1462 1463 1464
    return ret;
}


1465 1466
static int
udevAddOneDevice(struct udev_device *device)
1467 1468
{
    virNodeDeviceDefPtr def = NULL;
1469
    virNodeDeviceObjPtr obj = NULL;
1470
    virNodeDeviceDefPtr objdef;
1471 1472
    virObjectEventPtr event = NULL;
    bool new_device = true;
1473 1474
    int ret = -1;

1475
    if (VIR_ALLOC(def) != 0)
1476
        goto cleanup;
1477

1478
    if (VIR_STRDUP(def->sysfs_path, udev_device_get_syspath(device)) < 0)
1479
        goto cleanup;
1480

1481
    if (udevGetStringProperty(device, "DRIVER", &def->driver) < 0)
1482
        goto cleanup;
1483

1484
    if (VIR_ALLOC(def->caps) != 0)
1485
        goto cleanup;
1486

1487
    if (udevGetDeviceType(device, &def->caps->data.type) != 0)
1488
        goto cleanup;
1489

1490 1491 1492
    if (udevGetDeviceNodes(device, def) != 0)
        goto cleanup;

1493
    if (udevGetDeviceDetails(device, def) != 0)
1494
        goto cleanup;
1495

1496
    if (udevSetParent(device, def) != 0)
1497
        goto cleanup;
1498

1499
    if ((obj = virNodeDeviceObjListFindByName(driver->devs, def->name))) {
1500
        virNodeDeviceObjEndAPI(&obj);
1501 1502 1503
        new_device = false;
    }

1504 1505
    /* If this is a device change, the old definition will be freed
     * and the current definition will take its place. */
1506
    if (!(obj = virNodeDeviceObjListAssignDef(driver->devs, def)))
1507
        goto cleanup;
1508
    objdef = virNodeDeviceObjGetDef(obj);
1509

1510
    if (new_device)
1511
        event = virNodeDeviceEventLifecycleNew(objdef->name,
1512 1513
                                               VIR_NODE_DEVICE_EVENT_CREATED,
                                               0);
1514
    else
1515
        event = virNodeDeviceEventUpdateNew(objdef->name);
1516

1517
    virNodeDeviceObjEndAPI(&obj);
1518 1519 1520

    ret = 0;

1521
 cleanup:
1522 1523 1524
    if (event)
        virObjectEventStateQueue(driver->nodeDeviceEventState, event);

1525
    if (ret != 0) {
1526
        VIR_DEBUG("Discarding device %d %p %s", ret, def,
1527
                  def ? NULLSTR(def->sysfs_path) : "");
1528 1529 1530
        virNodeDeviceDefFree(def);
    }

1531 1532 1533 1534
    return ret;
}


1535 1536 1537
static int
udevProcessDeviceListEntry(struct udev *udev,
                           struct udev_list_entry *list_entry)
1538 1539 1540 1541 1542 1543 1544 1545
{
    struct udev_device *device;
    const char *name = NULL;
    int ret = -1;

    name = udev_list_entry_get_name(list_entry);

    device = udev_device_new_from_syspath(udev, name);
1546

1547 1548
    if (device != NULL) {
        if (udevAddOneDevice(device) != 0) {
1549 1550
            VIR_DEBUG("Failed to create node device for udev device '%s'",
                      name);
1551 1552 1553 1554
        }
        ret = 0;
    }

1555 1556
    udev_device_unref(device);

1557 1558 1559 1560
    return ret;
}


1561 1562 1563 1564 1565 1566 1567 1568
/* We do not care about every device (see udevGetDeviceType).
 * Do not bother enumerating over subsystems that do not
 * contain interesting devices.
 */
const char *subsystem_blacklist[] = {
    "acpi", "tty", "vc", "i2c",
};

1569 1570
static int
udevEnumerateAddMatches(struct udev_enumerate *udev_enumerate)
1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584
{
    size_t i;

    for (i = 0; i < ARRAY_CARDINALITY(subsystem_blacklist); i++) {
        const char *s = subsystem_blacklist[i];
        if (udev_enumerate_add_nomatch_subsystem(udev_enumerate, s) < 0) {
            virReportSystemError(errno, "%s", _("failed to add susbsystem filter"));
            return -1;
        }
    }
    return 0;
}


1585 1586
static int
udevEnumerateDevices(struct udev *udev)
1587 1588 1589
{
    struct udev_enumerate *udev_enumerate = NULL;
    struct udev_list_entry *list_entry = NULL;
1590
    int ret = -1;
1591 1592

    udev_enumerate = udev_enumerate_new(udev);
1593 1594
    if (udevEnumerateAddMatches(udev_enumerate) < 0)
        goto cleanup;
1595 1596

    ret = udev_enumerate_scan_devices(udev_enumerate);
1597
    if (ret != 0) {
1598 1599 1600
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("udev scan devices returned %d"),
                       ret);
1601
        goto cleanup;
1602 1603 1604 1605 1606 1607 1608 1609
    }

    udev_list_entry_foreach(list_entry,
                            udev_enumerate_get_list_entry(udev_enumerate)) {

        udevProcessDeviceListEntry(udev, list_entry);
    }

1610
 cleanup:
1611 1612 1613 1614 1615
    udev_enumerate_unref(udev_enumerate);
    return ret;
}


1616 1617
static void
udevPCITranslateDeinit(void)
1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628
{
#if defined __s390__ || defined __s390x_
    /* Nothing was initialized, nothing needs to be cleaned up */
#else
    /* pci_system_cleanup returns void */
    pci_system_cleanup();
#endif
    return;
}


1629 1630
static int
nodeStateCleanup(void)
1631
{
1632 1633
    udevEventDataPtr priv = NULL;

J
Ján Tomko 已提交
1634 1635
    if (!driver)
        return -1;
1636

1637 1638 1639 1640 1641 1642 1643 1644 1645 1646
    priv = driver->privateData;
    if (priv) {
        virObjectLock(priv);
        priv->threadQuit = true;
        virCondSignal(&priv->threadCond);
        virObjectUnlock(priv);
        virThreadJoin(&priv->th);
    }

    virObjectUnref(priv);
1647
    virObjectUnref(driver->nodeDeviceEventState);
1648

1649
    virNodeDeviceObjListFree(driver->devs);
J
Ján Tomko 已提交
1650 1651
    virMutexDestroy(&driver->lock);
    VIR_FREE(driver);
1652

J
Ján Tomko 已提交
1653 1654
    udevPCITranslateDeinit();
    return 0;
1655 1656 1657
}


1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674
static int
udevHandleOneDevice(struct udev_device *device)
{
    const char *action = udev_device_get_action(device);

    VIR_DEBUG("udev action: '%s'", action);

    if (STREQ(action, "add") || STREQ(action, "change"))
        return udevAddOneDevice(device);

    if (STREQ(action, "remove"))
        return udevRemoveOneDevice(device);

    return 0;
}


1675 1676 1677
/* the caller must be holding the udevEventData object lock prior to calling
 * this function
 */
1678
static bool
1679
udevEventMonitorSanityCheck(udevEventDataPtr priv,
1680
                            int fd)
1681
{
1682
    int rc = -1;
1683

1684
    rc = udev_monitor_get_fd(priv->udev_monitor);
1685
    if (fd != rc) {
1686 1687 1688
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("File descriptor returned by udev %d does not "
                         "match node device file descriptor %d"),
1689
                       fd, rc);
1690 1691 1692 1693 1694 1695 1696 1697

        /* this is a non-recoverable error, let's remove the handle, so that we
         * don't get in here again because of some spurious behaviour and report
         * the same error multiple times
         */
        virEventRemoveHandle(priv->watch);
        priv->watch = -1;

1698
        return false;
1699 1700
    }

1701 1702 1703 1704 1705
    return true;
}


static void
1706
udevEventHandleThread(void *opaque ATTRIBUTE_UNUSED)
1707
{
1708
    udevEventDataPtr priv = driver->privateData;
1709 1710
    struct udev_device *device = NULL;

1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726
    /* continue rather than break from the loop on non-fatal errors */
    while (1) {
        virObjectLock(priv);
        while (!priv->dataReady && !priv->threadQuit) {
            if (virCondWait(&priv->threadCond, &priv->parent.lock)) {
                virReportSystemError(errno, "%s",
                                     _("handler failed to wait on condition"));
                virObjectUnlock(priv);
                return;
            }
        }

        if (priv->threadQuit) {
            virObjectUnlock(priv);
            return;
        }
1727

1728 1729
        errno = 0;
        device = udev_monitor_receive_device(priv->udev_monitor);
1730 1731
        virObjectUnlock(priv);

1732 1733 1734 1735 1736 1737
        if (!device) {
            if (errno == 0) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("failed to receive device from udev monitor"));
                return;
            }
1738

1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749
            /* POSIX allows both EAGAIN and EWOULDBLOCK to be used
             * interchangeably when the read would block or timeout was fired
             */
            VIR_WARNINGS_NO_WLOGICALOP_EQUAL_EXPR
            if (errno != EAGAIN && errno != EWOULDBLOCK) {
            VIR_WARNINGS_RESET
                virReportSystemError(errno, "%s",
                                     _("failed to receive device from udev "
                                       "monitor"));
                return;
            }
1750

1751 1752 1753 1754 1755 1756 1757 1758 1759 1760
            virObjectLock(priv);
            priv->dataReady = false;
            virObjectUnlock(priv);

            continue;
        }

        udevHandleOneDevice(device);
        udev_device_unref(device);
    }
1761 1762 1763
}


1764 1765 1766 1767 1768 1769 1770 1771 1772 1773
static void
udevEventHandleCallback(int watch ATTRIBUTE_UNUSED,
                        int fd,
                        int events ATTRIBUTE_UNUSED,
                        void *data ATTRIBUTE_UNUSED)
{
    udevEventDataPtr priv = driver->privateData;

    virObjectLock(priv);

1774 1775 1776 1777 1778 1779 1780
    if (!udevEventMonitorSanityCheck(priv, fd))
        priv->threadQuit = true;
    else
        priv->dataReady = true;

    virCondSignal(&priv->threadCond);
    virObjectUnlock(priv);
1781 1782 1783
}


1784 1785
/* DMI is intel-compatible specific */
#if defined(__x86_64__) || defined(__i386__) || defined(__amd64__)
1786
static void
1787
udevGetDMIData(virNodeDevCapSystemPtr syscap)
1788
{
1789
    udevEventDataPtr priv = driver->privateData;
1790 1791
    struct udev *udev = NULL;
    struct udev_device *device = NULL;
1792 1793
    virNodeDevCapSystemHardwarePtr hardware = &syscap->hardware;
    virNodeDevCapSystemFirmwarePtr firmware = &syscap->firmware;
1794

1795
    virObjectLock(priv);
1796
    udev = udev_monitor_get_udev(priv->udev_monitor);
1797

1798 1799
    device = udev_device_new_from_syspath(udev, DMI_DEVPATH);
    if (device == NULL) {
1800 1801
        device = udev_device_new_from_syspath(udev, DMI_DEVPATH_FALLBACK);
        if (device == NULL) {
1802 1803 1804
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to get udev device for syspath '%s' or '%s'"),
                           DMI_DEVPATH, DMI_DEVPATH_FALLBACK);
1805
            virObjectUnlock(priv);
1806
            return;
1807
        }
1808
    }
1809
    virObjectUnlock(priv);
1810

1811
    if (udevGetStringSysfsAttr(device, "product_name",
1812
                               &syscap->product_name) < 0)
1813
        goto cleanup;
1814
    if (udevGetStringSysfsAttr(device, "sys_vendor",
1815
                               &hardware->vendor_name) < 0)
1816
        goto cleanup;
1817
    if (udevGetStringSysfsAttr(device, "product_version",
1818
                               &hardware->version) < 0)
1819
        goto cleanup;
1820
    if (udevGetStringSysfsAttr(device, "product_serial",
1821
                               &hardware->serial) < 0)
1822
        goto cleanup;
1823

1824
    if (virGetHostUUID(hardware->uuid))
1825
        goto cleanup;
1826

1827
    if (udevGetStringSysfsAttr(device, "bios_vendor",
1828
                               &firmware->vendor_name) < 0)
1829
        goto cleanup;
1830
    if (udevGetStringSysfsAttr(device, "bios_version",
1831
                               &firmware->version) < 0)
1832
        goto cleanup;
1833
    if (udevGetStringSysfsAttr(device, "bios_date",
1834
                               &firmware->release_date) < 0)
1835
        goto cleanup;
1836

1837
 cleanup:
1838
    if (device != NULL)
1839 1840 1841
        udev_device_unref(device);
    return;
}
1842
#endif
1843 1844


1845 1846
static int
udevSetupSystemDev(void)
1847 1848
{
    virNodeDeviceDefPtr def = NULL;
1849
    virNodeDeviceObjPtr obj = NULL;
1850 1851
    int ret = -1;

1852 1853
    if (VIR_ALLOC(def) < 0)
        return -1;
1854

1855
    if (VIR_STRDUP(def->name, "computer") < 0)
1856
        goto cleanup;
1857

1858
    if (VIR_ALLOC(def->caps) != 0)
1859
        goto cleanup;
1860

1861
#if defined(__x86_64__) || defined(__i386__) || defined(__amd64__)
1862
    udevGetDMIData(&def->caps->data.system);
1863
#endif
1864

1865
    if (!(obj = virNodeDeviceObjListAssignDef(driver->devs, def)))
1866
        goto cleanup;
1867

1868
    virNodeDeviceObjEndAPI(&obj);
1869 1870 1871

    ret = 0;

1872
 cleanup:
1873
    if (ret == -1)
1874 1875
        virNodeDeviceDefFree(def);

1876 1877 1878
    return ret;
}

1879 1880 1881

static int
udevPCITranslateInit(bool privileged ATTRIBUTE_UNUSED)
1882
{
1883 1884 1885 1886
#if defined __s390__ || defined __s390x_
    /* On s390(x) system there is no PCI bus.
     * Therefore there is nothing to initialize here. */
#else
1887
    int rc;
1888

1889
    if ((rc = pci_system_init()) != 0) {
1890 1891 1892
        /* Ignore failure as non-root; udev is not as helpful in that
         * situation, but a non-privileged user won't benefit much
         * from udev in the first place.  */
1893
        if (errno != ENOENT && (privileged  || errno != EACCES)) {
1894 1895
            virReportSystemError(rc, "%s",
                                 _("Failed to initialize libpciaccess"));
1896
            return -1;
1897
        }
1898
    }
1899
#endif
1900 1901 1902
    return 0;
}

1903 1904 1905 1906 1907

static int
nodeStateInitialize(bool privileged,
                    virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                    void *opaque ATTRIBUTE_UNUSED)
1908
{
1909
    udevEventDataPtr priv = NULL;
1910 1911
    struct udev *udev = NULL;

1912
    if (VIR_ALLOC(driver) < 0)
1913
        return -1;
1914

1915
    if (virMutexInit(&driver->lock) < 0) {
1916 1917
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to initialize mutex"));
1918
        VIR_FREE(driver);
1919
        return -1;
1920 1921
    }

1922 1923
    if (!(driver->devs = virNodeDeviceObjListNew()) ||
        !(priv = udevEventDataNew()))
1924
        goto cleanup;
1925

1926
    driver->privateData = priv;
1927
    driver->nodeDeviceEventState = virObjectEventStateNew();
1928

1929
    if (udevPCITranslateInit(privileged) < 0)
1930
        goto cleanup;
1931

1932
    udev = udev_new();
1933 1934 1935
    if (!udev) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to create udev context"));
1936
        goto cleanup;
1937
    }
1938
#if HAVE_UDEV_LOGGING
J
Ján Tomko 已提交
1939 1940
    /* cast to get rid of missing-format-attribute warning */
    udev_set_log_fn(udev, (udevLogFunctionPtr) udevLogFunction);
1941
#endif
1942

1943 1944
    virObjectLock(priv);

1945
    priv->udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
1946
    if (!priv->udev_monitor) {
1947 1948
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("udev_monitor_new_from_netlink returned NULL"));
1949
        goto unlock;
1950 1951
    }

1952
    udev_monitor_enable_receiving(priv->udev_monitor);
1953

1954
#if HAVE_UDEV_MONITOR_SET_RECEIVE_BUFFER_SIZE
1955 1956 1957 1958 1959 1960
    /* mimic udevd's behaviour and override the systems rmem_max limit in case
     * there's a significant number of device 'add' events
     */
    if (geteuid() == 0)
        udev_monitor_set_receive_buffer_size(priv->udev_monitor,
                                             128 * 1024 * 1024);
1961
#endif
1962

1963 1964 1965 1966 1967 1968
    if (virThreadCreate(&priv->th, true, udevEventHandleThread, NULL) < 0) {
        virReportSystemError(errno, "%s",
                             _("failed to create udev handler thread"));
        goto unlock;
    }

1969 1970 1971 1972 1973 1974 1975 1976
    /* We register the monitor with the event callback so we are
     * notified by udev of device changes before we enumerate existing
     * devices because libvirt will simply recreate the device if we
     * try to register it twice, i.e., if the device appears between
     * the time we register the callback and the time we begin
     * enumeration.  The alternative is to register the callback after
     * we enumerate, in which case we will fail to create any devices
     * that appear while the enumeration is taking place.  */
1977 1978 1979
    priv->watch = virEventAddHandle(udev_monitor_get_fd(priv->udev_monitor),
                                    VIR_EVENT_HANDLE_READABLE,
                                    udevEventHandleCallback, NULL, NULL);
1980
    if (priv->watch == -1)
1981
        goto unlock;
1982

1983 1984
    virObjectUnlock(priv);

1985
    /* Create a fictional 'computer' device to root the device tree. */
1986
    if (udevSetupSystemDev() != 0)
1987
        goto cleanup;
1988

1989
    /* Populate with known devices */
1990
    if (udevEnumerateDevices(udev) != 0)
1991
        goto cleanup;
1992

1993
    return 0;
1994

1995
 cleanup:
1996 1997
    nodeStateCleanup();
    return -1;
1998 1999

 unlock:
2000
    virObjectUnlock(priv);
2001
    goto cleanup;
2002 2003 2004
}


2005 2006
static int
nodeStateReload(void)
2007 2008 2009 2010 2011
{
    return 0;
}


2012
static virNodeDeviceDriver udevNodeDeviceDriver = {
2013
    .name = "udev",
2014 2015
    .nodeNumOfDevices = nodeNumOfDevices, /* 0.7.3 */
    .nodeListDevices = nodeListDevices, /* 0.7.3 */
2016
    .connectListAllNodeDevices = nodeConnectListAllNodeDevices, /* 0.10.2 */
2017 2018
    .connectNodeDeviceEventRegisterAny = nodeConnectNodeDeviceEventRegisterAny, /* 2.2.0 */
    .connectNodeDeviceEventDeregisterAny = nodeConnectNodeDeviceEventDeregisterAny, /* 2.2.0 */
2019 2020 2021 2022 2023 2024 2025 2026
    .nodeDeviceLookupByName = nodeDeviceLookupByName, /* 0.7.3 */
    .nodeDeviceLookupSCSIHostByWWN = nodeDeviceLookupSCSIHostByWWN, /* 1.0.2 */
    .nodeDeviceGetXMLDesc = nodeDeviceGetXMLDesc, /* 0.7.3 */
    .nodeDeviceGetParent = nodeDeviceGetParent, /* 0.7.3 */
    .nodeDeviceNumOfCaps = nodeDeviceNumOfCaps, /* 0.7.3 */
    .nodeDeviceListCaps = nodeDeviceListCaps, /* 0.7.3 */
    .nodeDeviceCreateXML = nodeDeviceCreateXML, /* 0.7.3 */
    .nodeDeviceDestroy = nodeDeviceDestroy, /* 0.7.3 */
2027 2028 2029
};

static virStateDriver udevStateDriver = {
M
Matthias Bolte 已提交
2030
    .name = "udev",
2031 2032 2033
    .stateInitialize = nodeStateInitialize, /* 0.7.3 */
    .stateCleanup = nodeStateCleanup, /* 0.7.3 */
    .stateReload = nodeStateReload, /* 0.7.3 */
2034 2035
};

2036 2037 2038

int
udevNodeRegister(void)
2039
{
2040
    VIR_DEBUG("Registering udev node device backend");
2041

2042
    if (virSetSharedNodeDeviceDriver(&udevNodeDeviceDriver) < 0)
2043 2044 2045 2046
        return -1;

    return virRegisterStateDriver(&udevStateDriver);
}