node_device_udev.c 56.7 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
static int
udevFillMdevType(struct udev_device *device,
                 const char *dir,
                 virNodeDevCapMdevTypePtr type)
{
    int ret = -1;
    char *attrpath = NULL;

404 405 406 407 408 409 410 411 412 413
#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) \
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

    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
    virNodeDevCapMdevPtr data = &def->caps->data.mdev;

1191 1192 1193 1194 1195 1196 1197 1198
    /* Because of a kernel uevent race, we might get the 'add' event prior to
     * the sysfs tree being ready, so any attempt to access any sysfs attribute
     * would result in ENOENT and us dropping the device, so let's work around
     * it by waiting for the attributes to become available.
     */

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

1201 1202 1203 1204 1205 1206 1207
    if (virFileWaitForExists(linkpath, 1, 100) < 0) {
        virReportSystemError(errno,
                             _("failed to wait for file '%s' to appear"),
                             linkpath);
        goto cleanup;
    }

1208 1209
    if (virFileResolveLink(linkpath, &canonicalpath) < 0) {
        virReportSystemError(errno, _("failed to resolve '%s'"), linkpath);
1210
        goto cleanup;
1211
    }
1212

1213
    if (VIR_STRDUP(data->type, last_component(canonicalpath)) < 0)
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227
        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);
1228
    VIR_FREE(canonicalpath);
1229 1230 1231
    return ret;
}

B
Bjoern Walk 已提交
1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261

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;
}


1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289
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;
}

1290

1291 1292
static int
udevGetDeviceType(struct udev_device *device,
1293
                  virNodeDevCapType *type)
1294 1295
{
    const char *devtype = NULL;
1296
    char *subsystem = NULL;
1297
    int ret = -1;
D
David Allan 已提交
1298

1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316
    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 已提交
1317 1318
        else if (STREQ(devtype, "drm_minor"))
            *type = VIR_NODE_DEV_CAP_DRM;
1319 1320
    } else {
        /* PCI devices don't set the DEVTYPE property. */
1321
        if (udevHasDeviceProperty(device, "PCI_CLASS"))
1322
            *type = VIR_NODE_DEV_CAP_PCI_DEV;
1323

1324 1325 1326 1327
        /* 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. */
1328
        if (udevHasDeviceProperty(device, "INTERFACE"))
1329
            *type = VIR_NODE_DEV_CAP_NET;
1330

B
Bjoern Walk 已提交
1331 1332
        /* The following devices do not set the DEVTYPE property, therefore
         * we need to rely on the SUBSYSTEM property */
1333 1334 1335 1336
        if (udevGetStringProperty(device, "SUBSYSTEM", &subsystem) < 0)
            return -1;

        if (STREQ_NULLABLE(subsystem, "scsi_generic"))
1337
            *type = VIR_NODE_DEV_CAP_SCSI_GENERIC;
1338 1339
        else if (STREQ_NULLABLE(subsystem, "mdev"))
            *type = VIR_NODE_DEV_CAP_MDEV;
B
Bjoern Walk 已提交
1340 1341
        else if (STREQ_NULLABLE(subsystem, "ccw"))
            *type = VIR_NODE_DEV_CAP_CCW_DEV;
1342

1343
        VIR_FREE(subsystem);
1344 1345
    }

1346 1347 1348 1349 1350 1351
    if (!*type)
        VIR_DEBUG("Could not determine device type for device "
                  "with sysfs name '%s'",
                  udev_device_get_sysname(device));
    else
        ret = 0;
1352 1353 1354 1355 1356

    return ret;
}


1357 1358 1359
static int
udevGetDeviceDetails(struct udev_device *device,
                     virNodeDeviceDefPtr def)
