node_device_udev.c 47.5 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 47 48

#define VIR_FROM_THIS VIR_FROM_NODEDEV

49 50
VIR_LOG_INIT("node_device.node_device_udev");

51 52 53 54
#ifndef TYPE_RAID
# define TYPE_RAID 12
#endif

55 56 57
struct _udevPrivate {
    struct udev_monitor *udev_monitor;
    int watch;
58
    bool privileged;
59 60
};

61

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

    return false;
}


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

78
    ret = udev_device_get_property_value(udev_device, property_key);
79

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

    return ret;
}


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

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


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

106
    str = udevGetDeviceProperty(udev_device, property_key);
107

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


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

124
    str = udevGetDeviceProperty(udev_device, property_key);
125

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


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

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

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


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

157
    virStringStripControlChars(*value);
158

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

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


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

173
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
174

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

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


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

192
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
193

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

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


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

210
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
211

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

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


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

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

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

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

    def->name = virBufferContentAndReset(&buf);

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

246
    return 0;
247 248
}

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

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

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

    format = virBufferContentAndReset(&buf);

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

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


285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
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,
304
                    &vendor_name,
305 306 307
                    NULL,
                    NULL);

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

312
    return 0;
313 314 315
}


316 317 318
static int udevProcessPCI(struct udev_device *device,
                          virNodeDeviceDefPtr def)
{
319
    const char *syspath = NULL;
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
    syspath = udev_device_get_syspath(device);
328

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

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

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

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

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

356
    if (udevGenerateDeviceName(device, def, NULL) != 0)
357
        goto cleanup;
358

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

366 367
    if (nodeDeviceSysfsGetPCIRelatedDevCaps(syspath,
                                            &def->caps->data.pci_dev) < 0)
368
        goto cleanup;
369

370 371 372 373
    if (!(pciDev = virPCIDeviceNew(pci_dev->domain,
                                   pci_dev->bus,
                                   pci_dev->slot,
                                   pci_dev->function)))
374
        goto cleanup;
375

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

381 382
        if (virPCIDeviceIsPCIExpress(pciDev) > 0) {
            if (VIR_ALLOC(pci_express) < 0)
383
                goto cleanup;
384

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

                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)
396
                    goto cleanup;
397 398 399

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

406 407
    ret = 0;

408
 cleanup:
409
    virPCIDeviceFree(pciDev);
410
    virPCIEDeviceInfoFree(pci_express);
411 412 413
    return ret;
}

M
Marc-André Lureau 已提交
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
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)
{
434
    virNodeDevCapDRMPtr drm = &def->caps->data.drm;
M
Marc-André Lureau 已提交
435 436 437 438 439 440 441 442 443 444 445
    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;

446
    drm->type = minor;
M
Marc-André Lureau 已提交
447 448 449

    return 0;
}
450 451 452 453

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

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

463 464
    if (udevGetStringProperty(device,
                              "ID_VENDOR_FROM_DATABASE",
465
                              &usb_dev->vendor_name) < 0)
466
        return -1;
467

468
    if (!usb_dev->vendor_name &&
469
        udevGetStringSysfsAttr(device, "manufacturer",
470
                               &usb_dev->vendor_name) < 0)
471
        return -1;
472

473
    if (udevGetUintProperty(device, "ID_MODEL_ID", &usb_dev->product, 16) < 0)
474
        return -1;
475

476 477
    if (udevGetStringProperty(device,
                              "ID_MODEL_FROM_DATABASE",
478
                              &usb_dev->product_name) < 0)
479
        return -1;
480

481
    if (!usb_dev->product_name &&
482
        udevGetStringSysfsAttr(device, "product",
483
                               &usb_dev->product_name) < 0)
484
        return -1;
485

486
    if (udevGenerateDeviceName(device, def, NULL) != 0)
487
        return -1;
488

489
    return 0;
490 491 492 493 494 495
}


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

498
    if (udevGetUintSysfsAttr(device, "bInterfaceNumber",
499
                             &usb_if->number, 16) < 0)
500
        return -1;
501

