node_device_udev.c 52.9 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
struct _udevPrivate {
    struct udev_monitor *udev_monitor;
    int watch;
59
    bool privileged;
60 61
};

62

J
Ján Tomko 已提交
63 64 65 66 67 68 69 70 71 72 73
static bool
udevHasDeviceProperty(struct udev_device *dev,
                      const char *key)
{
    if (udev_device_get_property_value(dev, key))
        return true;

    return false;
}


74 75 76
static const char *
udevGetDeviceProperty(struct udev_device *udev_device,
                      const char *property_key)
77
{
78
    const char *ret = NULL;
79

80
    ret = udev_device_get_property_value(udev_device, property_key);
81

82 83
    VIR_DEBUG("Found property key '%s' value '%s' for device with sysname '%s'",
              property_key, NULLSTR(ret), udev_device_get_sysname(udev_device));
84 85 86 87 88

    return ret;
}


89 90 91 92
static int
udevGetStringProperty(struct udev_device *udev_device,
                      const char *property_key,
                      char **value)
93
{
94 95
    if (VIR_STRDUP(*value,
                   udevGetDeviceProperty(udev_device, property_key)) < 0)
96
        return -1;
97

98
    return 0;
99 100 101
}


102 103 104 105 106
static int
udevGetIntProperty(struct udev_device *udev_device,
                   const char *property_key,
                   int *value,
                   int base)
107
{
108
    const char *str = NULL;
109

110
    str = udevGetDeviceProperty(udev_device, property_key);
111

112
    if (str && virStrToLong_i(str, NULL, base, value) < 0) {
113 114
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to convert '%s' to int"), str);
115
        return -1;
116
    }
117
    return 0;
118 119 120
}


121 122 123 124 125
static int
udevGetUintProperty(struct udev_device *udev_device,
                    const char *property_key,
                    unsigned int *value,
                    int base)
126
{
127
    const char *str = NULL;
128

129
    str = udevGetDeviceProperty(udev_device, property_key);
130

131
    if (str && virStrToLong_ui(str, NULL, base, value) < 0) {
132 133
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to convert '%s' to int"), str);
134
        return -1;
135
    }
136
    return 0;
137 138 139
}


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

146
    ret = udev_device_get_sysattr_value(udev_device, attr_name);
147 148

    VIR_DEBUG("Found sysfs attribute '%s' value '%s' "
149
              "for device with sysname '%s'",
150
              attr_name, NULLSTR(ret),
151 152 153 154 155
              udev_device_get_sysname(udev_device));
    return ret;
}


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

164
    virStringStripControlChars(*value);
165

166 167
    if (*value != NULL && (STREQ(*value, "")))
        VIR_FREE(*value);
168

169
    return 0;
170 171 172
}


173 174 175 176 177
static int
udevGetIntSysfsAttr(struct udev_device *udev_device,
                    const char *attr_name,
                    int *value,
                    int base)
178
{
179
    const char *str = NULL;
180

181
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
182

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

189
    return 0;
190 191 192
}


193 194 195 196 197
static int
udevGetUintSysfsAttr(struct udev_device *udev_device,
                     const char *attr_name,
                     unsigned int *value,
                     int base)
198
{
199
    const char *str = NULL;
200

201
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
202

203
    if (str && virStrToLong_ui(str, NULL, base, value) < 0) {
204 205
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to convert '%s' to unsigned int"), str);
206
        return -1;
207 208
    }

209
    return 0;
210 211 212
}


213 214 215 216
static int
udevGetUint64SysfsAttr(struct udev_device *udev_device,
                       const char *attr_name,
                       unsigned long long *value)
217
{
218
    const char *str = NULL;
219

220
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
221

222
    if (str && virStrToLong_ull(str, NULL, 0, value) < 0) {
223 224
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to convert '%s' to unsigned long long"), str);
J
Ján Tomko 已提交
225
        return -1;
226 227
    }

J
Ján Tomko 已提交
228
    return 0;
229 230 231
}


232 233 234 235
static int
udevGenerateDeviceName(struct udev_device *device,
                       virNodeDeviceDefPtr def,
                       const char *s)
236
{
237
    size_t i;
238 239
    virBuffer buf = VIR_BUFFER_INITIALIZER;

240
    virBufferAsprintf(&buf, "%s_%s",
241 242 243
                      udev_device_get_subsystem(device),
                      udev_device_get_sysname(device));

244
    if (s != NULL)
245
        virBufferAsprintf(&buf, "_%s", s);
246

247 248
    if (virBufferCheckError(&buf) < 0)
        return -1;
249 250 251

    def->name = virBufferContentAndReset(&buf);

252
    for (i = 0; i < strlen(def->name); i++) {
253
        if (!(c_isalnum(*(def->name + i))))
254 255 256
            *(def->name + i) = '_';
    }

257
    return 0;
258 259
}

260

261
#if HAVE_UDEV_LOGGING
262 263 264 265 266 267 268 269
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 已提交
270 271

static void
272
ATTRIBUTE_FMT_PRINTF(6, 0)
J
Ján Tomko 已提交
273 274 275 276 277 278 279
udevLogFunction(struct udev *udev ATTRIBUTE_UNUSED,
                int priority,
                const char *file,
                int line,
                const char *fn,
                const char *fmt,
                va_list args)
280
{
J
Ján Tomko 已提交
281
    virBuffer buf = VIR_BUFFER_INITIALIZER;
282
    char *format = NULL;
J
Ján Tomko 已提交
283 284 285 286 287 288

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

    format = virBufferContentAndReset(&buf);

289
    virLogVMessage(&virLogSelf,
J
Ján Tomko 已提交
290 291 292 293
                   virLogPriorityFromSyslog(priority),
                   file, line, fn, NULL, format ? format : fmt, args);

    VIR_FREE(format);
294
}
295
#endif
296 297


298 299 300 301 302
static int
udevTranslatePCIIds(unsigned int vendor,
                    unsigned int product,
                    char **vendor_string,
                    char **product_string)
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
{
    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,
318
                    &vendor_name,
319 320 321
                    NULL,
                    NULL);

322
    if (VIR_STRDUP(*vendor_string, vendor_name) < 0 ||
323
        VIR_STRDUP(*product_string, device_name) < 0)
324
        return -1;
325

326
    return 0;
327 328 329
}


330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 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
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;
}


443 444 445
static int
udevProcessPCI(struct udev_device *device,
               virNodeDeviceDefPtr def)