1360
{
1361
    switch (def->caps->data.type) {
1362
    case VIR_NODE_DEV_CAP_PCI_DEV:
1363
        return udevProcessPCI(device, def);
1364
    case VIR_NODE_DEV_CAP_USB_DEV:
1365
        return udevProcessUSBDevice(device, def);
1366
    case VIR_NODE_DEV_CAP_USB_INTERFACE:
1367
        return udevProcessUSBInterface(device, def);
1368
    case VIR_NODE_DEV_CAP_NET:
1369
        return udevProcessNetworkInterface(device, def);
1370
    case VIR_NODE_DEV_CAP_SCSI_HOST:
1371
        return udevProcessSCSIHost(device, def);
D
David Allan 已提交
1372
    case VIR_NODE_DEV_CAP_SCSI_TARGET:
1373
        return udevProcessSCSITarget(device, def);
1374
    case VIR_NODE_DEV_CAP_SCSI:
1375
        return udevProcessSCSIDevice(device, def);
1376
    case VIR_NODE_DEV_CAP_STORAGE:
1377
        return udevProcessStorage(device, def);
1378
    case VIR_NODE_DEV_CAP_SCSI_GENERIC:
1379
        return udevProcessSCSIGeneric(device, def);
M
Marc-André Lureau 已提交
1380
    case VIR_NODE_DEV_CAP_DRM:
1381
        return udevProcessDRMDevice(device, def);
1382
    case VIR_NODE_DEV_CAP_MDEV:
1383
        return udevProcessMediatedDevice(device, def);
B
Bjoern Walk 已提交
1384 1385
    case VIR_NODE_DEV_CAP_CCW_DEV:
        return udevProcessCCW(device, def);
1386
    case VIR_NODE_DEV_CAP_MDEV_TYPES:
1387 1388 1389 1390
    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:
1391 1392 1393
        break;
    }

1394
    return 0;
1395 1396 1397
}


