node_device_udev.c 53.1 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
    virNodeDeviceDefPtr def;
1317
    virObjectEventPtr event = NULL;
1318 1319 1320
    const char *name = NULL;

    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
        return -1;
1327
    }
1328
    def = virNodeDeviceObjGetDef(dev);
1329

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

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

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


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

1355 1356
    parent_device = device;
    do {
1357

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

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

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

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

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

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

    ret = 0;

1391
 cleanup:
1392 1393 1394 1395
    return ret;
}


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

1406
    if (VIR_ALLOC(def) != 0)
1407
        goto cleanup;
1408

1409
    if (VIR_STRDUP(def->sysfs_path, udev_device_get_syspath(device)) < 0)
1410
        goto cleanup;
1411

1412
    if (udevGetStringProperty(device, "DRIVER", &def->driver) < 0)
1413
        goto cleanup;
1414

1415
    if (VIR_ALLOC(def->caps) != 0)
1416
        goto cleanup;
1417

1418
    if (udevGetDeviceType(device, &def->caps->data.type) != 0)
1419
        goto cleanup;
1420

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

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

1427
    if (udevSetParent(device, def) != 0)
1428
        goto cleanup;
1429

1430
    dev = virNodeDeviceObjFindByName(&driver->devs, def->name);
1431 1432 1433 1434 1435
    if (dev) {
        virNodeDeviceObjUnlock(dev);
        new_device = false;
    }

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

1443
    if (new_device)
1444
        event = virNodeDeviceEventLifecycleNew(objdef->name,
1445 1446
                                               VIR_NODE_DEVICE_EVENT_CREATED,
                                               0);
1447
    else
1448
        event = virNodeDeviceEventUpdateNew(objdef->name);
1449

1450 1451 1452 1453
    virNodeDeviceObjUnlock(dev);

    ret = 0;

1454
 cleanup:
1455 1456 1457
    if (event)
        virObjectEventStateQueue(driver->nodeDeviceEventState, event);

1458
    if (ret != 0) {
1459
        VIR_DEBUG("Discarding device %d %p %s", ret, def,
1460
                  def ? NULLSTR(def->sysfs_path) : "");
1461 1462 1463
        virNodeDeviceDefFree(def);
    }

1464 1465 1466 1467
    return ret;
}


1468 1469 1470
static int
udevProcessDeviceListEntry(struct udev *udev,
                           struct udev_list_entry *list_entry)
1471 1472 1473 1474 1475 1476 1477 1478
{
    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);
1479

1480 1481
    if (device != NULL) {
        if (udevAddOneDevice(device) != 0) {
1482 1483
            VIR_DEBUG("Failed to create node device for udev device '%s'",
                      name);
1484 1485 1486 1487
        }
        ret = 0;
    }

1488 1489
    udev_device_unref(device);

1490 1491 1492 1493
    return ret;
}


