node_device_udev.c 47.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
static const char *udevGetDeviceProperty(struct udev_device *udev_device,
                                         const char *property_key)
76
{
77
    const char *ret = NULL;
78

79
    ret = udev_device_get_property_value(udev_device, property_key);
80

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

    return ret;
}


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

96
    return 0;
97 98 99 100 101 102 103 104
}


static int udevGetIntProperty(struct udev_device *udev_device,
                              const char *property_key,
                              int *value,
                              int base)
{
105
    const char *str = NULL;
106

107
    str = udevGetDeviceProperty(udev_device, property_key);
108

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


static int udevGetUintProperty(struct udev_device *udev_device,
                               const char *property_key,
                               unsigned int *value,
                               int base)
{
123
    const char *str = NULL;
124

125
    str = udevGetDeviceProperty(udev_device, property_key);
126

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


136 137
static const char *udevGetDeviceSysfsAttr(struct udev_device *udev_device,
                                          const char *attr_name)
138
{
139
    const char *ret = NULL;
140

141
    ret = udev_device_get_sysattr_value(udev_device, attr_name);
142 143

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


static int udevGetStringSysfsAttr(struct udev_device *udev_device,
                                  const char *attr_name,
                                  char **value)
{
155
    if (VIR_STRDUP(*value, udevGetDeviceSysfsAttr(udev_device, attr_name)) < 0)
156
        return -1;
157

158
    virStringStripControlChars(*value);
159

160 161
    if (*value != NULL && (STREQ(*value, "")))
        VIR_FREE(*value);
162

163
    return 0;
164 165 166 167 168 169 170 171
}


static int udevGetIntSysfsAttr(struct udev_device *udev_device,
                               const char *attr_name,
                               int *value,
                               int base)
{
172
    const char *str = NULL;
173

174
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
175

176
    if (str && virStrToLong_i(str, NULL, base, value) < 0) {
177 178
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to convert '%s' to int"), str);
179
        return -1;
180 181
    }

182
    return 0;
183 184 185 186 187 188 189 190
}


static int udevGetUintSysfsAttr(struct udev_device *udev_device,
                                const char *attr_name,
                                unsigned int *value,
                                int base)
{
191
    const char *str = NULL;
192

193
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
194

195
    if (str && virStrToLong_ui(str, NULL, base, value) < 0) {
196 197
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to convert '%s' to unsigned int"), str);
198
        return -1;
199 200
    }

201
    return 0;
202 203 204 205 206 207 208
}


static int udevGetUint64SysfsAttr(struct udev_device *udev_device,
                                  const char *attr_name,
                                  unsigned long long *value)
{
209
    const char *str = NULL;
210

211
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
212

213
    if (str && virStrToLong_ull(str, NULL, 0, value) < 0) {
214 215
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to convert '%s' to unsigned long long"), str);
J
Ján Tomko 已提交
216
        return -1;
217 218
    }

J
Ján Tomko 已提交
219
    return 0;
220 221 222 223 224 225 226
}


static int udevGenerateDeviceName(struct udev_device *device,
                                  virNodeDeviceDefPtr def,
                                  const char *s)
{
227
    size_t i;
228 229
    virBuffer buf = VIR_BUFFER_INITIALIZER;

230
    virBufferAsprintf(&buf, "%s_%s",
231 232 233
                      udev_device_get_subsystem(device),
                      udev_device_get_sysname(device));

234
    if (s != NULL)
235
        virBufferAsprintf(&buf, "_%s", s);
236

237 238
    if (virBufferCheckError(&buf) < 0)
        return -1;
239 240 241

    def->name = virBufferContentAndReset(&buf);

242
    for (i = 0; i < strlen(def->name); i++) {
243
        if (!(c_isalnum(*(def->name + i))))
244 245 246
            *(def->name + i) = '_';
    }

247
    return 0;
248 249
}

250
#if HAVE_UDEV_LOGGING
J
Ján Tomko 已提交
251 252 253 254 255 256 257 258 259
typedef void (*udevLogFunctionPtr)(struct udev *udev,
                                   int priority,
                                   const char *file,
                                   int line,
                                   const char *fn,
                                   const char *format,
                                   va_list args);

static void
260
ATTRIBUTE_FMT_PRINTF(6, 0)
J
Ján Tomko 已提交
261 262 263 264 265 266 267
udevLogFunction(struct udev *udev ATTRIBUTE_UNUSED,
                int priority,
                const char *file,
                int line,
                const char *fn,
                const char *fmt,
                va_list args)
268
{
J
Ján Tomko 已提交
269
    virBuffer buf = VIR_BUFFER_INITIALIZER;
270
    char *format = NULL;
J
Ján Tomko 已提交
271 272 273 274 275 276

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

    format = virBufferContentAndReset(&buf);

277
    virLogVMessage(&virLogSelf,
J
Ján Tomko 已提交
278 279 280 281
                   virLogPriorityFromSyslog(priority),
                   file, line, fn, NULL, format ? format : fmt, args);

    VIR_FREE(format);
282
}
283
#endif
284 285


286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
static int udevTranslatePCIIds(unsigned int vendor,
                               unsigned int product,
                               char **vendor_string,
                               char **product_string)
{
    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,
305
                    &vendor_name,
306 307 308
                    NULL,
                    NULL);

309
    if (VIR_STRDUP(*vendor_string, vendor_name) < 0 ||
310
        VIR_STRDUP(*product_string, device_name) < 0)
311
        return -1;
312

313
    return 0;
314 315 316
}


317 318 319
static int udevProcessPCI(struct udev_device *device,
                          virNodeDeviceDefPtr def)
{
320
    virNodeDevCapPCIDevPtr pci_dev = &def->caps->data.pci_dev;
321 322
    virPCIEDeviceInfoPtr pci_express = NULL;
    virPCIDevicePtr pciDev = NULL;
323
    udevPrivate *priv = driver->privateData;
324
    int ret = -1;
325
    char *p;
326

327
    if (udevGetUintProperty(device, "PCI_CLASS", &pci_dev->class, 16) < 0)
328
        goto cleanup;
329

330
    if ((p = strrchr(def->sysfs_path, '/')) == NULL ||
331 332 333 334
        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) {
335 336
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to parse the PCI address from sysfs path: '%s'"),
337
                       def->sysfs_path);
338
        goto cleanup;
339 340
    }

341
    if (udevGetUintSysfsAttr(device, "vendor", &pci_dev->vendor, 16) < 0)
342
        goto cleanup;
343

344
    if (udevGetUintSysfsAttr(device, "device", &pci_dev->product, 16) < 0)
345
        goto cleanup;
346

347 348 349 350
    if (udevTranslatePCIIds(pci_dev->vendor,
                            pci_dev->product,
                            &pci_dev->vendor_name,
                            &pci_dev->product_name) != 0) {
351
        goto cleanup;
352
    }
353

354
    if (udevGenerateDeviceName(device, def, NULL) != 0)
355
        goto cleanup;
356

357 358
    /* The default value is -1, because it can't be 0
     * as zero is valid node number. */
359
    pci_dev->numa_node = -1;
360
    if (udevGetIntSysfsAttr(device, "numa_node",
361
                            &pci_dev->numa_node, 10) < 0)
362
        goto cleanup;
363

364
    if (nodeDeviceSysfsGetPCIRelatedDevCaps(def->sysfs_path, pci_dev) < 0)
365
        goto cleanup;
366

367 368 369 370
    if (!(pciDev = virPCIDeviceNew(pci_dev->domain,
                                   pci_dev->bus,
                                   pci_dev->slot,
                                   pci_dev->function)))
371
        goto cleanup;
372

373
    /* We need to be root to read PCI device configs */
374
    if (priv->privileged) {
375
        if (virPCIGetHeaderType(pciDev, &pci_dev->hdrType) < 0)
376
            goto cleanup;
377

378 379
        if (virPCIDeviceIsPCIExpress(pciDev) > 0) {
            if (VIR_ALLOC(pci_express) < 0)
380
                goto cleanup;
381

382 383 384
            if (virPCIDeviceHasPCIExpressLink(pciDev) > 0) {
                if (VIR_ALLOC(pci_express->link_cap) < 0 ||
                    VIR_ALLOC(pci_express->link_sta) < 0)
385
                    goto cleanup;
386 387 388 389 390 391 392

                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)
393
                    goto cleanup;
394 395 396

                pci_express->link_sta->port = -1; /* PCIe can't negotiate port. Yet :) */
            }
397 398
            pci_dev->flags |= VIR_NODE_DEV_CAP_FLAG_PCIE;
            pci_dev->pci_express = pci_express;
399
            pci_express = NULL;
400 401 402
        }
    }

403 404
    ret = 0;

405
 cleanup:
406
    virPCIDeviceFree(pciDev);
407
    virPCIEDeviceInfoFree(pci_express);
408 409 410
    return ret;
}