1398 1399
static int
udevRemoveOneDevice(struct udev_device *device)
1400
{
1401
    virNodeDeviceObjPtr obj = NULL;
1402
    virNodeDeviceDefPtr def;
1403
    virObjectEventPtr event = NULL;
1404 1405 1406
    const char *name = NULL;

    name = udev_device_get_syspath(device);
1407
    if (!(obj = virNodeDeviceObjListFindBySysfsPath(driver->devs, name))) {
1408 1409
        VIR_DEBUG("Failed to find device to remove that has udev name '%s'",
                  name);
1410
        return -1;
1411
    }
1412
    def = virNodeDeviceObjGetDef(obj);
1413

1414
    event = virNodeDeviceEventLifecycleNew(def->name,
1415 1416 1417 1418
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

    VIR_DEBUG("Removing device '%s' with sysfs path '%s'",
1419
              def->name, name);
1420
    virNodeDeviceObjListRemove(driver->devs, obj);
1421
    virObjectUnref(obj);
1422 1423 1424

    if (event)
        virObjectEventStateQueue(driver->nodeDeviceEventState, event);
1425
    return 0;
1426 1427 1428
}


1429 1430 1431
static int
udevSetParent(struct udev_device *device,
              virNodeDeviceDefPtr def)
1432 1433 1434
{
    struct udev_device *parent_device = NULL;
    const char *parent_sysfs_path = NULL;
1435
    virNodeDeviceObjPtr obj = NULL;
1436
    virNodeDeviceDefPtr objdef;
1437 1438
    int ret = -1;

1439 1440
    parent_device = device;
    do {
1441

1442
        parent_device = udev_device_get_parent(parent_device);
1443
        if (parent_device == NULL)
1444
            break;
1445

1446 1447
        parent_sysfs_path = udev_device_get_syspath(parent_device);
        if (parent_sysfs_path == NULL) {
1448 1449 1450
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not get syspath for parent of '%s'"),
                           udev_device_get_syspath(parent_device));
1451
            goto cleanup;
1452 1453
        }

1454 1455
        if ((obj = virNodeDeviceObjListFindBySysfsPath(driver->devs,
                                                       parent_sysfs_path))) {
1456
            objdef = virNodeDeviceObjGetDef(obj);
1457
            if (VIR_STRDUP(def->parent, objdef->name) < 0) {
1458
                virNodeDeviceObjEndAPI(&obj);
1459
                goto cleanup;
1460
            }
1461
            virNodeDeviceObjEndAPI(&obj);
1462

1463
            if (VIR_STRDUP(def->parent_sysfs_path, parent_sysfs_path) < 0)
1464
                goto cleanup;
1465 1466 1467 1468
        }

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

1469
    if (!def->parent && VIR_STRDUP(def->parent, "computer") < 0)
1470
        goto cleanup;
1471 1472 1473

    ret = 0;

1474
 cleanup:
1475 1476 1477 1478
    return ret;
}


1479 1480
static int
udevAddOneDevice(struct udev_device *device)
1481 1482
{
    virNodeDeviceDefPtr def = NULL;
1483
    virNodeDeviceObjPtr obj = NULL;
1484
    virNodeDeviceDefPtr objdef;
1485 1486
    virObjectEventPtr event = NULL;
    bool new_device = true;
1487 1488
    int ret = -1;

1489
    if (VIR_ALLOC(def) != 0)
1490
        goto cleanup;
1491

1492
    if (VIR_STRDUP(def->sysfs_path, udev_device_get_syspath(device)) < 0)
1493
        goto cleanup;
1494

1495
    if (udevGetStringProperty(device, "DRIVER", &def->driver) < 0)
1496
        goto cleanup;
1497

1498
    if (VIR_ALLOC(def->caps) != 0)
1499
        goto cleanup;
1500

1501
    if (udevGetDeviceType(device, &def->caps->data.type) != 0)
1502
        goto cleanup;
1503

1504 1505 1506
    if (udevGetDeviceNodes(device, def) != 0)
        goto cleanup;

1507
    if (udevGetDeviceDetails(device, def) != 0)
1508
        goto cleanup;
1509

1510
    if (udevSetParent(device, def) != 0)
1511
        goto cleanup;
1512

1513
    if ((obj = virNodeDeviceObjListFindByName(driver->devs, def->name))) {
1514
        virNodeDeviceObjEndAPI(&obj);
1515 1516 1517
        new_device = false;
    }

1518 1519
    /* If this is a device change, the old definition will be freed
     * and the current definition will take its place. */
1520
    if (!(obj = virNodeDeviceObjListAssignDef(driver->devs, def)))
1521
        goto cleanup;
1522
    objdef = virNodeDeviceObjGetDef(obj);
1523

1524
    if (new_device)
1525
        event = virNodeDeviceEventLifecycleNew(objdef->name,
1526 1527
                                               VIR_NODE_DEVICE_EVENT_CREATED,
                                               0);
1528
    else
1529
        event = virNodeDeviceEventUpdateNew(objdef->name);
1530

1531
    virNodeDeviceObjEndAPI(&obj);
1532 1533 1534

    ret = 0;

1535
 cleanup:
1536 1537 1538
    if (event)
        virObjectEventStateQueue(driver->nodeDeviceEventState, event);

1539
    if (ret != 0) {
1540
        VIR_DEBUG("Discarding device %d %p %s", ret, def,
1541
                  def ? NULLSTR(def->sysfs_path) : "");
1542 1543 1544
        virNodeDeviceDefFree(def);
    }

1545 1546 1547 1548
    return ret;
}


1549 1550 1551
static int
udevProcessDeviceListEntry(struct udev *udev,
                           struct udev_list_entry *list_entry)
1552 1553 1554 1555 1556 1557 1558 1559
{
    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);
1560

1561 1562
    if (device != NULL) {
        if (udevAddOneDevice(device) != 0) {
1563 1564
            VIR_DEBUG("Failed to create node device for udev device '%s'",
                      name);
1565 1566 1567 1568
        }
        ret = 0;
    }

1569 1570
    udev_device_unref(device);

1571 1572 1573 1574
    return ret;
}