446
{
447
    virNodeDevCapPCIDevPtr pci_dev = &def->caps->data.pci_dev;
448 449
    virPCIEDeviceInfoPtr pci_express = NULL;
    virPCIDevicePtr pciDev = NULL;
450
    udevPrivate *priv = driver->privateData;
451
    int ret = -1;
452
    char *p;
453

454
    if (udevGetUintProperty(device, "PCI_CLASS", &pci_dev->class, 16) < 0)
455
        goto cleanup;
456

457
    if ((p = strrchr(def->sysfs_path, '/')) == NULL ||
458 459 460 461
        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) {
462 463
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to parse the PCI address from sysfs path: '%s'"),
464
                       def->sysfs_path);
465
        goto cleanup;
466 467
    }

468
    if (udevGetUintSysfsAttr(device, "vendor", &pci_dev->vendor, 16) < 0)
469
        goto cleanup;
470

471
    if (udevGetUintSysfsAttr(device, "device", &pci_dev->product, 16) < 0)
472
        goto cleanup;
473

474 475 476 477
    if (udevTranslatePCIIds(pci_dev->vendor,
                            pci_dev->product,
                            &pci_dev->vendor_name,
                            &pci_dev->product_name) != 0) {
478
        goto cleanup;
479
    }
480

481
    if (udevGenerateDeviceName(device, def, NULL) != 0)
482
        goto cleanup;
483

484 485
    /* The default value is -1, because it can't be 0
     * as zero is valid node number. */
486
    pci_dev->numa_node = -1;
487
    if (udevGetIntSysfsAttr(device, "numa_node",
488
                            &pci_dev->numa_node, 10) < 0)
489
        goto cleanup;
490

491
    if (nodeDeviceSysfsGetPCIRelatedDevCaps(def->sysfs_path, pci_dev) < 0)
492
        goto cleanup;
493

494 495 496 497
    if (!(pciDev = virPCIDeviceNew(pci_dev->domain,
                                   pci_dev->bus,
                                   pci_dev->slot,
                                   pci_dev->function)))
498
        goto cleanup;
499

500
    /* We need to be root to read PCI device configs */
501
    if (priv->privileged) {
502
        if (virPCIGetHeaderType(pciDev, &pci_dev->hdrType) < 0)
503
            goto cleanup;
504

505 506
        if (virPCIDeviceIsPCIExpress(pciDev) > 0) {
            if (VIR_ALLOC(pci_express) < 0)
507
                goto cleanup;
508

509 510 511
            if (virPCIDeviceHasPCIExpressLink(pciDev) > 0) {
                if (VIR_ALLOC(pci_express->link_cap) < 0 ||
                    VIR_ALLOC(pci_express->link_sta) < 0)
512
                    goto cleanup;
513 514 515 516 517 518 519

                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)
520
                    goto cleanup;
521 522 523

                pci_express->link_sta->port = -1; /* PCIe can't negotiate port. Yet :) */
            }
524 525
            pci_dev->flags |= VIR_NODE_DEV_CAP_FLAG_PCIE;
            pci_dev->pci_express = pci_express;
526
            pci_express = NULL;
527 528 529
        }
    }

530 531 532 533 534 535
    /* check whether the device is mediated devices framework capable, if so,
     * process it
     */
    if (udevPCIGetMdevTypesCap(device, pci_dev) < 0)
        goto cleanup;

536 537
    ret = 0;

538
 cleanup:
539
    virPCIDeviceFree(pciDev);
540
    virPCIEDeviceInfoFree(pci_express);
541 542 543
    return ret;
}

544 545 546

static int
drmGetMinorType(int minor)
M
Marc-André Lureau 已提交
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562
{
    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;
    }
}

563 564 565 566

static int
udevProcessDRMDevice(struct udev_device *device,
                     virNodeDeviceDefPtr def)
M
Marc-André Lureau 已提交
567
{
568
    virNodeDevCapDRMPtr drm = &def->caps->data.drm;
M
Marc-André Lureau 已提交
569 570 571 572 573 574 575 576 577 578 579
    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;

580
    drm->type = minor;
M
Marc-André Lureau 已提交
581 582 583

    return 0;
}
584

585 586 587 588

static int
udevProcessUSBDevice(struct udev_device *device,
                     virNodeDeviceDefPtr def)
589
{
590
    virNodeDevCapUSBDevPtr usb_dev = &def->caps->data.usb_dev;
591

592
    if (udevGetUintProperty(device, "BUSNUM", &usb_dev->bus, 10) < 0)
593
        return -1;
594
    if (udevGetUintProperty(device, "DEVNUM", &usb_dev->device, 10) < 0)
595
        return -1;
596
    if (udevGetUintProperty(device, "ID_VENDOR_ID", &usb_dev->vendor, 16) < 0)
597
        return -1;
598

599 600
    if (udevGetStringProperty(device,
                              "ID_VENDOR_FROM_DATABASE",
601
                              &usb_dev->vendor_name) < 0)
602
        return -1;
603

604
    if (!usb_dev->vendor_name &&
605
        udevGetStringSysfsAttr(device, "manufacturer",
606
                               &usb_dev->vendor_name) < 0)
607
        return -1;
608

609
    if (udevGetUintProperty(device, "ID_MODEL_ID", &usb_dev->product, 16) < 0)
610
        return -1;
611

612 613
    if (udevGetStringProperty(device,
                              "ID_MODEL_FROM_DATABASE",
614
                              &usb_dev->product_name) < 0)
615
        return -1;
616

617
    if (!usb_dev->product_name &&
618
        udevGetStringSysfsAttr(device, "product",
619
                               &usb_dev->product_name) < 0)
620
        return -1;
621

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

625
    return 0;
626 627 628
}


629 630 631
static int
udevProcessUSBInterface(struct udev_device *device,
                        virNodeDeviceDefPtr def)
632
{
633
    virNodeDevCapUSBIfPtr usb_if = &def->caps->data.usb_if;
634

635
    if (udevGetUintSysfsAttr(device, "bInterfaceNumber",
636
                             &usb_if->number, 16) < 0)
637
        return -1;
638

639
    if (udevGetUintSysfsAttr(device, "bInterfaceClass",
640
                             &usb_if->_class, 16) < 0)
641
        return -1;
642

643
    if (udevGetUintSysfsAttr(device, "bInterfaceSubClass",
644
                             &usb_if->subclass, 16) < 0)
645
        return -1;
646

647
    if (udevGetUintSysfsAttr(device, "bInterfaceProtocol",
648
                             &usb_if->protocol, 16) < 0)
649
        return -1;
650

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

654
    return 0;
655 656 657
}