M
Marc-André Lureau 已提交
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
static int drmGetMinorType(int minor)
{
    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;
    }
}

static int udevProcessDRMDevice(struct udev_device *device,
                                virNodeDeviceDefPtr def)
{
431
    virNodeDevCapDRMPtr drm = &def->caps->data.drm;
M
Marc-André Lureau 已提交
432 433 434 435 436 437 438 439 440 441 442
    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;

443
    drm->type = minor;
M
Marc-André Lureau 已提交
444 445 446

    return 0;
}
447 448 449 450

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

453
    if (udevGetUintProperty(device, "BUSNUM", &usb_dev->bus, 10) < 0)
454
        return -1;
455
    if (udevGetUintProperty(device, "DEVNUM", &usb_dev->device, 10) < 0)
456
        return -1;
457
    if (udevGetUintProperty(device, "ID_VENDOR_ID", &usb_dev->vendor, 16) < 0)
458
        return -1;
459

460 461
    if (udevGetStringProperty(device,
                              "ID_VENDOR_FROM_DATABASE",
462
                              &usb_dev->vendor_name) < 0)
463
        return -1;
464

465
    if (!usb_dev->vendor_name &&
466
        udevGetStringSysfsAttr(device, "manufacturer",
467
                               &usb_dev->vendor_name) < 0)
468
        return -1;
469

470
    if (udevGetUintProperty(device, "ID_MODEL_ID", &usb_dev->product, 16) < 0)
471
        return -1;
472

473 474
    if (udevGetStringProperty(device,
                              "ID_MODEL_FROM_DATABASE",
475
                              &usb_dev->product_name) < 0)
476
        return -1;
477

478
    if (!usb_dev->product_name &&
479
        udevGetStringSysfsAttr(device, "product",
480
                               &usb_dev->product_name) < 0)
481
        return -1;
482

483
    if (udevGenerateDeviceName(device, def, NULL) != 0)
484
        return -1;
485

486
    return 0;
487 488 489 490 491 492
}


static int udevProcessUSBInterface(struct udev_device *device,
                                   virNodeDeviceDefPtr def)
{
493
    virNodeDevCapUSBIfPtr usb_if = &def->caps->data.usb_if;
494

495
    if (udevGetUintSysfsAttr(device, "bInterfaceNumber",
496
                             &usb_if->number, 16) < 0)
497
        return -1;
498

499
    if (udevGetUintSysfsAttr(device, "bInterfaceClass",
500
                             &usb_if->_class, 16) < 0)
501
        return -1;
502

503
    if (udevGetUintSysfsAttr(device, "bInterfaceSubClass",
504
                             &usb_if->subclass, 16) < 0)
505
        return -1;
506

507
    if (udevGetUintSysfsAttr(device, "bInterfaceProtocol",
508
                             &usb_if->protocol, 16) < 0)
509
        return -1;
510

511
    if (udevGenerateDeviceName(device, def, NULL) != 0)
512
        return -1;
513

514
    return 0;
515 516 517 518 519 520
}


