node_device_udev.c 47.2 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

    return ret;
}


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

1074
    return 0;
1075 1076 1077 1078 1079 1080
}


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

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

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

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

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

    ret = 0;
 cleanup:
    if (event)
        virObjectEventStateQueue(driver->nodeDeviceEventState, event);
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
    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;

1118 1119
    parent_device = device;
    do {
1120

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

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

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

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

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

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

    ret = 0;

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


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

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

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

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

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

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

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

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

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

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

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

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

1209 1210 1211 1212
    virNodeDeviceObjUnlock(dev);

    ret = 0;

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

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

1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236
    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);
1237

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

1246 1247
    udev_device_unref(device);

1248 1249 1250 1251
    return ret;
}


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


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

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

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

    udev_list_entry_foreach(list_entry,
                            udev_enumerate_get_list_entry(udev_enumerate)) {

        udevProcessDeviceListEntry(udev, list_entry);
    }

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


1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316
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;
}


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

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

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

1328
    virObjectUnref(driver->nodeDeviceEventState);
1329

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

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

1336
        udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
1337

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

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

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

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


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

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

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

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

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

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

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


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

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

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

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

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

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

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


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

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

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

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

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

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

    virNodeDeviceObjUnlock(dev);

    ret = 0;

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

1493 1494 1495
    return ret;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

    /* Populate with known devices */

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

    ret = 0;
1596

1597
 cleanup:
1598
    nodeDeviceUnlock();
1599

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


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


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

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

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

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

    return virRegisterStateDriver(&udevStateDriver);
}