658 659 660
static int
udevProcessNetworkInterface(struct udev_device *device,
                            virNodeDeviceDefPtr def)
661
{
D
David Allan 已提交
662
    const char *devtype = udev_device_get_devtype(device);
663
    virNodeDevCapNetPtr net = &def->caps->data.net;
664

D
David Allan 已提交
665
    if (devtype && STREQ(devtype, "wlan")) {
666
        net->subtype = VIR_NODE_DEV_CAP_NET_80211;
D
David Allan 已提交
667
    } else {
668
        net->subtype = VIR_NODE_DEV_CAP_NET_80203;
D
David Allan 已提交
669 670
    }

671 672
    if (udevGetStringProperty(device,
                              "INTERFACE",
673
                              &net->ifname) < 0)
674
        return -1;
675

676
    if (udevGetStringSysfsAttr(device, "address",
677
                               &net->address) < 0)
678
        return -1;
679

680
    if (udevGetUintSysfsAttr(device, "addr_len", &net->address_len, 0) < 0)
681
        return -1;
682

683
    if (udevGenerateDeviceName(device, def, net->address) != 0)
684
        return -1;
685

686
    if (virNetDevGetLinkInfo(net->ifname, &net->lnk) < 0)
687
        return -1;
688

689
    if (virNetDevGetFeatures(net->ifname, &net->features) < 0)
690
        return -1;
691

692
    return 0;
693 694 695
}


696 697 698
static int
udevProcessSCSIHost(struct udev_device *device ATTRIBUTE_UNUSED,
                    virNodeDeviceDefPtr def)
699
{
700
    virNodeDevCapSCSIHostPtr scsi_host = &def->caps->data.scsi_host;
701
    char *filename = NULL;
J
Ján Tomko 已提交
702
    char *str;
703

704
    filename = last_component(def->sysfs_path);
705

706
    if (!(str = STRSKIP(filename, "host")) ||
707
        virStrToLong_ui(str, NULL, 0, &scsi_host->host) < 0) {
708 709 710
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to parse SCSI host '%s'"),
                       filename);
711
        return -1;
712 713
    }

714
    nodeDeviceSysfsGetSCSIHostCaps(&def->caps->data.scsi_host);
715

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

719
    return 0;
720 721 722
}


723 724 725
static int
udevProcessSCSITarget(struct udev_device *device,
                      virNodeDeviceDefPtr def)
D
David Allan 已提交
726 727
{
    const char *sysname = NULL;
728
    virNodeDevCapSCSITargetPtr scsi_target = &def->caps->data.scsi_target;
D
David Allan 已提交
729 730 731

    sysname = udev_device_get_sysname(device);

732
    if (VIR_STRDUP(scsi_target->name, sysname) < 0)
733
        return -1;
D
David Allan 已提交
734

735 736
    nodeDeviceSysfsGetSCSITargetCaps(def->sysfs_path, &def->caps->data.scsi_target);

737
    if (udevGenerateDeviceName(device, def, NULL) != 0)
738
        return -1;
D
David Allan 已提交
739

740
    return 0;
D
David Allan 已提交
741 742 743
}


744 745 746 747
static int
udevGetSCSIType(virNodeDeviceDefPtr def ATTRIBUTE_UNUSED,
                unsigned int type,
                char **typestring)
748 749 750 751 752 753 754 755
{
    int ret = 0;
    int foundtype = 1;

    *typestring = NULL;

    switch (type) {
    case TYPE_DISK:
756
        ignore_value(VIR_STRDUP(*typestring, "disk"));
757 758
        break;
    case TYPE_TAPE:
759
        ignore_value(VIR_STRDUP(*typestring, "tape"));
760 761
        break;
    case TYPE_PROCESSOR:
762
        ignore_value(VIR_STRDUP(*typestring, "processor"));
763 764
        break;
    case TYPE_WORM:
765
        ignore_value(VIR_STRDUP(*typestring, "worm"));
766 767
        break;
    case TYPE_ROM:
768
        ignore_value(VIR_STRDUP(*typestring, "cdrom"));
769 770
        break;
    case TYPE_SCANNER:
771
        ignore_value(VIR_STRDUP(*typestring, "scanner"));
772 773
        break;
    case TYPE_MOD:
774
        ignore_value(VIR_STRDUP(*typestring, "mod"));
775 776
        break;
    case TYPE_MEDIUM_CHANGER:
777
        ignore_value(VIR_STRDUP(*typestring, "changer"));
778 779
        break;
    case TYPE_ENCLOSURE:
780
        ignore_value(VIR_STRDUP(*typestring, "enclosure"));
781
        break;
782
    case TYPE_RAID:
783
        ignore_value(VIR_STRDUP(*typestring, "raid"));
784
        break;
785 786 787 788 789 790 791 792 793 794
    case TYPE_NO_LUN:
    default:
        foundtype = 0;
        break;
    }

    if (*typestring == NULL) {
        if (foundtype == 1) {
            ret = -1;
        } else {
795 796
            VIR_DEBUG("Failed to find SCSI device type %d for %s",
                      type, def->sysfs_path);
797 798 799 800 801 802 803
        }
    }

    return ret;
}


804 805 806
static int
udevProcessSCSIDevice(struct udev_device *device ATTRIBUTE_UNUSED,
                      virNodeDeviceDefPtr def)
807 808 809
{
    int ret = -1;
    unsigned int tmp = 0;
810
    virNodeDevCapSCSIPtr scsi = &def->caps->data.scsi;
811 812
    char *filename = NULL, *p = NULL;

813
    filename = last_component(def->sysfs_path);
814

815 816 817 818
    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) {
819 820 821 822
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to parse the SCSI address from filename: '%s'"),
                       filename);
        return -1;
823 824
    }

825 826
    if (udev_device_get_sysattr_value(device, "type")) {
        if (udevGetUintSysfsAttr(device, "type", &tmp, 0) < 0)
827
            goto cleanup;
828

829
        if (udevGetSCSIType(def, tmp, &scsi->type) < 0)
830
            goto cleanup;
831 832
    }

833
    if (udevGenerateDeviceName(device, def, NULL) != 0)
834
        goto cleanup;
835 836 837

    ret = 0;

838
 cleanup:
839
    if (ret != 0) {
840 841 842
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to process SCSI device with sysfs path '%s'"),
                       def->sysfs_path);
843 844 845 846 847
    }
    return ret;
}


848 849 850
static int
udevProcessDisk(struct udev_device *device,
                virNodeDeviceDefPtr def)