static int udevProcessNetworkInterface(struct udev_device *device,
                                       virNodeDeviceDefPtr def)
{
D
David Allan 已提交
521
    const char *devtype = udev_device_get_devtype(device);
522
    virNodeDevCapNetPtr net = &def->caps->data.net;
523

D
David Allan 已提交
524
    if (devtype && STREQ(devtype, "wlan")) {
525
        net->subtype = VIR_NODE_DEV_CAP_NET_80211;
D
David Allan 已提交
526
    } else {
527
        net->subtype = VIR_NODE_DEV_CAP_NET_80203;
D
David Allan 已提交
528 529
    }

530 531
    if (udevGetStringProperty(device,
                              "INTERFACE",
532
                              &net->ifname) < 0)
533
        return -1;
534

535
    if (udevGetStringSysfsAttr(device, "address",
536
                               &net->address) < 0)
537
        return -1;
538

539
    if (udevGetUintSysfsAttr(device, "addr_len", &net->address_len, 0) < 0)
540
        return -1;
541

542
    if (udevGenerateDeviceName(device, def, net->address) != 0)
543
        return -1;
544

545
    if (virNetDevGetLinkInfo(net->ifname, &net->lnk) < 0)
546
        return -1;
547

548
    if (virNetDevGetFeatures(net->ifname, &net->features) < 0)
549
        return -1;
550

551
    return 0;
552 553 554 555 556 557
}


static int udevProcessSCSIHost(struct udev_device *device ATTRIBUTE_UNUSED,
                               virNodeDeviceDefPtr def)
{
558
    virNodeDevCapSCSIHostPtr scsi_host = &def->caps->data.scsi_host;
559
    char *filename = NULL;
J
Ján Tomko 已提交
560
    char *str;
561

562
    filename = last_component(def->sysfs_path);
563

564
    if (!(str = STRSKIP(filename, "host")) ||
565
        virStrToLong_ui(str, NULL, 0, &scsi_host->host) < 0) {
566 567 568
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to parse SCSI host '%s'"),
                       filename);
569
        return -1;
570 571
    }

572
    nodeDeviceSysfsGetSCSIHostCaps(&def->caps->data.scsi_host);
573

574
    if (udevGenerateDeviceName(device, def, NULL) != 0)
575
        return -1;
576

577
    return 0;
578 579 580
}


D
David Allan 已提交
581 582 583 584
static int udevProcessSCSITarget(struct udev_device *device ATTRIBUTE_UNUSED,
                                 virNodeDeviceDefPtr def)
{
    const char *sysname = NULL;
585
    virNodeDevCapSCSITargetPtr scsi_target = &def->caps->data.scsi_target;
D
David Allan 已提交
586 587 588

    sysname = udev_device_get_sysname(device);

589
    if (VIR_STRDUP(scsi_target->name, sysname) < 0)
590
        return -1;
D
David Allan 已提交
591

592
    if (udevGenerateDeviceName(device, def, NULL) != 0)
593
        return -1;
D
David Allan 已提交
594

595
    return 0;
D
David Allan 已提交
596 597 598
}


599
static int udevGetSCSIType(virNodeDeviceDefPtr def ATTRIBUTE_UNUSED,
600
                           unsigned int type, char **typestring)
601 602 603 604 605 606 607 608
{
    int ret = 0;
    int foundtype = 1;

    *typestring = NULL;

    switch (type) {
    case TYPE_DISK:
609
        ignore_value(VIR_STRDUP(*typestring, "disk"));
610 611
        break;
    case TYPE_TAPE:
612
        ignore_value(VIR_STRDUP(*typestring, "tape"));
613 614
        break;
    case TYPE_PROCESSOR:
615
        ignore_value(VIR_STRDUP(*typestring, "processor"));
616 617
        break;
    case TYPE_WORM:
618
        ignore_value(VIR_STRDUP(*typestring, "worm"));
619 620
        break;
    case TYPE_ROM:
621
        ignore_value(VIR_STRDUP(*typestring, "cdrom"));
622 623
        break;
    case TYPE_SCANNER:
624
        ignore_value(VIR_STRDUP(*typestring, "scanner"));
625 626
        break;
    case TYPE_MOD:
627
        ignore_value(VIR_STRDUP(*typestring, "mod"));
628 629
        break;
    case TYPE_MEDIUM_CHANGER:
630
        ignore_value(VIR_STRDUP(*typestring, "changer"));
631 632
        break;
    case TYPE_ENCLOSURE:
633
        ignore_value(VIR_STRDUP(*typestring, "enclosure"));
634
        break;
635
    case TYPE_RAID:
636
        ignore_value(VIR_STRDUP(*typestring, "raid"));
637
        break;
638 639 640 641 642 643 644 645 646 647
    case TYPE_NO_LUN:
    default:
        foundtype = 0;
        break;
    }

    if (*typestring == NULL) {
        if (foundtype == 1) {
            ret = -1;
        } else {
648 649
            VIR_DEBUG("Failed to find SCSI device type %d for %s",
                      type, def->sysfs_path);
650 651 652 653 654 655 656 657 658 659 660 661
        }
    }

    return ret;
}


static int udevProcessSCSIDevice(struct udev_device *device ATTRIBUTE_UNUSED,
                                 virNodeDeviceDefPtr def)
{
    int ret = -1;
    unsigned int tmp = 0;
662
    virNodeDevCapSCSIPtr scsi = &def->caps->data.scsi;
663 664
    char *filename = NULL, *p = NULL;

665
    filename = last_component(def->sysfs_path);
666

667 668 669 670
    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) {
671 672 673 674
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to parse the SCSI address from filename: '%s'"),
                       filename);
        return -1;
675 676
    }

677 678
    if (udev_device_get_sysattr_value(device, "type")) {
        if (udevGetUintSysfsAttr(device, "type", &tmp, 0) < 0)
679
            goto cleanup;
680

681
        if (udevGetSCSIType(def, tmp, &scsi->type) < 0)
682
            goto cleanup;
683 684
    }

685
    if (udevGenerateDeviceName(device, def, NULL) != 0)
686
        goto cleanup;
687 688 689

    ret = 0;

690
 cleanup:
691
    if (ret != 0) {
692 693 694
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to process SCSI device with sysfs path '%s'"),
                       def->sysfs_path);
695 696 697 698 699 700 701 702
    }
    return ret;
}