502
    if (udevGetUintSysfsAttr(device, "bInterfaceClass",
503
                             &usb_if->_class, 16) < 0)
504
        return -1;
505

506
    if (udevGetUintSysfsAttr(device, "bInterfaceSubClass",
507
                             &usb_if->subclass, 16) < 0)
508
        return -1;
509

510
    if (udevGetUintSysfsAttr(device, "bInterfaceProtocol",
511
                             &usb_if->protocol, 16) < 0)
512
        return -1;
513

514
    if (udevGenerateDeviceName(device, def, NULL) != 0)
515
        return -1;
516

517
    return 0;
518 519 520 521 522 523
}


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

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

533 534
    if (udevGetStringProperty(device,
                              "INTERFACE",
535
                              &net->ifname) < 0)
536
        return -1;
537

538
    if (udevGetStringSysfsAttr(device, "address",
539
                               &net->address) < 0)
540
        return -1;
541

542
    if (udevGetUintSysfsAttr(device, "addr_len", &net->address_len, 0) < 0)
543
        return -1;
544

545
    if (udevGenerateDeviceName(device, def, net->address) != 0)
546
        return -1;
547

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

551
    if (virNetDevGetFeatures(net->ifname, &net->features) < 0)
552
        return -1;
553

554
    return 0;
555 556 557 558 559 560
}


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

565
    filename = last_component(def->sysfs_path);
566

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

575
    nodeDeviceSysfsGetSCSIHostCaps(&def->caps->data.scsi_host);
576

577
    if (udevGenerateDeviceName(device, def, NULL) != 0)
578
        return -1;
579

580
    return 0;
581 582 583
}


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

    sysname = udev_device_get_sysname(device);

592
    if (VIR_STRDUP(scsi_target->name, sysname) < 0)
593
        return -1;
D
David Allan 已提交
594

595
    if (udevGenerateDeviceName(device, def, NULL) != 0)
596
        return -1;
D
David Allan 已提交
597

598
    return 0;
D
David Allan 已提交
599 600 601
}


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

    *typestring = NULL;

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

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

    return ret;
}


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

668
    filename = last_component(def->sysfs_path);
669

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

680 681
    if (udev_device_get_sysattr_value(device, "type")) {
        if (udevGetUintSysfsAttr(device, "type", &tmp, 0) < 0)
682
            goto cleanup;
683

684
        if (udevGetSCSIType(def, tmp, &scsi->type) < 0)
685
            goto cleanup;
686 687
    }

688
    if (udevGenerateDeviceName(device, def, NULL) != 0)
689
        goto cleanup;
690 691 692

    ret = 0;

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


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

708
    if (udevGetUint64SysfsAttr(device, "size", &storage->num_blocks) < 0)
709
        return -1;
710

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

715
    storage->size = storage->num_blocks * storage->logical_block_size;
716

717
    return 0;
718 719 720
}


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

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

J
Ján Tomko 已提交
733 734
    if (!has_media)
        return 0;
735

J
Ján Tomko 已提交
736 737
    def->caps->data.storage.flags |=
        VIR_NODE_DEV_CAP_STORAGE_REMOVABLE_MEDIA_AVAILABLE;
738

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

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

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