851
{
852
    virNodeDevCapStoragePtr storage = &def->caps->data.storage;
853

854
    if (udevGetUint64SysfsAttr(device, "size", &storage->num_blocks) < 0)
855
        return -1;
856

J
Ján Tomko 已提交
857
    if (udevGetUint64SysfsAttr(device, "queue/logical_block_size",
858
                               &storage->logical_block_size) < 0)
859
        return -1;
860

861
    storage->size = storage->num_blocks * storage->logical_block_size;
862

863
    return 0;
864 865 866
}


867 868 869 870
static int
udevProcessRemoveableMedia(struct udev_device *device,
                           virNodeDeviceDefPtr def,
                           int has_media)
871
{
872
    virNodeDevCapStoragePtr storage = &def->caps->data.storage;
J
Ján Tomko 已提交
873
    int is_removable = 0;
874

875 876 877
    if (udevGetIntSysfsAttr(device, "removable", &is_removable, 0) < 0)
        return -1;
    if (is_removable == 1)
878 879
        def->caps->data.storage.flags |= VIR_NODE_DEV_CAP_STORAGE_REMOVABLE;

J
Ján Tomko 已提交
880 881
    if (!has_media)
        return 0;
882

J
Ján Tomko 已提交
883 884
    def->caps->data.storage.flags |=
        VIR_NODE_DEV_CAP_STORAGE_REMOVABLE_MEDIA_AVAILABLE;
885

J
Ján Tomko 已提交
886
    if (udevGetStringProperty(device, "ID_FS_LABEL",
887
                              &storage->media_label) < 0)
J
Ján Tomko 已提交
888
        return -1;
889

J
Ján Tomko 已提交
890
    if (udevGetUint64SysfsAttr(device, "size",
891
                               &storage->num_blocks) < 0)
J
Ján Tomko 已提交
892
        return -1;
893

J
Ján Tomko 已提交
894
    if (udevGetUint64SysfsAttr(device, "queue/logical_block_size",
895
                               &storage->logical_block_size) < 0)
J
Ján Tomko 已提交
896
        return -1;
897

J
Ján Tomko 已提交
898 899 900 901 902 903 904
    /* 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;
905

J
Ján Tomko 已提交
906
    return 0;
907 908
}

909 910 911 912

static int
udevProcessCDROM(struct udev_device *device,
                 virNodeDeviceDefPtr def)
913 914 915 916 917 918 919 920
{
    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);
921
    if (VIR_STRDUP(def->caps->data.storage.drive_type, "cdrom") < 0)
922
        return -1;
923

924 925
    if (udevHasDeviceProperty(device, "ID_CDROM_MEDIA") &&
        udevGetIntProperty(device, "ID_CDROM_MEDIA", &has_media, 0) < 0)
926
        return -1;
927

928
    return udevProcessRemoveableMedia(device, def, has_media);
929 930
}

931 932 933 934

static int
udevProcessFloppy(struct udev_device *device,
                  virNodeDeviceDefPtr def)
935 936 937
{
    int has_media = 0;

938
    if (udevHasDeviceProperty(device, "ID_CDROM_MEDIA")) {
939
        /* USB floppy */
940 941
        if (udevGetIntProperty(device, "DKD_MEDIA_AVAILABLE", &has_media, 0) < 0)
            return -1;
942
    } else if (udevHasDeviceProperty(device, "ID_FS_LABEL")) {
943 944 945 946 947 948
        /* Legacy floppy */
        has_media = 1;
    }

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

950

951 952 953
static int
udevProcessSD(struct udev_device *device,
              virNodeDeviceDefPtr def)
954
{
955
    virNodeDevCapStoragePtr storage = &def->caps->data.storage;
956

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

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

965
    storage->size = storage->num_blocks * storage->logical_block_size;
966

967
    return 0;
968 969 970
}


971 972 973 974
/* 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. */
975 976
static int
udevKludgeStorageType(virNodeDeviceDefPtr def)
977
{
978 979 980
    VIR_DEBUG("Could not find definitive storage type for device "
              "with sysfs path '%s', trying to guess it",
              def->sysfs_path);
981

982 983 984
    /* virtio disk */
    if (STRPREFIX(def->caps->data.storage.block, "/dev/vd") &&
        VIR_STRDUP(def->caps->data.storage.drive_type, "disk") > 0) {
985
        VIR_DEBUG("Found storage type '%s' for device "
986
                  "with sysfs path '%s'",
987 988
                  def->caps->data.storage.drive_type,
                  def->sysfs_path);
989
        return 0;
990
    }
991 992 993
    VIR_DEBUG("Could not determine storage type "
              "for device with sysfs path '%s'", def->sysfs_path);
    return -1;
994 995 996
}


997 998 999
static int
udevProcessStorage(struct udev_device *device,
                   virNodeDeviceDefPtr def)
1000
{
1001
    virNodeDevCapStoragePtr storage = &def->caps->data.storage;
1002
    int ret = -1;
1003
    const char* devnode;
1004

1005
    devnode = udev_device_get_devnode(device);
1006
    if (!devnode) {
1007
        VIR_DEBUG("No devnode for '%s'", udev_device_get_devpath(device));
1008
        goto cleanup;
1009
    }
1010

1011
    if (VIR_STRDUP(storage->block, devnode) < 0)
1012
        goto cleanup;
1013

1014
    if (udevGetStringProperty(device, "ID_BUS", &storage->bus) < 0)
1015
        goto cleanup;
1016
    if (udevGetStringProperty(device, "ID_SERIAL", &storage->serial) < 0)
1017
        goto cleanup;
1018

1019
    if (udevGetStringSysfsAttr(device, "device/vendor", &storage->vendor) < 0)
1020
        goto cleanup;
1021 1022 1023
    if (def->caps->data.storage.vendor)
        virTrimSpaces(def->caps->data.storage.vendor, NULL);

1024
    if (udevGetStringSysfsAttr(device, "device/model", &storage->model) < 0)
1025
        goto cleanup;
1026 1027
    if (def->caps->data.storage.model)
        virTrimSpaces(def->caps->data.storage.model, NULL);
1028 1029 1030 1031 1032
    /* 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. */

1033
    if (udevGetStringProperty(device, "ID_TYPE", &storage->drive_type) < 0)
1034
        goto cleanup;
1035

1036
    if (!storage->drive_type ||
1037
        STREQ(def->caps->data.storage.drive_type, "generic")) {
1038 1039
        int val = 0;
        const char *str = NULL;
1040 1041 1042

        /* All floppy drives have the ID_DRIVE_FLOPPY prop. This is
         * needed since legacy floppies don't have a drive_type */
1043
        if (udevGetIntProperty(device, "ID_DRIVE_FLOPPY", &val, 0) < 0)
1044
            goto cleanup;
1045 1046
        else if (val == 1)
            str = "floppy";
1047

1048
        if (!str) {
1049
            if (udevGetIntProperty(device, "ID_CDROM", &val, 0) < 0)
1050
                goto cleanup;
1051 1052 1053
            else if (val == 1)
                str = "cd";
        }
1054

1055
        if (!str) {
1056
            if (udevGetIntProperty(device, "ID_DRIVE_FLASH_SD", &val, 0) < 0)
1057
                goto cleanup;
1058 1059 1060
            if (val == 1)
                str = "sd";
        }
1061

1062
        if (str) {
1063
            if (VIR_STRDUP(storage->drive_type, str) < 0)
1064
                goto cleanup;
1065 1066
        } else {
            /* If udev doesn't have it, perhaps we can guess it. */
1067
            if (udevKludgeStorageType(def) != 0)
1068
                goto cleanup;
1069 1070 1071 1072 1073 1074 1075
        }
    }

    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);