static int udevProcessDisk(struct udev_device *device,
                           virNodeDeviceDefPtr def)
{
703
    virNodeDevCapStoragePtr storage = &def->caps->data.storage;
704

705
    if (udevGetUint64SysfsAttr(device, "size", &storage->num_blocks) < 0)
706
        return -1;
707

J
Ján Tomko 已提交
708
    if (udevGetUint64SysfsAttr(device, "queue/logical_block_size",
709
                               &storage->logical_block_size) < 0)
710
        return -1;
711

712
    storage->size = storage->num_blocks * storage->logical_block_size;
713

714
    return 0;
715 716 717
}


718 719 720
static int udevProcessRemoveableMedia(struct udev_device *device,
                                      virNodeDeviceDefPtr def,
                                      int has_media)
721
{
722
    virNodeDevCapStoragePtr storage = &def->caps->data.storage;
J
Ján Tomko 已提交
723
    int is_removable = 0;
724

725 726 727
    if (udevGetIntSysfsAttr(device, "removable", &is_removable, 0) < 0)
        return -1;
    if (is_removable == 1)
728 729
        def->caps->data.storage.flags |= VIR_NODE_DEV_CAP_STORAGE_REMOVABLE;

J
Ján Tomko 已提交
730 731
    if (!has_media)
        return 0;
732

J
Ján Tomko 已提交
733 734
    def->caps->data.storage.flags |=
        VIR_NODE_DEV_CAP_STORAGE_REMOVABLE_MEDIA_AVAILABLE;
735

J
Ján Tomko 已提交
736
    if (udevGetStringProperty(device, "ID_FS_LABEL",
737
                              &storage->media_label) < 0)
J
Ján Tomko 已提交
738
        return -1;
739

J
Ján Tomko 已提交
740
    if (udevGetUint64SysfsAttr(device, "size",
741
                               &storage->num_blocks) < 0)
J
Ján Tomko 已提交
742
        return -1;
743

J
Ján Tomko 已提交
744
    if (udevGetUint64SysfsAttr(device, "queue/logical_block_size",
745
                               &storage->logical_block_size) < 0)
J
Ján Tomko 已提交
746
        return -1;
747

J
Ján Tomko 已提交
748 749 750 751 752 753 754
    /* 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;
755

J
Ján Tomko 已提交
756
    return 0;
757 758
}

759 760 761 762 763 764 765 766 767 768
static int udevProcessCDROM(struct udev_device *device,
                            virNodeDeviceDefPtr def)
{
    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);
769
    if (VIR_STRDUP(def->caps->data.storage.drive_type, "cdrom") < 0)
770
        return -1;
771

772 773
    if (udevHasDeviceProperty(device, "ID_CDROM_MEDIA") &&
        udevGetIntProperty(device, "ID_CDROM_MEDIA", &has_media, 0) < 0)
774
        return -1;
775

776
    return udevProcessRemoveableMedia(device, def, has_media);
777 778 779 780 781 782 783
}

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

784
    if (udevHasDeviceProperty(device, "ID_CDROM_MEDIA")) {
785
        /* USB floppy */
786 787
        if (udevGetIntProperty(device, "DKD_MEDIA_AVAILABLE", &has_media, 0) < 0)
            return -1;
788
    } else if (udevHasDeviceProperty(device, "ID_FS_LABEL")) {
789 790 791 792 793 794
        /* Legacy floppy */
        has_media = 1;
    }

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

796 797 798 799

static int udevProcessSD(struct udev_device *device,
                         virNodeDeviceDefPtr def)
{
800
    virNodeDevCapStoragePtr storage = &def->caps->data.storage;
801

J
Ján Tomko 已提交
802
    if (udevGetUint64SysfsAttr(device, "size",
803
                               &storage->num_blocks) < 0)
804
        return -1;
805

J
Ján Tomko 已提交
806
    if (udevGetUint64SysfsAttr(device, "queue/logical_block_size",
807
                               &storage->logical_block_size) < 0)
808
        return -1;
809

810
    storage->size = storage->num_blocks * storage->logical_block_size;
811

812
    return 0;
813 814 815 816
}



817 818 819 820 821 822
/* 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. */
static int udevKludgeStorageType(virNodeDeviceDefPtr def)
{
823 824 825
    VIR_DEBUG("Could not find definitive storage type for device "
              "with sysfs path '%s', trying to guess it",
              def->sysfs_path);
826

827 828 829
    /* virtio disk */
    if (STRPREFIX(def->caps->data.storage.block, "/dev/vd") &&
        VIR_STRDUP(def->caps->data.storage.drive_type, "disk") > 0) {
830
        VIR_DEBUG("Found storage type '%s' for device "
831
                  "with sysfs path '%s'",
832 833
                  def->caps->data.storage.drive_type,
                  def->sysfs_path);
834
        return 0;
835
    }
836 837 838
    VIR_DEBUG("Could not determine storage type "
              "for device with sysfs path '%s'", def->sysfs_path);
    return -1;
839 840 841 842 843 844
}