J
Ján Tomko 已提交
751 752 753 754 755 756 757
    /* 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;
758

J
Ján Tomko 已提交
759
    return 0;
760 761
}

762 763 764 765 766 767 768 769 770 771
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);
772
    if (VIR_STRDUP(def->caps->data.storage.drive_type, "cdrom") < 0)
773
        return -1;
774

775 776
    if (udevHasDeviceProperty(device, "ID_CDROM_MEDIA") &&
        udevGetIntProperty(device, "ID_CDROM_MEDIA", &has_media, 0) < 0)
777
        return -1;
778

779
    return udevProcessRemoveableMedia(device, def, has_media);
780 781 782 783 784 785 786
}

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

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

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

799 800 801 802

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

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

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

813
    storage->size = storage->num_blocks * storage->logical_block_size;
814

815
    return 0;
816 817 818 819
}



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

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


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

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

858
    if (VIR_STRDUP(storage->block, devnode) < 0)
859
        goto cleanup;
860

861
    if (udevGetStringProperty(device, "ID_BUS", &storage->bus) < 0)
862
        goto cleanup;
863
    if (udevGetStringProperty(device, "ID_SERIAL", &storage->serial) < 0)
864
        goto cleanup;
865

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

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

880
    if (udevGetStringProperty(device, "ID_TYPE", &storage->drive_type) < 0)
881
        goto cleanup;
882

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

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

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

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

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

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

933
    if (udevGenerateDeviceName(device, def, storage->serial) != 0)
934
        goto cleanup;
935

936
 cleanup:
937
    VIR_DEBUG("Storage ret=%d", ret);
938 939 940
    return ret;
}

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

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

    return 0;
}

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 980 981 982
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;
}

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

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

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

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

        if (STREQ_NULLABLE(subsystem, "scsi_generic"))
1028 1029
            *type = VIR_NODE_DEV_CAP_SCSI_GENERIC;
        VIR_FREE(subsystem);
1030 1031
    }

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

    return ret;
}


static int udevGetDeviceDetails(struct udev_device *device,
                                virNodeDeviceDefPtr def)
{
    int ret = 0;

1048
    switch (def->caps->data.type) {
1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
    case VIR_NODE_DEV_CAP_SYSTEM:
        /* There's no libudev equivalent of system, so ignore it. */
        break;
    case VIR_NODE_DEV_CAP_PCI_DEV:
        ret = udevProcessPCI(device, def);
        break;
    case VIR_NODE_DEV_CAP_USB_DEV:
        ret = udevProcessUSBDevice(device, def);
        break;
    case VIR_NODE_DEV_CAP_USB_INTERFACE:
        ret = udevProcessUSBInterface(device, def);
        break;
    case VIR_NODE_DEV_CAP_NET:
        ret = udevProcessNetworkInterface(device, def);
        break;
    case VIR_NODE_DEV_CAP_SCSI_HOST:
        ret = udevProcessSCSIHost(device, def);
        break;
D
David Allan 已提交
1067 1068 1069
    case VIR_NODE_DEV_CAP_SCSI_TARGET:
        ret = udevProcessSCSITarget(device, def);
        break;
1070 1071 1072 1073 1074 1075
    case VIR_NODE_DEV_CAP_SCSI:
        ret = udevProcessSCSIDevice(device, def);
        break;
    case VIR_NODE_DEV_CAP_STORAGE:
        ret = udevProcessStorage(device, def);
        break;
1076
    case VIR_NODE_DEV_CAP_SCSI_GENERIC:
1077
        ret = udevProcessSCSIGeneric(device, def);
1078
        break;
M
Marc-André Lureau 已提交
1079 1080 1081
    case VIR_NODE_DEV_CAP_DRM:
        ret = udevProcessDRMDevice(device, def);
        break;
1082
    default:
1083 1084
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unknown device type %d"), def->caps->data.type);
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
        ret = -1;
        break;
    }

    return ret;
}