1076 1077
    } else if (STREQ(def->caps->data.storage.drive_type, "floppy")) {
        ret = udevProcessFloppy(device, def);
1078 1079
    } else if (STREQ(def->caps->data.storage.drive_type, "sd")) {
        ret = udevProcessSD(device, def);
1080
    } else {
1081 1082
        VIR_DEBUG("Unsupported storage type '%s'",
                  def->caps->data.storage.drive_type);
1083
        goto cleanup;
1084 1085
    }

1086
    if (udevGenerateDeviceName(device, def, storage->serial) != 0)
1087
        goto cleanup;
1088

1089
 cleanup:
1090
    VIR_DEBUG("Storage ret=%d", ret);
1091 1092 1093
    return ret;
}

1094

1095
static int
1096
udevProcessSCSIGeneric(struct udev_device *dev,
1097 1098
                       virNodeDeviceDefPtr def)
{
1099 1100
    if (udevGetStringProperty(dev, "DEVNAME", &def->caps->data.sg.path) < 0 ||
        !def->caps->data.sg.path)
1101 1102 1103 1104 1105 1106 1107 1108
        return -1;

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

    return 0;
}

1109

1110 1111 1112 1113 1114 1115 1116 1117
static int
udevProcessMediatedDevice(struct udev_device *dev,
                          virNodeDeviceDefPtr def)
{
    int ret = -1;
    const char *uuidstr = NULL;
    int iommugrp = -1;
    char *linkpath = NULL;
1118
    char *canonicalpath = NULL;
1119 1120 1121 1122 1123
    virNodeDevCapMdevPtr data = &def->caps->data.mdev;

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

1124
    if (virFileResolveLink(linkpath, &canonicalpath) < 0)
1125 1126
        goto cleanup;

1127
    if (VIR_STRDUP(data->type, last_component(canonicalpath)) < 0)
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141
        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);
1142
    VIR_FREE(canonicalpath);
1143 1144 1145
    return ret;
}

B
Bjoern Walk 已提交
1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175

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


1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203
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;
}

1204

1205 1206
static int
udevGetDeviceType(struct udev_device *device,
1207
                  virNodeDevCapType *type)
1208 1209
{
    const char *devtype = NULL;
1210
    char *subsystem = NULL;
1211
    int ret = -1;
D
David Allan 已提交
1212

1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230
    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 已提交
1231 1232
        else if (STREQ(devtype, "drm_minor"))
            *type = VIR_NODE_DEV_CAP_DRM;
1233 1234
    } else {
        /* PCI devices don't set the DEVTYPE property. */
1235
        if (udevHasDeviceProperty(device, "PCI_CLASS"))
1236
            *type = VIR_NODE_DEV_CAP_PCI_DEV;
1237

1238 1239 1240 1241
        /* 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. */
1242
        if (udevHasDeviceProperty(device, "INTERFACE"))
1243
            *type = VIR_NODE_DEV_CAP_NET;
1244

B
Bjoern Walk 已提交
1245 1246
        /* The following devices do not set the DEVTYPE property, therefore
         * we need to rely on the SUBSYSTEM property */
1247 1248 1249 1250
        if (udevGetStringProperty(device, "SUBSYSTEM", &subsystem) < 0)
            return -1;

        if (STREQ_NULLABLE(subsystem, "scsi_generic"))
1251
            *type = VIR_NODE_DEV_CAP_SCSI_GENERIC;
1252 1253
        else if (STREQ_NULLABLE(subsystem, "mdev"))
            *type = VIR_NODE_DEV_CAP_MDEV;
B
Bjoern Walk 已提交
1254 1255
        else if (STREQ_NULLABLE(subsystem, "ccw"))
            *type = VIR_NODE_DEV_CAP_CCW_DEV;
1256

1257
        VIR_FREE(subsystem);
1258 1259
    }

1260 1261 1262 1263 1264 1265
    if (!*type)
        VIR_DEBUG("Could not determine device type for device "
                  "with sysfs name '%s'",
                  udev_device_get_sysname(device));
    else
        ret = 0;
1266 1267 1268 1269 1270

    return ret;
}


1271 1272 1273
static int
udevGetDeviceDetails(struct udev_device *device,
                     virNodeDeviceDefPtr def)
1274
{
1275
    switch (def->caps->data.type) {
1276
    case VIR_NODE_DEV_CAP_PCI_DEV:
1277
        return udevProcessPCI(device, def);
1278
    case VIR_NODE_DEV_CAP_USB_DEV:
1279
        return udevProcessUSBDevice(device, def);
1280
    case VIR_NODE_DEV_CAP_USB_INTERFACE:
1281
        return udevProcessUSBInterface(device, def);
1282
    case VIR_NODE_DEV_CAP_NET:
1283
        return udevProcessNetworkInterface(device, def);
1284
    case VIR_NODE_DEV_CAP_SCSI_HOST:
1285
        return udevProcessSCSIHost(device, def);
D
David Allan 已提交
1286
    case VIR_NODE_DEV_CAP_SCSI_TARGET:
1287
        return udevProcessSCSITarget(device, def);
1288
    case VIR_NODE_DEV_CAP_SCSI:
1289
        return udevProcessSCSIDevice(device, def);
1290
    case VIR_NODE_DEV_CAP_STORAGE:
1291
        return udevProcessStorage(device, def);
1292
    case VIR_NODE_DEV_CAP_SCSI_GENERIC:
1293
        return udevProcessSCSIGeneric(device, def);
M
Marc-André Lureau 已提交
1294
    case VIR_NODE_DEV_CAP_DRM:
1295
        return udevProcessDRMDevice(device, def);
1296
    case VIR_NODE_DEV_CAP_MDEV:
1297
        return udevProcessMediatedDevice(device, def);
B
Bjoern Walk 已提交
1298 1299
    case VIR_NODE_DEV_CAP_CCW_DEV:
        return udevProcessCCW(device, def);
1300
    case VIR_NODE_DEV_CAP_MDEV_TYPES:
1301 1302 1303 1304
    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:
1305 1306 1307
        break;
    }

1308
    return 0;
1309 1310 1311
}