static int udevProcessStorage(struct udev_device *device,
                              virNodeDeviceDefPtr def)
{
845
    virNodeDevCapStoragePtr storage = &def->caps->data.storage;
846
    int ret = -1;
847
    const char* devnode;
848

849
    devnode = udev_device_get_devnode(device);
850
    if (!devnode) {
851
        VIR_DEBUG("No devnode for '%s'", udev_device_get_devpath(device));
852
        goto cleanup;
853
    }
854

855
    if (VIR_STRDUP(storage->block, devnode) < 0)
856
        goto cleanup;
857

858
    if (udevGetStringProperty(device, "ID_BUS", &storage->bus) < 0)
859
        goto cleanup;
860
    if (udevGetStringProperty(device, "ID_SERIAL", &storage->serial) < 0)
861
        goto cleanup;
862

863
    if (udevGetStringSysfsAttr(device, "device/vendor", &storage->vendor) < 0)
864
        goto cleanup;
865 866 867
    if (def->caps->data.storage.vendor)
        virTrimSpaces(def->caps->data.storage.vendor, NULL);

868
    if (udevGetStringSysfsAttr(device, "device/model", &storage->model) < 0)
869
        goto cleanup;
870 871
    if (def->caps->data.storage.model)
        virTrimSpaces(def->caps->data.storage.model, NULL);
872 873 874 875 876
    /* 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. */

877
    if (udevGetStringProperty(device, "ID_TYPE", &storage->drive_type) < 0)
878
        goto cleanup;
879

880
    if (!storage->drive_type ||
881
        STREQ(def->caps->data.storage.drive_type, "generic")) {
882 883
        int val = 0;
        const char *str = NULL;
884 885 886

        /* All floppy drives have the ID_DRIVE_FLOPPY prop. This is
         * needed since legacy floppies don't have a drive_type */
887
        if (udevGetIntProperty(device, "ID_DRIVE_FLOPPY", &val, 0) < 0)
888
            goto cleanup;
889 890
        else if (val == 1)
            str = "floppy";
891

892
        if (!str) {
893
            if (udevGetIntProperty(device, "ID_CDROM", &val, 0) < 0)
894
                goto cleanup;
895 896 897
            else if (val == 1)
                str = "cd";
        }
898

899
        if (!str) {
900
            if (udevGetIntProperty(device, "ID_DRIVE_FLASH_SD", &val, 0) < 0)
901
                goto cleanup;
902 903 904
            if (val == 1)
                str = "sd";
        }
905

906
        if (str) {
907
            if (VIR_STRDUP(storage->drive_type, str) < 0)
908
                goto cleanup;
909 910
        } else {
            /* If udev doesn't have it, perhaps we can guess it. */
911
            if (udevKludgeStorageType(def) != 0)
912
                goto cleanup;
913 914 915 916 917 918 919
        }
    }

    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);
920 921
    } else if (STREQ(def->caps->data.storage.drive_type, "floppy")) {
        ret = udevProcessFloppy(device, def);
922 923
    } else if (STREQ(def->caps->data.storage.drive_type, "sd")) {
        ret = udevProcessSD(device, def);
924
    } else {
925 926
        VIR_DEBUG("Unsupported storage type '%s'",
                  def->caps->data.storage.drive_type);
927
        goto cleanup;
928 929
    }

930
    if (udevGenerateDeviceName(device, def, storage->serial) != 0)
931
        goto cleanup;
932

933
 cleanup:
934
    VIR_DEBUG("Storage ret=%d", ret);
935 936 937
    return ret;
}

938
static int
939
udevProcessSCSIGeneric(struct udev_device *dev,
940 941
                       virNodeDeviceDefPtr def)
{
942 943
    if (udevGetStringProperty(dev, "DEVNAME", &def->caps->data.sg.path) < 0 ||
        !def->caps->data.sg.path)
944 945 946 947 948 949 950 951
        return -1;

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

    return 0;
}

952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979
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;
}

980 981
static int
udevGetDeviceType(struct udev_device *device,
982
                  virNodeDevCapType *type)
983 984
{
    const char *devtype = NULL;
985
    char *subsystem = NULL;
986
    int ret = -1;
D
David Allan 已提交
987

988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005
    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 已提交
1006 1007
        else if (STREQ(devtype, "drm_minor"))
            *type = VIR_NODE_DEV_CAP_DRM;
1008 1009
    } else {
        /* PCI devices don't set the DEVTYPE property. */
1010
        if (udevHasDeviceProperty(device, "PCI_CLASS"))
1011
            *type = VIR_NODE_DEV_CAP_PCI_DEV;
1012

1013 1014 1015 1016
        /* 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. */
1017
        if (udevHasDeviceProperty(device, "INTERFACE"))
1018
            *type = VIR_NODE_DEV_CAP_NET;
1019 1020

        /* SCSI generic device doesn't set DEVTYPE property */
1021 1022 1023 1024
        if (udevGetStringProperty(device, "SUBSYSTEM", &subsystem) < 0)
            return -1;

        if (STREQ_NULLABLE(subsystem, "scsi_generic"))
1025 1026
            *type = VIR_NODE_DEV_CAP_SCSI_GENERIC;
        VIR_FREE(subsystem);
1027 1028
    }

1029 1030 1031 1032 1033 1034
    if (!*type)
        VIR_DEBUG("Could not determine device type for device "
                  "with sysfs name '%s'",
                  udev_device_get_sysname(device));
    else
        ret = 0;
1035 1036 1037 1038 1039 1040 1041 1042

    return ret;
}


static int udevGetDeviceDetails(struct udev_device *device,
                                virNodeDeviceDefPtr def)
{
1043
    switch (def->caps->data.type) {
1044
    case VIR_NODE_DEV_CAP_PCI_DEV:
1045
        return udevProcessPCI(device, def);
1046
    case VIR_NODE_DEV_CAP_USB_DEV:
1047
        return udevProcessUSBDevice(device, def);
1048
    case VIR_NODE_DEV_CAP_USB_INTERFACE:
1049
        return udevProcessUSBInterface(device, def);
1050
    case VIR_NODE_DEV_CAP_NET:
1051
        return udevProcessNetworkInterface(device, def);
1052
    case VIR_NODE_DEV_CAP_SCSI_HOST:
1053
        return udevProcessSCSIHost(device, def);
D
David Allan 已提交
1054
    case VIR_NODE_DEV_CAP_SCSI_TARGET:
1055
        return udevProcessSCSITarget(device, def);
1056
    case VIR_NODE_DEV_CAP_SCSI:
1057
        return udevProcessSCSIDevice(device, def);
1058
    case VIR_NODE_DEV_CAP_STORAGE:
1059
        return udevProcessStorage(device, def);
1060
    case VIR_NODE_DEV_CAP_SCSI_GENERIC:
1061
        return udevProcessSCSIGeneric(device, def);
M
Marc-André Lureau 已提交
1062
    case VIR_NODE_DEV_CAP_DRM:
1063
        return udevProcessDRMDevice(device, def);
1064 1065
    case VIR_NODE_DEV_CAP_MDEV:
    case VIR_NODE_DEV_CAP_MDEV_TYPES:
1066 1067 1068 1069
    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:
1070 1071 1072
        break;
    }

1073
    return 0;
1074 1075 1076 1077 1078 1079
}