static int udevRemoveOneDevice(struct udev_device *device)
{
    virNodeDeviceObjPtr dev = NULL;
1096
    virObjectEventPtr event = NULL;
1097
    const char *name = NULL;
1098
    int ret = -1;
1099 1100

    name = udev_device_get_syspath(device);
1101
    dev = virNodeDeviceObjFindBySysfsPath(&driver->devs, name);
1102

1103
    if (!dev) {
1104 1105
        VIR_DEBUG("Failed to find device to remove that has udev name '%s'",
                  name);
1106
        goto cleanup;
1107 1108
    }

1109 1110 1111 1112 1113 1114
    event = virNodeDeviceEventLifecycleNew(dev->def->name,
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

    VIR_DEBUG("Removing device '%s' with sysfs path '%s'",
              dev->def->name, name);
1115
    virNodeDeviceObjRemove(&driver->devs, &dev);
1116 1117 1118 1119 1120

    ret = 0;
 cleanup:
    if (event)
        virObjectEventStateQueue(driver->nodeDeviceEventState, event);
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132
    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;

1133 1134
    parent_device = device;
    do {
1135

1136
        parent_device = udev_device_get_parent(parent_device);
1137
        if (parent_device == NULL)
1138
            break;
1139

1140 1141
        parent_sysfs_path = udev_device_get_syspath(parent_device);
        if (parent_sysfs_path == NULL) {
1142 1143 1144
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not get syspath for parent of '%s'"),
                           udev_device_get_syspath(parent_device));
1145
            goto cleanup;
1146 1147
        }

1148 1149
        dev = virNodeDeviceObjFindBySysfsPath(&driver->devs,
                                              parent_sysfs_path);
1150
        if (dev != NULL) {
1151 1152
            if (VIR_STRDUP(def->parent, dev->def->name) < 0) {
                virNodeDeviceObjUnlock(dev);
1153
                goto cleanup;
1154
            }
1155
            virNodeDeviceObjUnlock(dev);
1156

1157
            if (VIR_STRDUP(def->parent_sysfs_path, parent_sysfs_path) < 0)
1158
                goto cleanup;
1159 1160 1161 1162
        }

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

1163
    if (!def->parent && VIR_STRDUP(def->parent, "computer") < 0)
1164
        goto cleanup;
1165 1166 1167

    ret = 0;

1168
 cleanup:
1169 1170 1171 1172 1173 1174 1175 1176
    return ret;
}


static int udevAddOneDevice(struct udev_device *device)
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDeviceObjPtr dev = NULL;
1177 1178
    virObjectEventPtr event = NULL;
    bool new_device = true;
1179 1180
    int ret = -1;

1181
    if (VIR_ALLOC(def) != 0)
1182
        goto cleanup;
1183

1184
    if (VIR_STRDUP(def->sysfs_path, udev_device_get_syspath(device)) < 0)
1185
        goto cleanup;
1186

1187
    if (udevGetStringProperty(device, "DRIVER", &def->driver) < 0)
1188
        goto cleanup;
1189

1190
    if (VIR_ALLOC(def->caps) != 0)
1191
        goto cleanup;
1192

1193
    if (udevGetDeviceType(device, &def->caps->data.type) != 0)
1194
        goto cleanup;
1195

1196 1197 1198
    if (udevGetDeviceNodes(device, def) != 0)
        goto cleanup;

1199
    if (udevGetDeviceDetails(device, def) != 0)
1200
        goto cleanup;
1201

1202
    if (udevSetParent(device, def) != 0)
1203
        goto cleanup;
1204

1205
    dev = virNodeDeviceObjFindByName(&driver->devs, def->name);
1206 1207 1208 1209 1210
    if (dev) {
        virNodeDeviceObjUnlock(dev);
        new_device = false;
    }

1211 1212
    /* If this is a device change, the old definition will be freed
     * and the current definition will take its place. */
1213
    dev = virNodeDeviceObjAssignDef(&driver->devs, def);
1214
    if (dev == NULL)
1215
        goto cleanup;
1216

1217 1218 1219 1220
    if (new_device)
        event = virNodeDeviceEventLifecycleNew(dev->def->name,
                                               VIR_NODE_DEVICE_EVENT_CREATED,
                                               0);
1221 1222
    else
        event = virNodeDeviceEventUpdateNew(dev->def->name);
1223

1224 1225 1226 1227
    virNodeDeviceObjUnlock(dev);

    ret = 0;

1228
 cleanup:
1229 1230 1231
    if (event)
        virObjectEventStateQueue(driver->nodeDeviceEventState, event);

1232
    if (ret != 0) {
1233
        VIR_DEBUG("Discarding device %d %p %s", ret, def,
1234
                  def ? NULLSTR(def->sysfs_path) : "");
1235 1236 1237
        virNodeDeviceDefFree(def);
    }

1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
    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);
1252

1253 1254
    if (device != NULL) {
        if (udevAddOneDevice(device) != 0) {
1255 1256
            VIR_DEBUG("Failed to create node device for udev device '%s'",
                      name);
1257 1258 1259 1260
        }
        ret = 0;
    }

1261 1262
    udev_device_unref(device);

1263 1264 1265 1266
    return ret;
}