1312 1313
static int
udevRemoveOneDevice(struct udev_device *device)
1314 1315
{
    virNodeDeviceObjPtr dev = NULL;
1316
    virObjectEventPtr event = NULL;
1317
    const char *name = NULL;
1318
    int ret = -1;
1319 1320

    name = udev_device_get_syspath(device);
1321
    dev = virNodeDeviceObjFindBySysfsPath(&driver->devs, name);
1322

1323
    if (!dev) {
1324 1325
        VIR_DEBUG("Failed to find device to remove that has udev name '%s'",
                  name);
1326
        goto cleanup;
1327 1328
    }

1329 1330 1331 1332 1333 1334
    event = virNodeDeviceEventLifecycleNew(dev->def->name,
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

    VIR_DEBUG("Removing device '%s' with sysfs path '%s'",
              dev->def->name, name);
1335
    virNodeDeviceObjRemove(&driver->devs, &dev);
1336 1337 1338 1339 1340

    ret = 0;
 cleanup:
    if (event)
        virObjectEventStateQueue(driver->nodeDeviceEventState, event);
1341 1342 1343 1344
    return ret;
}


1345 1346 1347
static int
udevSetParent(struct udev_device *device,
              virNodeDeviceDefPtr def)
1348 1349 1350 1351 1352 1353
{
    struct udev_device *parent_device = NULL;
    const char *parent_sysfs_path = NULL;
    virNodeDeviceObjPtr dev = NULL;
    int ret = -1;

1354 1355
    parent_device = device;
    do {
1356

1357
        parent_device = udev_device_get_parent(parent_device);
1358
        if (parent_device == NULL)
1359
            break;
1360

1361 1362
        parent_sysfs_path = udev_device_get_syspath(parent_device);
        if (parent_sysfs_path == NULL) {
1363 1364 1365
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not get syspath for parent of '%s'"),
                           udev_device_get_syspath(parent_device));
1366
            goto cleanup;
1367 1368
        }

1369 1370
        dev = virNodeDeviceObjFindBySysfsPath(&driver->devs,
                                              parent_sysfs_path);
1371
        if (dev != NULL) {
1372 1373
            if (VIR_STRDUP(def->parent, dev->def->name) < 0) {
                virNodeDeviceObjUnlock(dev);
1374
                goto cleanup;
1375
            }
1376
            virNodeDeviceObjUnlock(dev);
1377

1378
            if (VIR_STRDUP(def->parent_sysfs_path, parent_sysfs_path) < 0)
1379
                goto cleanup;
1380 1381 1382 1383
        }

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

1384
    if (!def->parent && VIR_STRDUP(def->parent, "computer") < 0)
1385
        goto cleanup;
1386 1387 1388

    ret = 0;

1389
 cleanup:
1390 1391 1392 1393
    return ret;
}


1394 1395
static int
udevAddOneDevice(struct udev_device *device)
1396 1397 1398
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDeviceObjPtr dev = NULL;
1399 1400
    virObjectEventPtr event = NULL;
    bool new_device = true;
1401 1402
    int ret = -1;

1403
    if (VIR_ALLOC(def) != 0)
1404
        goto cleanup;
1405

1406
    if (VIR_STRDUP(def->sysfs_path, udev_device_get_syspath(device)) < 0)
1407
        goto cleanup;
1408

1409
    if (udevGetStringProperty(device, "DRIVER", &def->driver) < 0)
1410
        goto cleanup;
1411

1412
    if (VIR_ALLOC(def->caps) != 0)
1413
        goto cleanup;
1414

1415
    if (udevGetDeviceType(device, &def->caps->data.type) != 0)
1416
        goto cleanup;
1417

1418 1419 1420
    if (udevGetDeviceNodes(device, def) != 0)
        goto cleanup;

1421
    if (udevGetDeviceDetails(device, def) != 0)
1422
        goto cleanup;
1423

1424
    if (udevSetParent(device, def) != 0)
1425
        goto cleanup;
1426

1427
    dev = virNodeDeviceObjFindByName(&driver->devs, def->name);
1428 1429 1430 1431 1432
    if (dev) {
        virNodeDeviceObjUnlock(dev);
        new_device = false;
    }

1433 1434
    /* If this is a device change, the old definition will be freed
     * and the current definition will take its place. */
1435
    dev = virNodeDeviceObjAssignDef(&driver->devs, def);
1436
    if (dev == NULL)
1437
        goto cleanup;
1438

1439 1440 1441 1442
    if (new_device)
        event = virNodeDeviceEventLifecycleNew(dev->def->name,
                                               VIR_NODE_DEVICE_EVENT_CREATED,
                                               0);
1443 1444
    else
        event = virNodeDeviceEventUpdateNew(dev->def->name);
1445

1446 1447 1448 1449
    virNodeDeviceObjUnlock(dev);

    ret = 0;

1450
 cleanup:
1451 1452 1453
    if (event)
        virObjectEventStateQueue(driver->nodeDeviceEventState, event);

1454
    if (ret != 0) {
1455
        VIR_DEBUG("Discarding device %d %p %s", ret, def,
1456
                  def ? NULLSTR(def->sysfs_path) : "");
1457 1458 1459
        virNodeDeviceDefFree(def);
    }

1460 1461 1462 1463
    return ret;
}


1464 1465 1466
static int
udevProcessDeviceListEntry(struct udev *udev,
                           struct udev_list_entry *list_entry)
1467 1468 1469 1470 1471 1472 1473 1474
{
    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);
1475

1476 1477
    if (device != NULL) {
        if (udevAddOneDevice(device) != 0) {
1478 1479
            VIR_DEBUG("Failed to create node device for udev device '%s'",
                      name);
1480 1481 1482 1483
        }
        ret = 0;
    }

1484 1485
    udev_device_unref(device);

1486 1487 1488 1489
    return ret;
}