1575 1576 1577 1578 1579 1580 1581 1582
/* 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",
};

1583 1584
static int
udevEnumerateAddMatches(struct udev_enumerate *udev_enumerate)
1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598
{
    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;
}


1599 1600
static int
udevEnumerateDevices(struct udev *udev)
1601 1602 1603
{
    struct udev_enumerate *udev_enumerate = NULL;
    struct udev_list_entry *list_entry = NULL;
1604
    int ret = -1;
1605 1606

    udev_enumerate = udev_enumerate_new(udev);
1607 1608
    if (udevEnumerateAddMatches(udev_enumerate) < 0)
        goto cleanup;
1609 1610

    ret = udev_enumerate_scan_devices(udev_enumerate);
1611
    if (ret != 0) {
1612 1613 1614
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("udev scan devices returned %d"),
                       ret);
1615
        goto cleanup;
1616 1617 1618 1619 1620 1621 1622 1623
    }

    udev_list_entry_foreach(list_entry,
                            udev_enumerate_get_list_entry(udev_enumerate)) {

        udevProcessDeviceListEntry(udev, list_entry);
    }

1624
 cleanup:
1625 1626 1627 1628 1629
    udev_enumerate_unref(udev_enumerate);
    return ret;
}


1630 1631
static void
udevPCITranslateDeinit(void)
1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642
{
#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;
}


1643 1644
static int
nodeStateCleanup(void)
1645
{
1646 1647
    udevEventDataPtr priv = NULL;

J
Ján Tomko 已提交
1648 1649
    if (!driver)
        return -1;
1650

1651 1652 1653 1654 1655 1656 1657 1658 1659 1660
    priv = driver->privateData;
    if (priv) {
        virObjectLock(priv);
        priv->threadQuit = true;
        virCondSignal(&priv->threadCond);
        virObjectUnlock(priv);
        virThreadJoin(&priv->th);
    }

    virObjectUnref(priv);
1661
    virObjectUnref(driver->nodeDeviceEventState);
1662

1663
    virNodeDeviceObjListFree(driver->devs);
J
Ján Tomko 已提交
1664 1665
    virMutexDestroy(&driver->lock);
    VIR_FREE(driver);
1666

J
Ján Tomko 已提交
1667 1668
    udevPCITranslateDeinit();
    return 0;
1669 1670 1671
}


1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688
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;
}


1689 1690 1691
/* the caller must be holding the udevEventData object lock prior to calling
 * this function
 */
1692
static bool
1693
udevEventMonitorSanityCheck(udevEventDataPtr priv,
1694
                            int fd)
1695
{
1696
    int rc = -1;
1697

1698
    rc = udev_monitor_get_fd(priv->udev_monitor);
1699
    if (fd != rc) {
1700 1701 1702
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("File descriptor returned by udev %d does not "
                         "match node device file descriptor %d"),
1703
                       fd, rc);
1704 1705 1706 1707 1708 1709 1710 1711

        /* 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;

1712
        return false;
1713 1714
    }

1715 1716 1717 1718 1719
    return true;
}


static void
1720
udevEventHandleThread(void *opaque ATTRIBUTE_UNUSED)
1721
{
1722
    udevEventDataPtr priv = driver->privateData;
1723 1724
    struct udev_device *device = NULL;

1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740
    /* 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;
        }
1741

1742 1743
        errno = 0;
        device = udev_monitor_receive_device(priv->udev_monitor);
1744 1745
        virObjectUnlock(priv);

1746 1747 1748 1749 1750 1751
        if (!device) {
            if (errno == 0) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("failed to receive device from udev monitor"));
                return;
            }
1752

1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763
            /* 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;
            }
1764

1765 1766 1767 1768 1769 1770 1771 1772 1773 1774
            virObjectLock(priv);
            priv->dataReady = false;
            virObjectUnlock(priv);

            continue;
        }

        udevHandleOneDevice(device);
        udev_device_unref(device);
    }
1775 1776 1777
}


1778 1779 1780 1781 1782 1783 1784 1785 1786 1787
static void
udevEventHandleCallback(int watch ATTRIBUTE_UNUSED,
                        int fd,
                        int events ATTRIBUTE_UNUSED,
                        void *data ATTRIBUTE_UNUSED)
{
    udevEventDataPtr priv = driver->privateData;

    virObjectLock(priv);

1788 1789 1790 1791 1792 1793 1794
    if (!udevEventMonitorSanityCheck(priv, fd))
        priv->threadQuit = true;
    else
        priv->dataReady = true;

    virCondSignal(&priv->threadCond);
    virObjectUnlock(priv);
1795 1796 1797
}


1798 1799
/* DMI is intel-compatible specific */
#if defined(__x86_64__) || defined(__i386__) || defined(__amd64__)
1800
static void
1801
udevGetDMIData(virNodeDevCapSystemPtr syscap)
1802
{
1803
    udevEventDataPtr priv = driver->privateData;
1804 1805
    struct udev *udev = NULL;
    struct udev_device *device = NULL;
1806 1807
    virNodeDevCapSystemHardwarePtr hardware = &syscap->hardware;
    virNodeDevCapSystemFirmwarePtr firmware = &syscap->firmware;
1808

1809
    virObjectLock(priv);
1810
    udev = udev_monitor_get_udev(priv->udev_monitor);
1811

1812 1813
    device = udev_device_new_from_syspath(udev, DMI_DEVPATH);
    if (device == NULL) {
1814 1815
        device = udev_device_new_from_syspath(udev, DMI_DEVPATH_FALLBACK);
        if (device == NULL) {
1816 1817 1818
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to get udev device for syspath '%s' or '%s'"),
                           DMI_DEVPATH, DMI_DEVPATH_FALLBACK);
1819
            virObjectUnlock(priv);
1820
            return;
1821
        }
1822
    }
1823
    virObjectUnlock(priv);
1824

1825
    if (udevGetStringSysfsAttr(device, "product_name",
1826
                               &syscap->product_name) < 0)
1827
        goto cleanup;
1828
    if (udevGetStringSysfsAttr(device, "sys_vendor",
1829
                               &hardware->vendor_name) < 0)
1830
        goto cleanup;
1831
    if (udevGetStringSysfsAttr(device, "product_version",
1832
                               &hardware->version) < 0)
1833
        goto cleanup;
1834
    if (udevGetStringSysfsAttr(device, "product_serial",
1835
                               &hardware->serial) < 0)
1836
        goto cleanup;
1837

1838
    if (virGetHostUUID(hardware->uuid))
1839
        goto cleanup;
1840

1841
    if (udevGetStringSysfsAttr(device, "bios_vendor",
1842
                               &firmware->vendor_name) < 0)
1843
        goto cleanup;
1844
    if (udevGetStringSysfsAttr(device, "bios_version",
1845
                               &firmware->version) < 0)
1846
        goto cleanup;
1847
    if (udevGetStringSysfsAttr(device, "bios_date",
1848
                               &firmware->release_date) < 0)
1849
        goto cleanup;
1850

1851
 cleanup:
1852
    if (device != NULL)
1853 1854 1855
        udev_device_unref(device);
    return;
}
1856
#endif
1857 1858