1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289
/* 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;
}


1290 1291 1292 1293
static int udevEnumerateDevices(struct udev *udev)
{
    struct udev_enumerate *udev_enumerate = NULL;
    struct udev_list_entry *list_entry = NULL;
1294
    int ret = -1;
1295 1296

    udev_enumerate = udev_enumerate_new(udev);
1297 1298
    if (udevEnumerateAddMatches(udev_enumerate) < 0)
        goto cleanup;
1299 1300

    ret = udev_enumerate_scan_devices(udev_enumerate);
1301
    if (ret != 0) {
1302 1303 1304
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("udev scan devices returned %d"),
                       ret);
1305
        goto cleanup;
1306 1307 1308 1309 1310 1311 1312 1313
    }

    udev_list_entry_foreach(list_entry,
                            udev_enumerate_get_list_entry(udev_enumerate)) {

        udevProcessDeviceListEntry(udev, list_entry);
    }

1314
 cleanup:
1315 1316 1317 1318 1319
    udev_enumerate_unref(udev_enumerate);
    return ret;
}


1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331
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;
}


1332
static int nodeStateCleanup(void)
1333
{
1334
    udevPrivate *priv = NULL;
1335 1336 1337
    struct udev_monitor *udev_monitor = NULL;
    struct udev *udev = NULL;

J
Ján Tomko 已提交
1338 1339
    if (!driver)
        return -1;
1340

J
Ján Tomko 已提交
1341
    nodeDeviceLock();
1342

1343
    virObjectUnref(driver->nodeDeviceEventState);
1344

J
Ján Tomko 已提交
1345
    priv = driver->privateData;
1346

1347 1348 1349
    if (priv) {
        if (priv->watch != -1)
            virEventRemoveHandle(priv->watch);
1350

1351
        udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
1352

1353 1354 1355 1356
        if (udev_monitor != NULL) {
            udev = udev_monitor_get_udev(udev_monitor);
            udev_monitor_unref(udev_monitor);
        }
J
Ján Tomko 已提交
1357
    }
1358

J
Ján Tomko 已提交
1359 1360
    if (udev != NULL)
        udev_unref(udev);
1361

J
Ján Tomko 已提交
1362 1363 1364 1365 1366
    virNodeDeviceObjListFree(&driver->devs);
    nodeDeviceUnlock();
    virMutexDestroy(&driver->lock);
    VIR_FREE(driver);
    VIR_FREE(priv);
1367

J
Ján Tomko 已提交
1368 1369
    udevPCITranslateDeinit();
    return 0;
1370 1371 1372 1373 1374 1375 1376 1377 1378
}


static void udevEventHandleCallback(int watch ATTRIBUTE_UNUSED,
                                    int fd,
                                    int events ATTRIBUTE_UNUSED,
                                    void *data ATTRIBUTE_UNUSED)
{
    struct udev_device *device = NULL;
1379
    struct udev_monitor *udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
1380 1381 1382
    const char *action = NULL;
    int udev_fd = -1;

1383
    nodeDeviceLock();
1384 1385
    udev_fd = udev_monitor_get_fd(udev_monitor);
    if (fd != udev_fd) {
1386 1387 1388 1389
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("File descriptor returned by udev %d does not "
                         "match node device file descriptor %d"),
                       fd, udev_fd);
1390
        goto cleanup;
1391 1392 1393 1394
    }

    device = udev_monitor_receive_device(udev_monitor);
    if (device == NULL) {
1395 1396
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("udev_monitor_receive_device returned NULL"));
1397
        goto cleanup;
1398 1399 1400
    }

    action = udev_device_get_action(device);
1401
    VIR_DEBUG("udev action: '%s'", action);
1402 1403 1404

    if (STREQ(action, "add") || STREQ(action, "change")) {
        udevAddOneDevice(device);
1405
        goto cleanup;
1406 1407 1408 1409
    }

    if (STREQ(action, "remove")) {
        udevRemoveOneDevice(device);
1410
        goto cleanup;
1411 1412
    }

1413
 cleanup:
1414
    udev_device_unref(device);
1415
    nodeDeviceUnlock();
1416 1417 1418 1419
    return;
}


1420 1421
/* DMI is intel-compatible specific */
#if defined(__x86_64__) || defined(__i386__) || defined(__amd64__)
1422
static void
1423
udevGetDMIData(virNodeDevCapSystemPtr system)
1424 1425 1426
{
    struct udev *udev = NULL;
    struct udev_device *device = NULL;
1427 1428
    virNodeDevCapSystemHardwarePtr hardware = &system->hardware;
    virNodeDevCapSystemFirmwarePtr firmware = &system->firmware;
1429

1430
    udev = udev_monitor_get_udev(DRV_STATE_UDEV_MONITOR(driver));
1431

1432 1433
    device = udev_device_new_from_syspath(udev, DMI_DEVPATH);
    if (device == NULL) {
1434 1435
        device = udev_device_new_from_syspath(udev, DMI_DEVPATH_FALLBACK);
        if (device == NULL) {
1436 1437 1438
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to get udev device for syspath '%s' or '%s'"),
                           DMI_DEVPATH, DMI_DEVPATH_FALLBACK);
1439
            return;
1440
        }
1441 1442
    }

