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 obj = NULL;
1316
    virNodeDeviceDefPtr def;
1317
    virObjectEventPtr event = NULL;
1318 1319 1320
    const char *name = NULL;

    name = udev_device_get_syspath(device);
1321
    if (!(obj = virNodeDeviceObjListFindBySysfsPath(driver->devs, name))) {
1322 1323
        VIR_DEBUG("Failed to find device to remove that has udev name '%s'",
                  name);
1324
        return -1;
1325
    }
1326
    def = virNodeDeviceObjGetDef(obj);
1327

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

    VIR_DEBUG("Removing device '%s' with sysfs path '%s'",
1333
              def->name, name);
1334
    virNodeDeviceObjListRemove(driver->devs, obj);
1335
    virNodeDeviceObjFree(obj);
1336 1337 1338

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


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

1353 1354
    parent_device = device;
    do {
1355

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

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

1368 1369
        if ((obj = virNodeDeviceObjListFindBySysfsPath(driver->devs,
                                                       parent_sysfs_path))) {
1370
            objdef = virNodeDeviceObjGetDef(obj);
1371
            if (VIR_STRDUP(def->parent, objdef->name) < 0) {
1372
                virNodeDeviceObjUnlock(obj);
1373
                goto cleanup;
1374
            }
1375
            virNodeDeviceObjUnlock(obj);
1376

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

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

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

    ret = 0;

1388
 cleanup:
1389 1390 1391 1392
    return ret;
}


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

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

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

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

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

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

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

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

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

1427
    if ((obj = virNodeDeviceObjListFindByName(driver->devs, def->name))) {
1428
        virNodeDeviceObjUnlock(obj);
1429 1430 1431
        new_device = false;
    }

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

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

1445
    virNodeDeviceObjUnlock(obj);
1446 1447 1448

    ret = 0;

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

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

1459 1460 1461 1462
    return ret;
}


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

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

1483 1484
    udev_device_unref(device);

1485 1486 1487 1488
    return ret;
}


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

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


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

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

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

    udev_list_entry_foreach(list_entry,
                            udev_enumerate_get_list_entry(udev_enumerate)) {

        udevProcessDeviceListEntry(udev, list_entry);
    }

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


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


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

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

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

1569
    virObjectUnref(driver->nodeDeviceEventState);
1570

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

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

1577
        udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
1578

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

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

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

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


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

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

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

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

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

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

1640
 cleanup:
1641
    udev_device_unref(device);
1642
    nodeDeviceUnlock();
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
    virNodeDeviceObjUnlock(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 1771
{
    udevPrivate *priv = NULL;
    struct udev *udev = NULL;
    int ret = -1;

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

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

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

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

1791
    driver->privateData = priv;
1792
    nodeDeviceLock();
1793 1794 1795 1796

    if (!(driver->devs = virNodeDeviceObjListNew()))
        goto cleanup;

1797
    driver->nodeDeviceEventState = virObjectEventStateNew();
1798

1799
    if (udevPCITranslateInit(privileged) < 0)
1800
        goto cleanup;
1801

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

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

1820
    udev_monitor_enable_receiving(priv->udev_monitor);
1821

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

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

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

    /* Populate with known devices */

1851
    if (udevEnumerateDevices(udev) != 0)
1852
        goto cleanup;
1853 1854

    ret = 0;
1855

1856
 cleanup:
1857
    nodeDeviceUnlock();
1858

1859
    if (ret == -1)
1860
        nodeStateCleanup();
1861 1862 1863 1864
    return ret;
}


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


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

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

1896 1897 1898

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

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

    return virRegisterStateDriver(&udevStateDriver);
}