static int udevRemoveOneDevice(struct udev_device *device)
{
    virNodeDeviceObjPtr dev = NULL;
1080
    virObjectEventPtr event = NULL;
1081
    const char *name = NULL;
1082
    int ret = -1;
1083 1084

    name = udev_device_get_syspath(device);
1085
    dev = virNodeDeviceObjFindBySysfsPath(&driver->devs, name);
1086

1087
    if (!dev) {
1088 1089
        VIR_DEBUG("Failed to find device to remove that has udev name '%s'",
                  name);
1090
        goto cleanup;
1091 1092
    }

1093 1094 1095 1096 1097 1098
    event = virNodeDeviceEventLifecycleNew(dev->def->name,
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

    VIR_DEBUG("Removing device '%s' with sysfs path '%s'",
              dev->def->name, name);
1099
    virNodeDeviceObjRemove(&driver->devs, &dev);
1100 1101 1102 1103 1104

    ret = 0;
 cleanup:
    if (event)
        virObjectEventStateQueue(driver->nodeDeviceEventState, event);
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116
    return ret;
}


static int udevSetParent(struct udev_device *device,
                         virNodeDeviceDefPtr def)
{
    struct udev_device *parent_device = NULL;
    const char *parent_sysfs_path = NULL;
    virNodeDeviceObjPtr dev = NULL;
    int ret = -1;

1117 1118
    parent_device = device;
    do {
1119

1120
        parent_device = udev_device_get_parent(parent_device);
1121
        if (parent_device == NULL)
1122
            break;
1123

1124 1125
        parent_sysfs_path = udev_device_get_syspath(parent_device);
        if (parent_sysfs_path == NULL) {
1126 1127 1128
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not get syspath for parent of '%s'"),
                           udev_device_get_syspath(parent_device));
1129
            goto cleanup;
1130 1131
        }

1132 1133
        dev = virNodeDeviceObjFindBySysfsPath(&driver->devs,
                                              parent_sysfs_path);
1134
        if (dev != NULL) {
1135 1136
            if (VIR_STRDUP(def->parent, dev->def->name) < 0) {
                virNodeDeviceObjUnlock(dev);
1137
                goto cleanup;
1138
            }
1139
            virNodeDeviceObjUnlock(dev);
1140

1141
            if (VIR_STRDUP(def->parent_sysfs_path, parent_sysfs_path) < 0)
1142
                goto cleanup;
1143 1144 1145 1146
        }

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

1147
    if (!def->parent && VIR_STRDUP(def->parent, "computer") < 0)
1148
        goto cleanup;
1149 1150 1151

    ret = 0;

1152
 cleanup:
1153 1154 1155 1156 1157 1158 1159 1160
    return ret;
}


static int udevAddOneDevice(struct udev_device *device)
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDeviceObjPtr dev = NULL;
1161 1162
    virObjectEventPtr event = NULL;
    bool new_device = true;
1163 1164
    int ret = -1;

1165
    if (VIR_ALLOC(def) != 0)
1166
        goto cleanup;
1167

1168
    if (VIR_STRDUP(def->sysfs_path, udev_device_get_syspath(device)) < 0)
1169
        goto cleanup;
1170

1171
    if (udevGetStringProperty(device, "DRIVER", &def->driver) < 0)
1172
        goto cleanup;
1173

1174
    if (VIR_ALLOC(def->caps) != 0)
1175
        goto cleanup;
1176

1177
    if (udevGetDeviceType(device, &def->caps->data.type) != 0)
1178
        goto cleanup;
1179

1180 1181 1182
    if (udevGetDeviceNodes(device, def) != 0)
        goto cleanup;

1183
    if (udevGetDeviceDetails(device, def) != 0)
1184
        goto cleanup;
1185

1186
    if (udevSetParent(device, def) != 0)
1187
        goto cleanup;
1188

1189
    dev = virNodeDeviceObjFindByName(&driver->devs, def->name);
1190 1191 1192 1193 1194
    if (dev) {
        virNodeDeviceObjUnlock(dev);
        new_device = false;
    }

1195 1196
    /* If this is a device change, the old definition will be freed
     * and the current definition will take its place. */
1197
    dev = virNodeDeviceObjAssignDef(&driver->devs, def);
1198
    if (dev == NULL)
1199
        goto cleanup;
1200

1201 1202 1203 1204
    if (new_device)
        event = virNodeDeviceEventLifecycleNew(dev->def->name,
                                               VIR_NODE_DEVICE_EVENT_CREATED,
                                               0);
1205 1206
    else
        event = virNodeDeviceEventUpdateNew(dev->def->name);
1207

1208 1209 1210 1211
    virNodeDeviceObjUnlock(dev);

    ret = 0;

1212
 cleanup:
1213 1214 1215
    if (event)
        virObjectEventStateQueue(driver->nodeDeviceEventState, event);

1216
    if (ret != 0) {
1217
        VIR_DEBUG("Discarding device %d %p %s", ret, def,
1218
                  def ? NULLSTR(def->sysfs_path) : "");
1219 1220 1221
        virNodeDeviceDefFree(def);
    }

1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235
    return ret;
}


static int udevProcessDeviceListEntry(struct udev *udev,
                                      struct udev_list_entry *list_entry)
{
    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);
1236

1237 1238
    if (device != NULL) {
        if (udevAddOneDevice(device) != 0) {
1239 1240
            VIR_DEBUG("Failed to create node device for udev device '%s'",
                      name);
1241 1242 1243 1244
        }
        ret = 0;
    }

1245 1246
    udev_device_unref(device);

1247 1248 1249 1250
    return ret;
}