1443
    if (udevGetStringSysfsAttr(device, "product_name",
1444
                               &system->product_name) < 0)
1445
        goto cleanup;
1446
    if (udevGetStringSysfsAttr(device, "sys_vendor",
1447
                               &hardware->vendor_name) < 0)
1448
        goto cleanup;
1449
    if (udevGetStringSysfsAttr(device, "product_version",
1450
                               &hardware->version) < 0)
1451
        goto cleanup;
1452
    if (udevGetStringSysfsAttr(device, "product_serial",
1453
                               &hardware->serial) < 0)
1454
        goto cleanup;
1455

1456
    if (virGetHostUUID(hardware->uuid))
1457
        goto cleanup;
1458

1459
    if (udevGetStringSysfsAttr(device, "bios_vendor",
1460
                               &firmware->vendor_name) < 0)
1461
        goto cleanup;
1462
    if (udevGetStringSysfsAttr(device, "bios_version",
1463
                               &firmware->version) < 0)
1464
        goto cleanup;
1465
    if (udevGetStringSysfsAttr(device, "bios_date",
1466
                               &firmware->release_date) < 0)
1467
        goto cleanup;
1468

1469
 cleanup:
1470
    if (device != NULL)
1471 1472 1473
        udev_device_unref(device);
    return;
}
1474
#endif
1475 1476 1477 1478 1479 1480 1481 1482


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

1483 1484
    if (VIR_ALLOC(def) < 0)
        return -1;
1485

1486
    if (VIR_STRDUP(def->name, "computer") < 0)
1487
        goto cleanup;
1488

1489
    if (VIR_ALLOC(def->caps) != 0)
1490
        goto cleanup;
1491

1492
#if defined(__x86_64__) || defined(__i386__) || defined(__amd64__)
1493
    udevGetDMIData(&def->caps->data.system);
1494
#endif
1495

1496
    dev = virNodeDeviceObjAssignDef(&driver->devs, def);
1497
    if (dev == NULL)
1498
        goto cleanup;
1499 1500 1501 1502 1503

    virNodeDeviceObjUnlock(dev);

    ret = 0;

1504
 cleanup:
1505
    if (ret == -1)
1506 1507
        virNodeDeviceDefFree(def);

1508 1509 1510
    return ret;
}