1859 1860
static int
udevSetupSystemDev(void)
1861 1862
{
    virNodeDeviceDefPtr def = NULL;
1863
    virNodeDeviceObjPtr obj = NULL;
1864 1865
    int ret = -1;

1866 1867
    if (VIR_ALLOC(def) < 0)
        return -1;
1868

1869
    if (VIR_STRDUP(def->name, "computer") < 0)
1870
        goto cleanup;
1871

1872
    if (VIR_ALLOC(def->caps) != 0)
1873
        goto cleanup;
1874

1875
#if defined(__x86_64__) || defined(__i386__) || defined(__amd64__)
1876
    udevGetDMIData(&def->caps->data.system);
1877
#endif
1878

1879
    if (!(obj = virNodeDeviceObjListAssignDef(driver->devs, def)))
1880
        goto cleanup;
1881

1882
    virNodeDeviceObjEndAPI(&obj);
1883 1884 1885

    ret = 0;

1886
 cleanup:
1887
    if (ret == -1)
1888 1889
        virNodeDeviceDefFree(def);

1890 1891 1892
    return ret;
}

1893 1894 1895

static int
udevPCITranslateInit(bool privileged ATTRIBUTE_UNUSED)
1896
{
1897 1898 1899 1900
#if defined __s390__ || defined __s390x_
    /* On s390(x) system there is no PCI bus.
     * Therefore there is nothing to initialize here. */
#else
1901
    int rc;
1902

1903
    if ((rc = pci_system_init()) != 0) {
1904 1905 1906
        /* 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.  */
1907
        if (errno != ENOENT && (privileged  || errno != EACCES)) {
1908 1909
            virReportSystemError(rc, "%s",
                                 _("Failed to initialize libpciaccess"));
1910
            return -1;
1911
        }
1912
    }
1913
#endif
1914 1915 1916
    return 0;
}

1917 1918 1919 1920 1921

static int
nodeStateInitialize(bool privileged,
                    virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                    void *opaque ATTRIBUTE_UNUSED)