1494 1495 1496 1497 1498 1499 1500 1501
/* 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",
};

1502 1503
static int
udevEnumerateAddMatches(struct udev_enumerate *udev_enumerate)
1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517
{
    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;
}


1518 1519
static int
udevEnumerateDevices(struct udev *udev)
1520 1521 1522
{
    struct udev_enumerate *udev_enumerate = NULL;
    struct udev_list_entry *list_entry = NULL;
1523
    int ret = -1;
1524 1525

    udev_enumerate = udev_enumerate_new(udev);
1526 1527
    if (udevEnumerateAddMatches(udev_enumerate) < 0)
        goto cleanup;
1528 1529

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

    udev_list_entry_foreach(list_entry,
                            udev_enumerate_get_list_entry(udev_enumerate)) {

        udevProcessDeviceListEntry(udev, list_entry);
    }

1543
 cleanup:
1544 1545 1546 1547 1548
    udev_enumerate_unref(udev_enumerate);
    return ret;
}


1549 1550
static void
udevPCITranslateDeinit(void)
1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561
{
#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;
}


1562 1563
static int
nodeStateCleanup(void)
1564
{
1565
    udevPrivate *priv = NULL;
1566 1567 1568
    struct udev_monitor *udev_monitor = NULL;
    struct udev *udev = NULL;

J
Ján Tomko 已提交
1569 1570
    if (!driver)
        return -1;
1571

J
Ján Tomko 已提交
1572
    nodeDeviceLock();
1573

1574
    virObjectUnref(driver->nodeDeviceEventState);
1575

J
Ján Tomko 已提交
1576
    priv = driver->privateData;
1577

1578 1579 1580
    if (priv) {
        if (priv->watch != -1)
            virEventRemoveHandle(priv->watch);
1581

1582
        udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
1583

1584 1585 1586 1587
        if (udev_monitor != NULL) {
            udev = udev_monitor_get_udev(udev_monitor);
            udev_monitor_unref(udev_monitor);
        }
J
Ján Tomko 已提交
1588
    }
1589

J
Ján Tomko 已提交
1590 1591
    if (udev != NULL)
        udev_unref(udev);
1592

J
Ján Tomko 已提交
1593 1594 1595 1596 1597
    virNodeDeviceObjListFree(&driver->devs);
    nodeDeviceUnlock();
    virMutexDestroy(&driver->lock);
    VIR_FREE(driver);
    VIR_FREE(priv);
1598

J
Ján Tomko 已提交
1599 1600
    udevPCITranslateDeinit();
    return 0;
1601 1602 1603
}


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

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

    device = udev_monitor_receive_device(udev_monitor);
    if (device == NULL) {
1627 1628
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("udev_monitor_receive_device returned NULL"));
1629
        goto cleanup;
1630 1631 1632
    }

    action = udev_device_get_action(device);
1633
    VIR_DEBUG("udev action: '%s'", action);
1634 1635 1636

    if (STREQ(action, "add") || STREQ(action, "change")) {
        udevAddOneDevice(device);
1637
        goto cleanup;
1638 1639 1640 1641
    }

    if (STREQ(action, "remove")) {
        udevRemoveOneDevice(device);
1642
        goto cleanup;
1643 1644
    }

1645
 cleanup:
1646
    udev_device_unref(device);
1647
    nodeDeviceUnlock();
1648 1649 1650 1651
    return;
}


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

1662
    udev = udev_monitor_get_udev(DRV_STATE_UDEV_MONITOR(driver));
1663

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

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

1688
    if (virGetHostUUID(hardware->uuid))
1689
        goto cleanup;
1690

1691
    if (udevGetStringSysfsAttr(device, "bios_vendor",
1692
                               &firmware->vendor_name) < 0)
1693
        goto cleanup;
1694
    if (udevGetStringSysfsAttr(device, "bios_version",
1695
                               &firmware->version) < 0)
1696
        goto cleanup;
1697
    if (udevGetStringSysfsAttr(device, "bios_date",
1698
                               &firmware->release_date) < 0)
1699
        goto cleanup;
1700

1701
 cleanup:
1702
    if (device != NULL)
1703 1704 1705
        udev_device_unref(device);
    return;
}
1706
#endif
1707 1708


1709 1710
static int
udevSetupSystemDev(void)
1711 1712 1713 1714 1715
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDeviceObjPtr dev = NULL;
    int ret = -1;

1716 1717
    if (VIR_ALLOC(def) < 0)
        return -1;
1718

1719
    if (VIR_STRDUP(def->name, "computer") < 0)
1720
        goto cleanup;
1721

1722
    if (VIR_ALLOC(def->caps) != 0)
1723
        goto cleanup;
1724

1725
#if defined(__x86_64__) || defined(__i386__) || defined(__amd64__)
1726
    udevGetDMIData(&def->caps->data.system);
1727
#endif
1728

1729
    dev = virNodeDeviceObjAssignDef(&driver->devs, def);
1730
    if (dev == NULL)
1731
        goto cleanup;
1732 1733 1734 1735 1736

    virNodeDeviceObjUnlock(dev);

    ret = 0;

1737
 cleanup:
1738
    if (ret == -1)
1739 1740
        virNodeDeviceDefFree(def);

1741 1742 1743
    return ret;
}

1744 1745 1746

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

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

1768 1769 1770 1771 1772

static int
nodeStateInitialize(bool privileged,
                    virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                    void *opaque ATTRIBUTE_UNUSED)
1773 1774 1775 1776 1777
{
    udevPrivate *priv = NULL;
    struct udev *udev = NULL;
    int ret = -1;

1778
    if (VIR_ALLOC(priv) < 0)
1779
        return -1;
1780 1781

    priv->watch = -1;
1782
    priv->privileged = privileged;
1783

1784
    if (VIR_ALLOC(driver) < 0) {
1785
        VIR_FREE(priv);
1786
        return -1;
1787 1788
    }

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

1797
    driver->privateData = priv;
1798
    nodeDeviceLock();
1799
    driver->nodeDeviceEventState = virObjectEventStateNew();
1800

1801
    if (udevPCITranslateInit(privileged) < 0)
1802
        goto cleanup;
1803

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

1815 1816
    priv->udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
    if (priv->udev_monitor == NULL) {
1817 1818
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("udev_monitor_new_from_netlink returned NULL"));
1819
        goto cleanup;
1820 1821
    }

1822
    udev_monitor_enable_receiving(priv->udev_monitor);
1823

1824
#if HAVE_UDEV_MONITOR_SET_RECEIVE_BUFFER_SIZE
1825 1826 1827 1828 1829 1830
    /* 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);
1831
#endif
1832

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

    /* Create a fictional 'computer' device to root the device tree. */
1848
    if (udevSetupSystemDev() != 0)
1849
        goto cleanup;
1850 1851 1852

    /* Populate with known devices */

1853
    if (udevEnumerateDevices(udev) != 0)
1854
        goto cleanup;
1855 1856

    ret = 0;
1857

1858
 cleanup:
1859
    nodeDeviceUnlock();
1860

1861
    if (ret == -1)
1862
        nodeStateCleanup();
1863 1864 1865 1866
    return ret;
}


1867 1868
static int
nodeStateReload(void)
1869 1870 1871 1872 1873
{
    return 0;
}


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

static virStateDriver udevStateDriver = {
M
Matthias Bolte 已提交
1892
    .name = "udev",
1893 1894 1895
    .stateInitialize = nodeStateInitialize, /* 0.7.3 */
    .stateCleanup = nodeStateCleanup, /* 0.7.3 */
    .stateReload = nodeStateReload, /* 0.7.3 */
1896 1897
};

1898 1899 1900

int
udevNodeRegister(void)
1901
{
1902
    VIR_DEBUG("Registering udev node device backend");
1903

1904
    if (virSetSharedNodeDeviceDriver(&udevNodeDeviceDriver) < 0)
1905 1906 1907 1908
        return -1;

    return virRegisterStateDriver(&udevStateDriver);
}