1511
static int udevPCITranslateInit(bool privileged ATTRIBUTE_UNUSED)
1512
{
1513 1514 1515 1516
#if defined __s390__ || defined __s390x_
    /* On s390(x) system there is no PCI bus.
     * Therefore there is nothing to initialize here. */
#else
1517
    int rc;
1518

1519
    if ((rc = pci_system_init()) != 0) {
1520 1521 1522
        /* 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.  */
1523
        if (errno != ENOENT && (privileged  || errno != EACCES)) {
1524 1525
            virReportSystemError(rc, "%s",
                                 _("Failed to initialize libpciaccess"));
1526
            return -1;
1527
        }
1528
    }
1529
#endif
1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540
    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;

1541
    if (VIR_ALLOC(priv) < 0)
1542
        return -1;
1543 1544

    priv->watch = -1;
1545
    priv->privileged = privileged;
1546

1547
    if (VIR_ALLOC(driver) < 0) {
1548
        VIR_FREE(priv);
1549
        return -1;
1550 1551
    }

1552
    if (virMutexInit(&driver->lock) < 0) {
1553 1554
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to initialize mutex"));
1555
        VIR_FREE(priv);
1556
        VIR_FREE(driver);
1557
        return -1;
1558 1559
    }

1560
    driver->privateData = priv;
1561
    nodeDeviceLock();
1562
    driver->nodeDeviceEventState = virObjectEventStateNew();
1563

1564
    if (udevPCITranslateInit(privileged) < 0)
1565
        goto cleanup;
1566

1567
    udev = udev_new();
1568 1569 1570 1571 1572
    if (!udev) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to create udev context"));
        goto cleanup;
    }
1573
#if HAVE_UDEV_LOGGING
J
Ján Tomko 已提交
1574 1575
    /* cast to get rid of missing-format-attribute warning */
    udev_set_log_fn(udev, (udevLogFunctionPtr) udevLogFunction);
1576
#endif
1577

1578 1579
    priv->udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
    if (priv->udev_monitor == NULL) {
1580 1581
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("udev_monitor_new_from_netlink returned NULL"));
1582
        goto cleanup;
1583 1584
    }

1585
    udev_monitor_enable_receiving(priv->udev_monitor);
1586 1587 1588 1589 1590 1591 1592 1593 1594

    /* 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.  */
1595 1596 1597
    priv->watch = virEventAddHandle(udev_monitor_get_fd(priv->udev_monitor),
                                    VIR_EVENT_HANDLE_READABLE,
                                    udevEventHandleCallback, NULL, NULL);
1598
    if (priv->watch == -1)
1599
        goto cleanup;
1600 1601

    /* Create a fictional 'computer' device to root the device tree. */
1602
    if (udevSetupSystemDev() != 0)
1603
        goto cleanup;
1604 1605 1606

    /* Populate with known devices */

1607
    if (udevEnumerateDevices(udev) != 0)
1608
        goto cleanup;
1609 1610

    ret = 0;
1611

1612
 cleanup:
1613
    nodeDeviceUnlock();
1614

1615
    if (ret == -1)
1616
        nodeStateCleanup();
1617 1618 1619 1620
    return ret;
}


1621
static int nodeStateReload(void)
1622 1623 1624 1625 1626
{
    return 0;
}


1627
static virNodeDeviceDriver udevNodeDeviceDriver = {
1628
    .name = "udev",
1629 1630
    .nodeNumOfDevices = nodeNumOfDevices, /* 0.7.3 */
    .nodeListDevices = nodeListDevices, /* 0.7.3 */
1631
    .connectListAllNodeDevices = nodeConnectListAllNodeDevices, /* 0.10.2 */
1632 1633
    .connectNodeDeviceEventRegisterAny = nodeConnectNodeDeviceEventRegisterAny, /* 2.2.0 */
    .connectNodeDeviceEventDeregisterAny = nodeConnectNodeDeviceEventDeregisterAny, /* 2.2.0 */
1634 1635 1636 1637 1638 1639 1640 1641
    .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 */
1642 1643 1644
};

static virStateDriver udevStateDriver = {
M
Matthias Bolte 已提交
1645
    .name = "udev",
1646 1647 1648
    .stateInitialize = nodeStateInitialize, /* 0.7.3 */
    .stateCleanup = nodeStateCleanup, /* 0.7.3 */
    .stateReload = nodeStateReload, /* 0.7.3 */
1649 1650 1651 1652
};

int udevNodeRegister(void)
{
1653
    VIR_DEBUG("Registering udev node device backend");
1654

1655
    if (virSetSharedNodeDeviceDriver(&udevNodeDeviceDriver) < 0)
1656 1657 1658 1659
        return -1;

    return virRegisterStateDriver(&udevStateDriver);
}