1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273
/* 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",
};

static int udevEnumerateAddMatches(struct udev_enumerate *udev_enumerate)
{
    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;
}


1274 1275 1276 1277
static int udevEnumerateDevices(struct udev *udev)
{
    struct udev_enumerate *udev_enumerate = NULL;
    struct udev_list_entry *list_entry = NULL;
1278
    int ret = -1;
1279 1280

    udev_enumerate = udev_enumerate_new(udev);
1281 1282
    if (udevEnumerateAddMatches(udev_enumerate) < 0)
        goto cleanup;
1283 1284

    ret = udev_enumerate_scan_devices(udev_enumerate);
1285
    if (ret != 0) {
1286 1287 1288
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("udev scan devices returned %d"),
                       ret);
1289
        goto cleanup;
1290 1291 1292 1293 1294 1295 1296 1297
    }

    udev_list_entry_foreach(list_entry,
                            udev_enumerate_get_list_entry(udev_enumerate)) {

        udevProcessDeviceListEntry(udev, list_entry);
    }

1298
 cleanup:
1299 1300 1301 1302 1303
    udev_enumerate_unref(udev_enumerate);
    return ret;
}


1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315
static void udevPCITranslateDeinit(void)
{
#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;
}


1316
static int nodeStateCleanup(void)
1317
{
1318
    udevPrivate *priv = NULL;
1319 1320 1321
    struct udev_monitor *udev_monitor = NULL;
    struct udev *udev = NULL;

J
Ján Tomko 已提交
1322 1323
    if (!driver)
        return -1;
1324

J
Ján Tomko 已提交
1325
    nodeDeviceLock();
1326

1327
    virObjectUnref(driver->nodeDeviceEventState);
1328

J
Ján Tomko 已提交
1329
    priv = driver->privateData;
1330

1331 1332 1333
    if (priv) {
        if (priv->watch != -1)
            virEventRemoveHandle(priv->watch);
1334

1335
        udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
1336

1337 1338 1339 1340
        if (udev_monitor != NULL) {
            udev = udev_monitor_get_udev(udev_monitor);
            udev_monitor_unref(udev_monitor);
        }
J
Ján Tomko 已提交
1341
    }
1342

J
Ján Tomko 已提交
1343 1344
    if (udev != NULL)
        udev_unref(udev);
1345

J
Ján Tomko 已提交
1346 1347 1348 1349 1350
    virNodeDeviceObjListFree(&driver->devs);
    nodeDeviceUnlock();
    virMutexDestroy(&driver->lock);
    VIR_FREE(driver);
    VIR_FREE(priv);
1351

J
Ján Tomko 已提交
1352 1353
    udevPCITranslateDeinit();
    return 0;
1354 1355 1356 1357 1358 1359 1360 1361 1362
}


static void udevEventHandleCallback(int watch ATTRIBUTE_UNUSED,
                                    int fd,
                                    int events ATTRIBUTE_UNUSED,
                                    void *data ATTRIBUTE_UNUSED)
{
    struct udev_device *device = NULL;
1363
    struct udev_monitor *udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
1364 1365 1366
    const char *action = NULL;
    int udev_fd = -1;

1367
    nodeDeviceLock();
1368 1369
    udev_fd = udev_monitor_get_fd(udev_monitor);
    if (fd != udev_fd) {
1370 1371 1372 1373
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("File descriptor returned by udev %d does not "
                         "match node device file descriptor %d"),
                       fd, udev_fd);
1374
        goto cleanup;
1375 1376 1377 1378
    }

    device = udev_monitor_receive_device(udev_monitor);
    if (device == NULL) {
1379 1380
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("udev_monitor_receive_device returned NULL"));
1381
        goto cleanup;
1382 1383 1384
    }

    action = udev_device_get_action(device);
1385
    VIR_DEBUG("udev action: '%s'", action);
1386 1387 1388

    if (STREQ(action, "add") || STREQ(action, "change")) {
        udevAddOneDevice(device);
1389
        goto cleanup;
1390 1391 1392 1393
    }

    if (STREQ(action, "remove")) {
        udevRemoveOneDevice(device);
1394
        goto cleanup;
1395 1396
    }

1397
 cleanup:
1398
    udev_device_unref(device);
1399
    nodeDeviceUnlock();
1400 1401 1402 1403
    return;
}


1404 1405
/* DMI is intel-compatible specific */
#if defined(__x86_64__) || defined(__i386__) || defined(__amd64__)
1406
static void
1407
udevGetDMIData(virNodeDevCapSystemPtr syscap)
1408 1409 1410
{
    struct udev *udev = NULL;
    struct udev_device *device = NULL;
1411 1412
    virNodeDevCapSystemHardwarePtr hardware = &syscap->hardware;
    virNodeDevCapSystemFirmwarePtr firmware = &syscap->firmware;
1413

1414
    udev = udev_monitor_get_udev(DRV_STATE_UDEV_MONITOR(driver));
1415

1416 1417
    device = udev_device_new_from_syspath(udev, DMI_DEVPATH);
    if (device == NULL) {
1418 1419
        device = udev_device_new_from_syspath(udev, DMI_DEVPATH_FALLBACK);
        if (device == NULL) {
1420 1421 1422
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to get udev device for syspath '%s' or '%s'"),
                           DMI_DEVPATH, DMI_DEVPATH_FALLBACK);
1423
            return;
1424
        }
1425 1426
    }

1427
    if (udevGetStringSysfsAttr(device, "product_name",
1428
                               &syscap->product_name) < 0)
1429
        goto cleanup;
1430
    if (udevGetStringSysfsAttr(device, "sys_vendor",
1431
                               &hardware->vendor_name) < 0)
1432
        goto cleanup;
1433
    if (udevGetStringSysfsAttr(device, "product_version",
1434
                               &hardware->version) < 0)
1435
        goto cleanup;
1436
    if (udevGetStringSysfsAttr(device, "product_serial",
1437
                               &hardware->serial) < 0)
1438
        goto cleanup;
1439

1440
    if (virGetHostUUID(hardware->uuid))
1441
        goto cleanup;
1442

1443
    if (udevGetStringSysfsAttr(device, "bios_vendor",
1444
                               &firmware->vendor_name) < 0)
1445
        goto cleanup;
1446
    if (udevGetStringSysfsAttr(device, "bios_version",
1447
                               &firmware->version) < 0)
1448
        goto cleanup;