1490 1491 1492 1493 1494 1495 1496 1497
/* 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",
};

1498 1499
static int
udevEnumerateAddMatches(struct udev_enumerate *udev_enumerate)
1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513
{
    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;
}


1514 1515
static int
udevEnumerateDevices(struct udev *udev)
1516 1517 1518
{
    struct udev_enumerate *udev_enumerate = NULL;
    struct udev_list_entry *list_entry = NULL;
1519
    int ret = -1;
1520 1521

    udev_enumerate = udev_enumerate_new(udev);
1522 1523
    if (udevEnumerateAddMatches(udev_enumerate) < 0)
        goto cleanup;
1524 1525

    ret = udev_enumerate_scan_devices(udev_enumerate);
1526
    if (ret != 0) {
1527 1528 1529
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("udev scan devices returned %d"),
                       ret);
1530
        goto cleanup;
1531 1532 1533 1534 1535 1536 1537 1538
    }

    udev_list_entry_foreach(list_entry,
                            udev_enumerate_get_list_entry(udev_enumerate)) {

        udevProcessDeviceListEntry(udev, list_entry);
    }

1539
 cleanup:
1540 1541 1542 1543 1544
    udev_enumerate_unref(udev_enumerate);
    return ret;
}


1545 1546
static void
udevPCITranslateDeinit(void)
1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557
{
#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;
}


1558 1559
static int
nodeStateCleanup(void)
1560
{
1561
    udevPrivate *priv = NULL;
1562 1563 1564
    struct udev_monitor *udev_monitor = NULL;
    struct udev *udev = NULL;

J
Ján Tomko 已提交
1565 1566
    if (!driver)
        return -1;
1567

J
Ján Tomko 已提交
1568
    nodeDeviceLock();
1569

1570
    virObjectUnref(driver->nodeDeviceEventState);
1571

J
Ján Tomko 已提交
1572
    priv = driver->privateData;
1573

1574 1575 1576
    if (priv) {
        if (priv->watch != -1)
            virEventRemoveHandle(priv->watch);
1577

1578
        udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
1579

1580 1581 1582 1583
        if (udev_monitor != NULL) {
            udev = udev_monitor_get_udev(udev_monitor);
            udev_monitor_unref(udev_monitor);
        }
J
Ján Tomko 已提交
1584
    }
1585

J
Ján Tomko 已提交
1586 1587
    if (udev != NULL)
        udev_unref(udev);
1588

J
Ján Tomko 已提交
1589 1590 1591 1592 1593
    virNodeDeviceObjListFree(&driver->devs);
    nodeDeviceUnlock();
    virMutexDestroy(&driver->lock);
    VIR_FREE(driver);
    VIR_FREE(priv);
1594

J
Ján Tomko 已提交
1595 1596
    udevPCITranslateDeinit();
    return 0;
1597 1598 1599
}


1600 1601 1602 1603 1604
static void
udevEventHandleCallback(int watch ATTRIBUTE_UNUSED,
                        int fd,
                        int events ATTRIBUTE_UNUSED,
                        void *data ATTRIBUTE_UNUSED)
1605 1606
{
    struct udev_device *device = NULL;
1607
    struct udev_monitor *udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
1608 1609 1610
    const char *action = NULL;
    int udev_fd = -1;

1611
    nodeDeviceLock();
1612 1613
    udev_fd = udev_monitor_get_fd(udev_monitor);
    if (fd != udev_fd) {
1614 1615 1616 1617
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("File descriptor returned by udev %d does not "
                         "match node device file descriptor %d"),
                       fd, udev_fd);
1618
        goto cleanup;
1619 1620 1621 1622
    }

    device = udev_monitor_receive_device(udev_monitor);
    if (device == NULL) {
1623 1624
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("udev_monitor_receive_device returned NULL"));
1625
        goto cleanup;
1626 1627 1628
    }

    action = udev_device_get_action(device);
1629
    VIR_DEBUG("udev action: '%s'", action);
1630 1631 1632

    if (STREQ(action, "add") || STREQ(action, "change")) {
        udevAddOneDevice(device);
1633
        goto cleanup;
1634 1635 1636 1637
    }

    if (STREQ(action, "remove")) {
        udevRemoveOneDevice(device);
1638
        goto cleanup;
1639 1640
    }

1641
 cleanup:
1642
    udev_device_unref(device);
1643
    nodeDeviceUnlock();
1644 1645 1646 1647
    return;
}


1648 1649
/* DMI is intel-compatible specific */
#if defined(__x86_64__) || defined(__i386__) || defined(__amd64__)
1650
static void
1651
udevGetDMIData(virNodeDevCapSystemPtr syscap)
1652 1653 1654
{
    struct udev *udev = NULL;
    struct udev_device *device = NULL;
1655 1656
    virNodeDevCapSystemHardwarePtr hardware = &syscap->hardware;
    virNodeDevCapSystemFirmwarePtr firmware = &syscap->firmware;
1657

1658
    udev = udev_monitor_get_udev(DRV_STATE_UDEV_MONITOR(driver));
1659

1660 1661
    device = udev_device_new_from_syspath(udev, DMI_DEVPATH);
    if (device == NULL) {
1662 1663
        device = udev_device_new_from_syspath(udev, DMI_DEVPATH_FALLBACK);
        if (device == NULL) {
1664 1665 1666
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to get udev device for syspath '%s' or '%s'"),
                           DMI_DEVPATH, DMI_DEVPATH_FALLBACK);
1667
            return;
1668
        }
1669 1670
    }

1671
    if (udevGetStringSysfsAttr(device, "product_name",
1672
                               &syscap->product_name) < 0)
1673
        goto cleanup;
1674
    if (udevGetStringSysfsAttr(device, "sys_vendor",
1675
                               &hardware->vendor_name) < 0)
1676
        goto cleanup;
1677
    if (udevGetStringSysfsAttr(device, "product_version",
1678
                               &hardware->version) < 0)
1679
        goto cleanup;
1680
    if (udevGetStringSysfsAttr(device, "product_serial",
1681
                               &hardware->serial) < 0)
1682
        goto cleanup;
1683

1684
    if (virGetHostUUID(hardware->uuid))
1685
        goto cleanup;
1686

1687
    if (udevGetStringSysfsAttr(device, "bios_vendor",
1688
                               &firmware->vendor_name) < 0)
1689
        goto cleanup;
1690
    if (udevGetStringSysfsAttr(device, "bios_version",
1691
                               &firmware->version) < 0)
1692
        goto cleanup;
1693
    if (udevGetStringSysfsAttr(device, "bios_date",
1694
                               &firmware->release_date) < 0)
