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 1125
    if (virFileResolveLink(linkpath, &canonicalpath) < 0) {
        virReportSystemError(errno, _("failed to resolve '%s'"), linkpath);
1126
        goto cleanup;
1127
    }
1128

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

B
Bjoern Walk 已提交
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 1176 1177

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


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

1206

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

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

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

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

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

1259
        VIR_FREE(subsystem);
1260 1261
    }

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

    return ret;
}


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

1310
    return 0;
1311 1312 1313
}


1314 1315
static int
udevRemoveOneDevice(struct udev_device *device)
1316
{
1317
    virNodeDeviceObjPtr obj = NULL;
1318
    virNodeDeviceDefPtr def;
1319
    virObjectEventPtr event = NULL;
1320 1321 1322
    const char *name = NULL;

    name = udev_device_get_syspath(device);
1323
    if (!(obj = virNodeDeviceObjListFindBySysfsPath(driver->devs, name))) {
1324 1325
        VIR_DEBUG("Failed to find device to remove that has udev name '%s'",
                  name);
1326
        return -1;
1327
    }
1328
    def = virNodeDeviceObjGetDef(obj);
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
    virNodeDeviceObjListRemove(driver->devs, obj);
1337
    virObjectUnref(obj);
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
{
    struct udev_device *parent_device = NULL;
    const char *parent_sysfs_path = NULL;
1351
    virNodeDeviceObjPtr obj = 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
        if ((obj = virNodeDeviceObjListFindBySysfsPath(driver->devs,
                                                       parent_sysfs_path))) {
1372
            objdef = virNodeDeviceObjGetDef(obj);
1373
            if (VIR_STRDUP(def->parent, objdef->name) < 0) {
1374
                virNodeDeviceObjEndAPI(&obj);
1375
                goto cleanup;
1376
            }
1377
            virNodeDeviceObjEndAPI(&obj);
1378

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

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

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

    ret = 0;

1390
 cleanup:
1391 1392 1393 1394
    return ret;
}


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

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

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

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

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

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

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

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

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

1429
    if ((obj = virNodeDeviceObjListFindByName(driver->devs, def->name))) {
1430
        virNodeDeviceObjEndAPI(&obj);
1431 1432 1433
        new_device = false;
    }

1434 1435
    /* If this is a device change, the old definition will be freed
     * and the current definition will take its place. */
1436
    if (!(obj = virNodeDeviceObjListAssignDef(driver->devs, def)))
1437
        goto cleanup;
1438
    objdef = virNodeDeviceObjGetDef(obj);
1439

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

1447
    virNodeDeviceObjEndAPI(&obj);
1448 1449 1450

    ret = 0;

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

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

1461 1462 1463 1464
    return ret;
}


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

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

1485 1486
    udev_device_unref(device);

1487 1488 1489 1490
    return ret;
}


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

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


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

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

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

    udev_list_entry_foreach(list_entry,
                            udev_enumerate_get_list_entry(udev_enumerate)) {

        udevProcessDeviceListEntry(udev, list_entry);
    }

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


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


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

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

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

1571
    virObjectUnref(driver->nodeDeviceEventState);
1572

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

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

1579
        udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
1580

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

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

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

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


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

    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 1644 1645 1646
    return;
}


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

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

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

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

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

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

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


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

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

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

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

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

1724
    if (!(obj = virNodeDeviceObjListAssignDef(driver->devs, def)))
1725
        goto cleanup;
1726

1727
    virNodeDeviceObjEndAPI(&obj);
1728 1729 1730

    ret = 0;

1731
 cleanup:
1732
    if (ret == -1)
1733 1734
        virNodeDeviceDefFree(def);

1735 1736 1737
    return ret;
}

1738 1739 1740

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

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

1762 1763 1764 1765 1766

static int
nodeStateInitialize(bool privileged,
                    virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                    void *opaque ATTRIBUTE_UNUSED)
1767 1768 1769 1770
{
    udevPrivate *priv = NULL;
    struct udev *udev = NULL;

1771
    if (VIR_ALLOC(priv) < 0)
1772
        return -1;
1773 1774

    priv->watch = -1;
1775
    priv->privileged = privileged;
1776

1777
    if (VIR_ALLOC(driver) < 0) {
1778
        VIR_FREE(priv);
1779
        return -1;
1780 1781
    }

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

1790
    driver->privateData = priv;
1791
    nodeDeviceLock();
1792 1793

    if (!(driver->devs = virNodeDeviceObjListNew()))
1794
        goto unlock;
1795

1796
    driver->nodeDeviceEventState = virObjectEventStateNew();
1797

1798
    if (udevPCITranslateInit(privileged) < 0)
1799
        goto unlock;
1800

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

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

1819
    udev_monitor_enable_receiving(priv->udev_monitor);
1820

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

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

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

1848
    nodeDeviceUnlock();
1849

1850
    /* Populate with known devices */
1851
    if (udevEnumerateDevices(udev) != 0)
1852
        goto cleanup;
1853

1854
    return 0;
1855

1856
 cleanup:
1857 1858
    nodeStateCleanup();
    return -1;
1859 1860 1861 1862

 unlock:
    nodeDeviceUnlock();
    goto cleanup;
1863 1864 1865
}


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


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

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

1897 1898 1899

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

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

    return virRegisterStateDriver(&udevStateDriver);
}