1449
    if (udevGetStringSysfsAttr(device, "bios_date",
1450
                               &firmware->release_date) < 0)
1451
        goto cleanup;
1452

1453
 cleanup:
1454
    if (device != NULL)
1455 1456 1457
        udev_device_unref(device);
    return;
}
1458
#endif
1459 1460 1461 1462 1463 1464 1465 1466


static int udevSetupSystemDev(void)
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDeviceObjPtr dev = NULL;
    int ret = -1;

1467 1468
    if (VIR_ALLOC(def) < 0)
        return -1;
1469

1470
    if (VIR_STRDUP(def->name, "computer") < 0)
1471
        goto cleanup;
1472

1473
    if (VIR_ALLOC(def->caps) != 0)
1474
        goto cleanup;
1475

1476
#if defined(__x86_64__) || defined(__i386__) || defined(__amd64__)
1477
    udevGetDMIData(&def->caps->data.system);
1478
#endif
1479

1480
    dev = virNodeDeviceObjAssignDef(&driver->devs, def);
1481
    if (dev == NULL)
1482
        goto cleanup;
1483 1484 1485 1486 1487

    virNodeDeviceObjUnlock(dev);

    ret = 0;

1488
 cleanup:
1489
    if (ret == -1)
1490 1491
        virNodeDeviceDefFree(def);

1492 1493 1494
    return ret;
}

1495
static int udevPCITranslateInit(bool privileged ATTRIBUTE_UNUSED)
1496
{
1497 1498 1499 1500
#if defined __s390__ || defined __s390x_
    /* On s390(x) system there is no PCI bus.
     * Therefore there is nothing to initialize here. */
#else
1501
    int rc;
1502

1503
    if ((rc = pci_system_init()) != 0) {
1504 1505 1506
        /* 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.  */
1507
        if (errno != ENOENT && (privileged  || errno != EACCES)) {
1508 1509
            virReportSystemError(rc, "%s",
                                 _("Failed to initialize libpciaccess"));
1510
            return -1;
1511
        }
1512
    }
1513
#endif
1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524
    return 0;
}

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

1525
    if (VIR_ALLOC(priv) < 0)
1526
        return -1;
1527 1528

    priv->watch = -1;
1529
    priv->privileged = privileged;
1530

1531
    if (VIR_ALLOC(driver) < 0) {
1532
        VIR_FREE(priv);
1533
        return -1;
1534 1535
    }

1536
    if (virMutexInit(&driver->lock) < 0) {
1537 1538
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to initialize mutex"));
1539
        VIR_FREE(priv);
1540
        VIR_FREE(driver);
1541
        return -1;
1542 1543
    }

1544
    driver->privateData = priv;
1545
    nodeDeviceLock();
1546
    driver->nodeDeviceEventState = virObjectEventStateNew();
1547

1548
    if (udevPCITranslateInit(privileged) < 0)
1549
        goto cleanup;
1550

1551
    udev = udev_new();
1552 1553 1554 1555 1556
    if (!udev) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to create udev context"));
        goto cleanup;
    }
1557
#if HAVE_UDEV_LOGGING
J
Ján Tomko 已提交
1558 1559
    /* cast to get rid of missing-format-attribute warning */
    udev_set_log_fn(udev, (udevLogFunctionPtr) udevLogFunction);
1560
#endif
1561

1562 1563
    priv->udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
    if (priv->udev_monitor == NULL) {
1564 1565
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("udev_monitor_new_from_netlink returned NULL"));
1566
        goto cleanup;
1567 1568
    }

1569
    udev_monitor_enable_receiving(priv->udev_monitor);
1570 1571 1572 1573 1574 1575 1576 1577 1578

    /* 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.  */
1579 1580 1581
    priv->watch = virEventAddHandle(udev_monitor_get_fd(priv->udev_monitor),
                                    VIR_EVENT_HANDLE_READABLE,
                                    udevEventHandleCallback, NULL, NULL);
1582
    if (priv->watch == -1)
1583
        goto cleanup;
1584 1585

    /* Create a fictional 'computer' device to root the device tree. */
1586
    if (udevSetupSystemDev() != 0)
1587
        goto cleanup;
1588 1589 1590

    /* Populate with known devices */

1591
    if (udevEnumerateDevices(udev) != 0)
1592
        goto cleanup;
1593 1594

    ret = 0;
1595

1596
 cleanup:
1597
    nodeDeviceUnlock();
1598

1599
    if (ret == -1)
1600
        nodeStateCleanup();
1601 1602 1603 1604
    return ret;
}


1605
static int nodeStateReload(void)
1606 1607 1608 1609 1610
{
    return 0;
}


1611
static virNodeDeviceDriver udevNodeDeviceDriver = {
1612
    .name = "udev",
1613 1614
    .nodeNumOfDevices = nodeNumOfDevices, /* 0.7.3 */
    .nodeListDevices = nodeListDevices, /* 0.7.3 */
1615
    .connectListAllNodeDevices = nodeConnectListAllNodeDevices, /* 0.10.2 */
1616 1617
    .connectNodeDeviceEventRegisterAny = nodeConnectNodeDeviceEventRegisterAny, /* 2.2.0 */
    .connectNodeDeviceEventDeregisterAny = nodeConnectNodeDeviceEventDeregisterAny, /* 2.2.0 */
1618 1619 1620 1621 1622 1623 1624 1625
    .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 */
1626 1627 1628
};

static virStateDriver udevStateDriver = {
M
Matthias Bolte 已提交
1629
    .name = "udev",
1630 1631 1632
    .stateInitialize = nodeStateInitialize, /* 0.7.3 */
    .stateCleanup = nodeStateCleanup, /* 0.7.3 */
    .stateReload = nodeStateReload, /* 0.7.3 */
1633 1634 1635 1636
};

int udevNodeRegister(void)
{
1637
    VIR_DEBUG("Registering udev node device backend");
1638

1639
    if (virSetSharedNodeDeviceDriver(&udevNodeDeviceDriver) < 0)
1640 1641 1642 1643
        return -1;

    return virRegisterStateDriver(&udevStateDriver);
}