1695
        goto cleanup;
1696

1697
 cleanup:
1698
    if (device != NULL)
1699 1700 1701
        udev_device_unref(device);
    return;
}
1702
#endif
1703 1704


1705 1706
static int
udevSetupSystemDev(void)
1707 1708 1709 1710 1711
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDeviceObjPtr dev = NULL;
    int ret = -1;

1712 1713
    if (VIR_ALLOC(def) < 0)
        return -1;
1714

1715
    if (VIR_STRDUP(def->name, "computer") < 0)
1716
        goto cleanup;
1717

1718
    if (VIR_ALLOC(def->caps) != 0)
1719
        goto cleanup;
1720

1721
#if defined(__x86_64__) || defined(__i386__) || defined(__amd64__)
1722
    udevGetDMIData(&def->caps->data.system);
1723
#endif
1724

1725
    dev = virNodeDeviceObjAssignDef(&driver->devs, def);
1726
    if (dev == NULL)
1727
        goto cleanup;
1728 1729 1730 1731 1732

    virNodeDeviceObjUnlock(dev);

    ret = 0;

1733
 cleanup:
1734
    if (ret == -1)
1735 1736
        virNodeDeviceDefFree(def);

1737 1738 1739
    return ret;
}

1740 1741 1742

static int
udevPCITranslateInit(bool privileged ATTRIBUTE_UNUSED)
1743
{
1744 1745 1746 1747
#if defined __s390__ || defined __s390x_
    /* On s390(x) system there is no PCI bus.
     * Therefore there is nothing to initialize here. */
#else
1748
    int rc;
1749

1750
    if ((rc = pci_system_init()) != 0) {
1751 1752 1753
        /* 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.  */
1754
        if (errno != ENOENT && (privileged  || errno != EACCES)) {
1755 1756
            virReportSystemError(rc, "%s",
                                 _("Failed to initialize libpciaccess"));
1757
            return -1;
1758
        }
1759
    }
1760
#endif
1761 1762 1763
    return 0;
}

1764 1765 1766 1767 1768

static int
nodeStateInitialize(bool privileged,
                    virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                    void *opaque ATTRIBUTE_UNUSED)
1769 1770 1771 1772 1773
{
    udevPrivate *priv = NULL;
    struct udev *udev = NULL;
    int ret = -1;

1774
    if (VIR_ALLOC(priv) < 0)
1775
        return -1;
1776 1777

    priv->watch = -1;
1778
    priv->privileged = privileged;
1779

1780
    if (VIR_ALLOC(driver) < 0) {
1781
        VIR_FREE(priv);
1782
        return -1;
1783 1784
    }

1785
    if (virMutexInit(&driver->lock) < 0) {
1786 1787
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to initialize mutex"));
1788
        VIR_FREE(priv);
1789
        VIR_FREE(driver);
1790
        return -1;
1791 1792
    }

1793
    driver->privateData = priv;
1794
    nodeDeviceLock();
1795
    driver->nodeDeviceEventState = virObjectEventStateNew();
1796

1797
    if (udevPCITranslateInit(privileged) < 0)
1798
        goto cleanup;
1799

1800
    udev = udev_new();
1801 1802 1803 1804 1805
    if (!udev) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to create udev context"));
        goto cleanup;
    }
1806
#if HAVE_UDEV_LOGGING
J
Ján Tomko 已提交
1807 1808
    /* cast to get rid of missing-format-attribute warning */
    udev_set_log_fn(udev, (udevLogFunctionPtr) udevLogFunction);
1809
#endif
1810

1811 1812
    priv->udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
    if (priv->udev_monitor == NULL) {
1813 1814
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("udev_monitor_new_from_netlink returned NULL"));
1815
        goto cleanup;
1816 1817
    }

1818
    udev_monitor_enable_receiving(priv->udev_monitor);
1819

1820
#if HAVE_UDEV_MONITOR_SET_RECEIVE_BUFFER_SIZE
1821 1822 1823 1824 1825 1826
    /* 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);
1827
#endif
1828

1829 1830 1831 1832 1833 1834 1835 1836
    /* 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.  */
1837 1838 1839
    priv->watch = virEventAddHandle(udev_monitor_get_fd(priv->udev_monitor),
                                    VIR_EVENT_HANDLE_READABLE,
                                    udevEventHandleCallback, NULL, NULL);
1840
    if (priv->watch == -1)
1841
        goto cleanup;
1842 1843

    /* Create a fictional 'computer' device to root the device tree. */
1844
    if (udevSetupSystemDev() != 0)
1845
        goto cleanup;
1846 1847 1848

    /* Populate with known devices */

1849
    if (udevEnumerateDevices(udev) != 0)
1850
        goto cleanup;
1851 1852

    ret = 0;
1853

1854
 cleanup:
1855
    nodeDeviceUnlock();
1856

1857
    if (ret == -1)
1858
        nodeStateCleanup();
1859 1860 1861 1862
    return ret;
}


1863 1864
static int
nodeStateReload(void)
1865 1866 1867 1868 1869
{
    return 0;
}


1870
static virNodeDeviceDriver udevNodeDeviceDriver = {
1871
    .name = "udev",
1872 1873
    .nodeNumOfDevices = nodeNumOfDevices, /* 0.7.3 */
    .nodeListDevices = nodeListDevices, /* 0.7.3 */
1874
    .connectListAllNodeDevices = nodeConnectListAllNodeDevices, /* 0.10.2 */
1875 1876
    .connectNodeDeviceEventRegisterAny = nodeConnectNodeDeviceEventRegisterAny, /* 2.2.0 */
    .connectNodeDeviceEventDeregisterAny = nodeConnectNodeDeviceEventDeregisterAny, /* 2.2.0 */
1877 1878 1879 1880 1881 1882 1883 1884
    .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 */
1885 1886 1887
};

static virStateDriver udevStateDriver = {
M
Matthias Bolte 已提交
1888
    .name = "udev",
1889 1890 1891
    .stateInitialize = nodeStateInitialize, /* 0.7.3 */
    .stateCleanup = nodeStateCleanup, /* 0.7.3 */
    .stateReload = nodeStateReload, /* 0.7.3 */
1892 1893
};

1894 1895 1896

int
udevNodeRegister(void)
1897
{
1898
    VIR_DEBUG("Registering udev node device backend");
1899

1900
    if (virSetSharedNodeDeviceDriver(&udevNodeDeviceDriver) < 0)
1901 1902 1903 1904
        return -1;

    return virRegisterStateDriver(&udevStateDriver);
}