1922
{
1923
    udevEventDataPtr priv = NULL;
1924 1925
    struct udev *udev = NULL;

1926
    if (VIR_ALLOC(driver) < 0)
1927
        return -1;
1928

1929
    if (virMutexInit(&driver->lock) < 0) {
1930 1931
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to initialize mutex"));
1932
        VIR_FREE(driver);
1933
        return -1;
1934 1935
    }

1936 1937
    if (!(driver->devs = virNodeDeviceObjListNew()) ||
        !(priv = udevEventDataNew()))
1938
        goto cleanup;
1939

1940
    driver->privateData = priv;
1941
    driver->nodeDeviceEventState = virObjectEventStateNew();
1942

1943
    if (udevPCITranslateInit(privileged) < 0)
1944
        goto cleanup;
1945

1946
    udev = udev_new();
1947 1948 1949
    if (!udev) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to create udev context"));
1950
        goto cleanup;
1951
    }
1952
#if HAVE_UDEV_LOGGING
J
Ján Tomko 已提交
1953 1954
    /* cast to get rid of missing-format-attribute warning */
    udev_set_log_fn(udev, (udevLogFunctionPtr) udevLogFunction);
1955
#endif
1956

1957 1958
    virObjectLock(priv);

1959
    priv->udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
1960
    if (!priv->udev_monitor) {
1961 1962
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("udev_monitor_new_from_netlink returned NULL"));
1963
        goto unlock;
1964 1965
    }

1966
    udev_monitor_enable_receiving(priv->udev_monitor);
1967

1968
#if HAVE_UDEV_MONITOR_SET_RECEIVE_BUFFER_SIZE
1969 1970 1971 1972 1973 1974
    /* 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);
1975
#endif
1976

1977 1978 1979 1980 1981 1982
    if (virThreadCreate(&priv->th, true, udevEventHandleThread, NULL) < 0) {
        virReportSystemError(errno, "%s",
                             _("failed to create udev handler thread"));
        goto unlock;
    }

1983 1984 1985 1986 1987 1988 1989 1990
    /* 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.  */
1991 1992 1993
    priv->watch = virEventAddHandle(udev_monitor_get_fd(priv->udev_monitor),
                                    VIR_EVENT_HANDLE_READABLE,
                                    udevEventHandleCallback, NULL, NULL);
1994
    if (priv->watch == -1)
1995
        goto unlock;
1996

1997 1998
    virObjectUnlock(priv);

1999
    /* Create a fictional 'computer' device to root the device tree. */
2000
    if (udevSetupSystemDev() != 0)
2001
        goto cleanup;
2002

2003
    /* Populate with known devices */
2004
    if (udevEnumerateDevices(udev) != 0)
2005
        goto cleanup;
2006

2007
    return 0;
2008

2009
 cleanup:
2010 2011
    nodeStateCleanup();
    return -1;
2012 2013

 unlock:
2014
    virObjectUnlock(priv);
2015
    goto cleanup;
2016 2017 2018
}


2019 2020
static int
nodeStateReload(void)
2021 2022 2023 2024 2025
{
    return 0;
}


2026
static virNodeDeviceDriver udevNodeDeviceDriver = {
2027
    .name = "udev",
2028 2029
    .nodeNumOfDevices = nodeNumOfDevices, /* 0.7.3 */
    .nodeListDevices = nodeListDevices, /* 0.7.3 */
2030
    .connectListAllNodeDevices = nodeConnectListAllNodeDevices, /* 0.10.2 */
2031 2032
    .connectNodeDeviceEventRegisterAny = nodeConnectNodeDeviceEventRegisterAny, /* 2.2.0 */
    .connectNodeDeviceEventDeregisterAny = nodeConnectNodeDeviceEventDeregisterAny, /* 2.2.0 */
2033 2034 2035 2036 2037 2038 2039 2040
    .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 */
2041 2042 2043
};

static virStateDriver udevStateDriver = {
M
Matthias Bolte 已提交
2044
    .name = "udev",
2045 2046 2047
    .stateInitialize = nodeStateInitialize, /* 0.7.3 */
    .stateCleanup = nodeStateCleanup, /* 0.7.3 */
    .stateReload = nodeStateReload, /* 0.7.3 */
2048 2049
};

2050 2051 2052

int
udevNodeRegister(void)
2053
{
2054
    VIR_DEBUG("Registering udev node device backend");
2055

2056
    if (virSetSharedNodeDeviceDriver(&udevNodeDeviceDriver) < 0)
2057 2058 2059 2060
        return -1;

    return virRegisterStateDriver(&udevStateDriver);
}