node_device_udev.c 45.9 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
    virNodeDevCapDataPtr data = &def->caps->data;
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", &data->pci_dev.class, 16) < 0)
330
        goto cleanup;
331

332 333 334 335 336 337 338 339
    if ((p = strrchr(syspath, '/')) == NULL ||
        virStrToLong_ui(p + 1, &p, 16, &data->pci_dev.domain) < 0 || p == NULL ||
        virStrToLong_ui(p + 1, &p, 16, &data->pci_dev.bus) < 0 || p == NULL ||
        virStrToLong_ui(p + 1, &p, 16, &data->pci_dev.slot) < 0 || p == NULL ||
        virStrToLong_ui(p + 1, &p, 16, &data->pci_dev.function) < 0) {
        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", &data->pci_dev.vendor, 16) < 0)
344
        goto cleanup;
345

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

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

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

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

366
    if (nodeDeviceSysfsGetPCIRelatedDevCaps(syspath, data) < 0)
367
        goto cleanup;
368

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

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

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

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

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

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

405 406
    ret = 0;

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


static int udevProcessUSBDevice(struct udev_device *device,
                                virNodeDeviceDefPtr def)
{
417
    virNodeDevCapDataPtr data = &def->caps->data;
418

419
    if (udevGetUintProperty(device, "BUSNUM", &data->usb_dev.bus, 10) < 0)
420
        return -1;
421
    if (udevGetUintProperty(device, "DEVNUM", &data->usb_dev.device, 10) < 0)
422
        return -1;
423
    if (udevGetUintProperty(device, "ID_VENDOR_ID", &data->usb_dev.vendor, 16) < 0)
424
        return -1;
425

426 427 428
    if (udevGetStringProperty(device,
                              "ID_VENDOR_FROM_DATABASE",
                              &data->usb_dev.vendor_name) < 0)
429
        return -1;
430 431

    if (!data->usb_dev.vendor_name &&
432 433
        udevGetStringSysfsAttr(device, "manufacturer",
                               &data->usb_dev.vendor_name) < 0)
434
        return -1;
435

436
    if (udevGetUintProperty(device, "ID_MODEL_ID", &data->usb_dev.product, 16) < 0)
437
        return -1;
438

439 440 441
    if (udevGetStringProperty(device,
                              "ID_MODEL_FROM_DATABASE",
                              &data->usb_dev.product_name) < 0)
442
        return -1;
443 444

    if (!data->usb_dev.product_name &&
445 446
        udevGetStringSysfsAttr(device, "product",
                               &data->usb_dev.product_name) < 0)
447
        return -1;
448

449
    if (udevGenerateDeviceName(device, def, NULL) != 0)
450
        return -1;
451

452
    return 0;
453 454 455 456 457 458
}


static int udevProcessUSBInterface(struct udev_device *device,
                                   virNodeDeviceDefPtr def)
{
459
    virNodeDevCapDataPtr data = &def->caps->data;
460

461 462
    if (udevGetUintSysfsAttr(device, "bInterfaceNumber",
                             &data->usb_if.number, 16) < 0)
463
        return -1;
464

465 466
    if (udevGetUintSysfsAttr(device, "bInterfaceClass",
                             &data->usb_if._class, 16) < 0)
467
        return -1;
468

469 470
    if (udevGetUintSysfsAttr(device, "bInterfaceSubClass",
                             &data->usb_if.subclass, 16) < 0)
471
        return -1;
472

473 474
    if (udevGetUintSysfsAttr(device, "bInterfaceProtocol",
                             &data->usb_if.protocol, 16) < 0)
475
        return -1;
476

477
    if (udevGenerateDeviceName(device, def, NULL) != 0)
478
        return -1;
479

480
    return 0;
481 482 483 484 485 486
}


static int udevProcessNetworkInterface(struct udev_device *device,
                                       virNodeDeviceDefPtr def)
{
D
David Allan 已提交
487
    const char *devtype = udev_device_get_devtype(device);
488
    virNodeDevCapDataPtr data = &def->caps->data;
489

D
David Allan 已提交
490 491 492 493 494 495
    if (devtype && STREQ(devtype, "wlan")) {
        data->net.subtype = VIR_NODE_DEV_CAP_NET_80211;
    } else {
        data->net.subtype = VIR_NODE_DEV_CAP_NET_80203;
    }

496 497
    if (udevGetStringProperty(device,
                              "INTERFACE",
498
                              &data->net.ifname) < 0)
499
        return -1;
500

501 502
    if (udevGetStringSysfsAttr(device, "address",
                               &data->net.address) < 0)
503
        return -1;
504

505
    if (udevGetUintSysfsAttr(device, "addr_len", &data->net.address_len, 0) < 0)
506
        return -1;
507

508
    if (udevGenerateDeviceName(device, def, data->net.address) != 0)
509
        return -1;
510

511
    if (virNetDevGetLinkInfo(data->net.ifname, &data->net.lnk) < 0)
512
        return -1;
513

514
    if (virNetDevGetFeatures(data->net.ifname, &data->net.features) < 0)
515
        return -1;
516

517
    return 0;
518 519 520 521 522 523
}


static int udevProcessSCSIHost(struct udev_device *device ATTRIBUTE_UNUSED,
                               virNodeDeviceDefPtr def)
{
524
    virNodeDevCapDataPtr data = &def->caps->data;
525
    char *filename = NULL;
J
Ján Tomko 已提交
526
    char *str;
527

528
    filename = last_component(def->sysfs_path);
529

530 531 532 533 534
    if (!(str = STRSKIP(filename, "host")) ||
        virStrToLong_ui(str, NULL, 0, &data->scsi_host.host) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to parse SCSI host '%s'"),
                       filename);
535
        return -1;
536 537
    }

538
    nodeDeviceSysfsGetSCSIHostCaps(&def->caps->data);
539

540
    if (udevGenerateDeviceName(device, def, NULL) != 0)
541
        return -1;
542

543
    return 0;
544 545 546
}


D
David Allan 已提交
547 548 549 550
static int udevProcessSCSITarget(struct udev_device *device ATTRIBUTE_UNUSED,
                                 virNodeDeviceDefPtr def)
{
    const char *sysname = NULL;
551
    virNodeDevCapDataPtr data = &def->caps->data;
D
David Allan 已提交
552 553 554

    sysname = udev_device_get_sysname(device);

555
    if (VIR_STRDUP(data->scsi_target.name, sysname) < 0)
556
        return -1;
D
David Allan 已提交
557

558
    if (udevGenerateDeviceName(device, def, NULL) != 0)
559
        return -1;
D
David Allan 已提交
560

561
    return 0;
D
David Allan 已提交
562 563 564
}


565
static int udevGetSCSIType(virNodeDeviceDefPtr def ATTRIBUTE_UNUSED,
566
                           unsigned int type, char **typestring)
567 568 569 570 571 572 573 574
{
    int ret = 0;
    int foundtype = 1;

    *typestring = NULL;

    switch (type) {
    case TYPE_DISK:
575
        ignore_value(VIR_STRDUP(*typestring, "disk"));
576 577
        break;
    case TYPE_TAPE:
578
        ignore_value(VIR_STRDUP(*typestring, "tape"));
579 580
        break;
    case TYPE_PROCESSOR:
581
        ignore_value(VIR_STRDUP(*typestring, "processor"));
582 583
        break;
    case TYPE_WORM:
584
        ignore_value(VIR_STRDUP(*typestring, "worm"));
585 586
        break;
    case TYPE_ROM:
587
        ignore_value(VIR_STRDUP(*typestring, "cdrom"));
588 589
        break;
    case TYPE_SCANNER:
590
        ignore_value(VIR_STRDUP(*typestring, "scanner"));
591 592
        break;
    case TYPE_MOD:
593
        ignore_value(VIR_STRDUP(*typestring, "mod"));
594 595
        break;
    case TYPE_MEDIUM_CHANGER:
596
        ignore_value(VIR_STRDUP(*typestring, "changer"));
597 598
        break;
    case TYPE_ENCLOSURE:
599
        ignore_value(VIR_STRDUP(*typestring, "enclosure"));
600
        break;
601
    case TYPE_RAID:
602
        ignore_value(VIR_STRDUP(*typestring, "raid"));
603
        break;
604 605 606 607 608 609 610 611 612 613
    case TYPE_NO_LUN:
    default:
        foundtype = 0;
        break;
    }

    if (*typestring == NULL) {
        if (foundtype == 1) {
            ret = -1;
        } else {
614 615
            VIR_DEBUG("Failed to find SCSI device type %d for %s",
                      type, def->sysfs_path);
616 617 618 619 620 621 622 623 624 625 626 627
        }
    }

    return ret;
}


static int udevProcessSCSIDevice(struct udev_device *device ATTRIBUTE_UNUSED,
                                 virNodeDeviceDefPtr def)
{
    int ret = -1;
    unsigned int tmp = 0;
628
    virNodeDevCapDataPtr data = &def->caps->data;
629 630
    char *filename = NULL, *p = NULL;

631
    filename = last_component(def->sysfs_path);
632

633 634 635 636 637 638 639 640
    if (virStrToLong_ui(filename, &p, 10, &data->scsi.host) < 0 || p == NULL ||
        virStrToLong_ui(p + 1, &p, 10, &data->scsi.bus) < 0 || p == NULL ||
        virStrToLong_ui(p + 1, &p, 10, &data->scsi.target) < 0 || p == NULL ||
        virStrToLong_ui(p + 1, &p, 10, &data->scsi.lun) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to parse the SCSI address from filename: '%s'"),
                       filename);
        return -1;
641 642
    }

643 644
    if (udev_device_get_sysattr_value(device, "type")) {
        if (udevGetUintSysfsAttr(device, "type", &tmp, 0) < 0)
645
            goto cleanup;
646 647

        if (udevGetSCSIType(def, tmp, &data->scsi.type) < 0)
648
            goto cleanup;
649 650
    }

651
    if (udevGenerateDeviceName(device, def, NULL) != 0)
652
        goto cleanup;
653 654 655

    ret = 0;

656
 cleanup:
657
    if (ret != 0) {
658 659 660
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to process SCSI device with sysfs path '%s'"),
                       def->sysfs_path);
661 662 663 664 665 666 667 668
    }
    return ret;
}


static int udevProcessDisk(struct udev_device *device,
                           virNodeDeviceDefPtr def)
{
669
    virNodeDevCapDataPtr data = &def->caps->data;
670

J
Ján Tomko 已提交
671
    if (udevGetUint64SysfsAttr(device, "size", &data->storage.num_blocks) < 0)
672
        return -1;
673

J
Ján Tomko 已提交
674 675
    if (udevGetUint64SysfsAttr(device, "queue/logical_block_size",
                               &data->storage.logical_block_size) < 0)
676
        return -1;
677 678 679 680

    data->storage.size = data->storage.num_blocks *
        data->storage.logical_block_size;

681
    return 0;
682 683 684
}


685 686 687
static int udevProcessRemoveableMedia(struct udev_device *device,
                                      virNodeDeviceDefPtr def,
                                      int has_media)
688
{
689
    virNodeDevCapDataPtr data = &def->caps->data;
J
Ján Tomko 已提交
690
    int is_removable = 0;
691

692 693 694
    if (udevGetIntSysfsAttr(device, "removable", &is_removable, 0) < 0)
        return -1;
    if (is_removable == 1)
695 696
        def->caps->data.storage.flags |= VIR_NODE_DEV_CAP_STORAGE_REMOVABLE;

J
Ján Tomko 已提交
697 698
    if (!has_media)
        return 0;
699

J
Ján Tomko 已提交
700 701
    def->caps->data.storage.flags |=
        VIR_NODE_DEV_CAP_STORAGE_REMOVABLE_MEDIA_AVAILABLE;
702

J
Ján Tomko 已提交
703 704 705
    if (udevGetStringProperty(device, "ID_FS_LABEL",
                              &data->storage.media_label) < 0)
        return -1;
706

J
Ján Tomko 已提交
707 708 709
    if (udevGetUint64SysfsAttr(device, "size",
                               &data->storage.num_blocks) < 0)
        return -1;
710

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

J
Ján Tomko 已提交
715 716 717 718 719 720 721
    /* 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;
722

J
Ján Tomko 已提交
723
    return 0;
724 725
}

726 727 728 729 730 731 732 733 734 735
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);
736
    if (VIR_STRDUP(def->caps->data.storage.drive_type, "cdrom") < 0)
737
        return -1;
738

739 740
    if (udevHasDeviceProperty(device, "ID_CDROM_MEDIA") &&
        udevGetIntProperty(device, "ID_CDROM_MEDIA", &has_media, 0) < 0)
741
        return -1;
742

743
    return udevProcessRemoveableMedia(device, def, has_media);
744 745 746 747 748 749 750
}

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

751
    if (udevHasDeviceProperty(device, "ID_CDROM_MEDIA")) {
752
        /* USB floppy */
753 754
        if (udevGetIntProperty(device, "DKD_MEDIA_AVAILABLE", &has_media, 0) < 0)
            return -1;
755
    } else if (udevHasDeviceProperty(device, "ID_FS_LABEL")) {
756 757 758 759 760 761
        /* Legacy floppy */
        has_media = 1;
    }

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

763 764 765 766

static int udevProcessSD(struct udev_device *device,
                         virNodeDeviceDefPtr def)
{
767
    virNodeDevCapDataPtr data = &def->caps->data;
768

J
Ján Tomko 已提交
769 770
    if (udevGetUint64SysfsAttr(device, "size",
                               &data->storage.num_blocks) < 0)
771
        return -1;
772

J
Ján Tomko 已提交
773 774
    if (udevGetUint64SysfsAttr(device, "queue/logical_block_size",
                               &data->storage.logical_block_size) < 0)
775
        return -1;
776 777 778 779

    data->storage.size = data->storage.num_blocks *
        data->storage.logical_block_size;

780
    return 0;
781 782 783 784
}



785 786 787 788 789 790
/* 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)
{
791 792 793
    VIR_DEBUG("Could not find definitive storage type for device "
              "with sysfs path '%s', trying to guess it",
              def->sysfs_path);
794

795 796 797
    /* virtio disk */
    if (STRPREFIX(def->caps->data.storage.block, "/dev/vd") &&
        VIR_STRDUP(def->caps->data.storage.drive_type, "disk") > 0) {
798
        VIR_DEBUG("Found storage type '%s' for device "
799
                  "with sysfs path '%s'",
800 801
                  def->caps->data.storage.drive_type,
                  def->sysfs_path);
802
        return 0;
803
    }
804 805 806
    VIR_DEBUG("Could not determine storage type "
              "for device with sysfs path '%s'", def->sysfs_path);
    return -1;
807 808 809 810 811 812
}


static int udevProcessStorage(struct udev_device *device,
                              virNodeDeviceDefPtr def)
{
813
    virNodeDevCapDataPtr data = &def->caps->data;
814
    int ret = -1;
815
    const char* devnode;
816

817
    devnode = udev_device_get_devnode(device);
818
    if (!devnode) {
819
        VIR_DEBUG("No devnode for '%s'", udev_device_get_devpath(device));
820
        goto cleanup;
821
    }
822 823

    if (VIR_STRDUP(data->storage.block, devnode) < 0)
824
        goto cleanup;
825

826
    if (udevGetStringProperty(device, "ID_BUS", &data->storage.bus) < 0)
827
        goto cleanup;
828
    if (udevGetStringProperty(device, "ID_SERIAL", &data->storage.serial) < 0)
829
        goto cleanup;
830

831
    if (udevGetStringSysfsAttr(device, "device/vendor", &data->storage.vendor) < 0)
832
        goto cleanup;
833 834 835
    if (def->caps->data.storage.vendor)
        virTrimSpaces(def->caps->data.storage.vendor, NULL);

836
    if (udevGetStringSysfsAttr(device, "device/model", &data->storage.model) < 0)
837
        goto cleanup;
838 839
    if (def->caps->data.storage.model)
        virTrimSpaces(def->caps->data.storage.model, NULL);
840 841 842 843 844
    /* 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. */

845
    if (udevGetStringProperty(device, "ID_TYPE", &data->storage.drive_type) < 0)
846
        goto cleanup;
847 848

    if (!data->storage.drive_type ||
849
        STREQ(def->caps->data.storage.drive_type, "generic")) {
850 851
        int val = 0;
        const char *str = NULL;
852 853 854

        /* All floppy drives have the ID_DRIVE_FLOPPY prop. This is
         * needed since legacy floppies don't have a drive_type */
855
        if (udevGetIntProperty(device, "ID_DRIVE_FLOPPY", &val, 0) < 0)
856
            goto cleanup;
857 858
        else if (val == 1)
            str = "floppy";
859

860
        if (!str) {
861
            if (udevGetIntProperty(device, "ID_CDROM", &val, 0) < 0)
862
                goto cleanup;
863 864 865
            else if (val == 1)
                str = "cd";
        }
866

867
        if (!str) {
868
            if (udevGetIntProperty(device, "ID_DRIVE_FLASH_SD", &val, 0) < 0)
869
                goto cleanup;
870 871 872
            if (val == 1)
                str = "sd";
        }
873

874 875
        if (str) {
            if (VIR_STRDUP(data->storage.drive_type, str) < 0)
876
                goto cleanup;
877 878
        } else {
            /* If udev doesn't have it, perhaps we can guess it. */
879
            if (udevKludgeStorageType(def) != 0)
880
                goto cleanup;
881 882 883 884 885 886 887
        }
    }

    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);
888 889
    } else if (STREQ(def->caps->data.storage.drive_type, "floppy")) {
        ret = udevProcessFloppy(device, def);
890 891
    } else if (STREQ(def->caps->data.storage.drive_type, "sd")) {
        ret = udevProcessSD(device, def);
892
    } else {
893 894
        VIR_DEBUG("Unsupported storage type '%s'",
                  def->caps->data.storage.drive_type);
895
        goto cleanup;
896 897
    }

898
    if (udevGenerateDeviceName(device, def, data->storage.serial) != 0)
899
        goto cleanup;
900

901
 cleanup:
902
    VIR_DEBUG("Storage ret=%d", ret);
903 904 905
    return ret;
}

906
static int
907
udevProcessSCSIGeneric(struct udev_device *dev,
908 909
                       virNodeDeviceDefPtr def)
{
910 911
    if (udevGetStringProperty(dev, "DEVNAME", &def->caps->data.sg.path) < 0 ||
        !def->caps->data.sg.path)
912 913 914 915 916 917 918 919
        return -1;

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

    return 0;
}

920 921
static int
udevGetDeviceType(struct udev_device *device,
922
                  virNodeDevCapType *type)
923 924
{
    const char *devtype = NULL;
925
    char *subsystem = NULL;
926
    int ret = -1;
D
David Allan 已提交
927

928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947
    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;
    } else {
        /* PCI devices don't set the DEVTYPE property. */
948
        if (udevHasDeviceProperty(device, "PCI_CLASS"))
949
            *type = VIR_NODE_DEV_CAP_PCI_DEV;
950

951 952 953 954
        /* 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. */
955
        if (udevHasDeviceProperty(device, "INTERFACE"))
956
            *type = VIR_NODE_DEV_CAP_NET;
957 958

        /* SCSI generic device doesn't set DEVTYPE property */
959 960 961 962
        if (udevGetStringProperty(device, "SUBSYSTEM", &subsystem) < 0)
            return -1;

        if (STREQ_NULLABLE(subsystem, "scsi_generic"))
963 964
            *type = VIR_NODE_DEV_CAP_SCSI_GENERIC;
        VIR_FREE(subsystem);
965 966
    }

967 968 969 970 971 972
    if (!*type)
        VIR_DEBUG("Could not determine device type for device "
                  "with sysfs name '%s'",
                  udev_device_get_sysname(device));
    else
        ret = 0;
973 974 975 976 977 978 979 980 981 982

    return ret;
}


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

983
    switch (def->caps->data.type) {
984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001
    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 已提交
1002 1003 1004
    case VIR_NODE_DEV_CAP_SCSI_TARGET:
        ret = udevProcessSCSITarget(device, def);
        break;
1005 1006 1007 1008 1009 1010
    case VIR_NODE_DEV_CAP_SCSI:
        ret = udevProcessSCSIDevice(device, def);
        break;
    case VIR_NODE_DEV_CAP_STORAGE:
        ret = udevProcessStorage(device, def);
        break;
1011
    case VIR_NODE_DEV_CAP_SCSI_GENERIC:
1012
        ret = udevProcessSCSIGeneric(device, def);
1013
        break;
1014
    default:
1015 1016
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unknown device type %d"), def->caps->data.type);
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
        ret = -1;
        break;
    }

    return ret;
}


static int udevRemoveOneDevice(struct udev_device *device)
{
    virNodeDeviceObjPtr dev = NULL;
1028
    virObjectEventPtr event = NULL;
1029
    const char *name = NULL;
1030
    int ret = -1;
1031 1032

    name = udev_device_get_syspath(device);
1033
    dev = virNodeDeviceFindBySysfsPath(&driver->devs, name);
1034

1035
    if (!dev) {
1036 1037
        VIR_DEBUG("Failed to find device to remove that has udev name '%s'",
                  name);
1038
        goto cleanup;
1039 1040
    }

1041 1042 1043 1044 1045 1046
    event = virNodeDeviceEventLifecycleNew(dev->def->name,
                                           VIR_NODE_DEVICE_EVENT_DELETED,
                                           0);

    VIR_DEBUG("Removing device '%s' with sysfs path '%s'",
              dev->def->name, name);
1047
    virNodeDeviceObjRemove(&driver->devs, &dev);
1048 1049 1050 1051 1052

    ret = 0;
 cleanup:
    if (event)
        virObjectEventStateQueue(driver->nodeDeviceEventState, event);
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
    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;

1065 1066
    parent_device = device;
    do {
1067

1068
        parent_device = udev_device_get_parent(parent_device);
1069
        if (parent_device == NULL)
1070
            break;
1071

1072 1073
        parent_sysfs_path = udev_device_get_syspath(parent_device);
        if (parent_sysfs_path == NULL) {
1074 1075 1076
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not get syspath for parent of '%s'"),
                           udev_device_get_syspath(parent_device));
1077
            goto cleanup;
1078 1079
        }

1080
        dev = virNodeDeviceFindBySysfsPath(&driver->devs,
1081 1082
                                           parent_sysfs_path);
        if (dev != NULL) {
1083 1084
            if (VIR_STRDUP(def->parent, dev->def->name) < 0) {
                virNodeDeviceObjUnlock(dev);
1085
                goto cleanup;
1086
            }
1087
            virNodeDeviceObjUnlock(dev);
1088

1089
            if (VIR_STRDUP(def->parent_sysfs_path, parent_sysfs_path) < 0)
1090
                goto cleanup;
1091 1092 1093 1094
        }

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

1095
    if (!def->parent && VIR_STRDUP(def->parent, "computer") < 0)
1096
        goto cleanup;
1097 1098 1099

    ret = 0;

1100
 cleanup:
1101 1102 1103 1104 1105 1106 1107 1108
    return ret;
}


static int udevAddOneDevice(struct udev_device *device)
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDeviceObjPtr dev = NULL;
1109 1110
    virObjectEventPtr event = NULL;
    bool new_device = true;
1111 1112
    int ret = -1;

1113
    if (VIR_ALLOC(def) != 0)
1114
        goto cleanup;
1115

1116
    if (VIR_STRDUP(def->sysfs_path, udev_device_get_syspath(device)) < 0)
1117
        goto cleanup;
1118

1119
    if (udevGetStringProperty(device, "DRIVER", &def->driver) < 0)
1120
        goto cleanup;
1121

1122
    if (VIR_ALLOC(def->caps) != 0)
1123
        goto cleanup;
1124

1125
    if (udevGetDeviceType(device, &def->caps->data.type) != 0)
1126
        goto cleanup;
1127

1128
    if (udevGetDeviceDetails(device, def) != 0)
1129
        goto cleanup;
1130

1131
    if (udevSetParent(device, def) != 0)
1132
        goto cleanup;
1133

1134 1135 1136 1137 1138 1139
    dev = virNodeDeviceFindByName(&driver->devs, def->name);
    if (dev) {
        virNodeDeviceObjUnlock(dev);
        new_device = false;
    }

1140 1141
    /* If this is a device change, the old definition will be freed
     * and the current definition will take its place. */
1142
    dev = virNodeDeviceAssignDef(&driver->devs, def);
1143
    if (dev == NULL)
1144
        goto cleanup;
1145

1146 1147 1148 1149
    if (new_device)
        event = virNodeDeviceEventLifecycleNew(dev->def->name,
                                               VIR_NODE_DEVICE_EVENT_CREATED,
                                               0);
1150 1151
    else
        event = virNodeDeviceEventUpdateNew(dev->def->name);
1152

1153 1154 1155 1156
    virNodeDeviceObjUnlock(dev);

    ret = 0;

1157
 cleanup:
1158 1159 1160
    if (event)
        virObjectEventStateQueue(driver->nodeDeviceEventState, event);

1161
    if (ret != 0) {
1162
        VIR_DEBUG("Discarding device %d %p %s", ret, def,
1163
                  def ? NULLSTR(def->sysfs_path) : "");
1164 1165 1166
        virNodeDeviceDefFree(def);
    }

1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180
    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);
1181

1182 1183
    if (device != NULL) {
        if (udevAddOneDevice(device) != 0) {
1184 1185
            VIR_DEBUG("Failed to create node device for udev device '%s'",
                      name);
1186 1187 1188 1189
        }
        ret = 0;
    }

1190 1191
    udev_device_unref(device);

1192 1193 1194 1195
    return ret;
}


1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
/* 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;
}


1219 1220 1221 1222
static int udevEnumerateDevices(struct udev *udev)
{
    struct udev_enumerate *udev_enumerate = NULL;
    struct udev_list_entry *list_entry = NULL;
1223
    int ret = -1;
1224 1225

    udev_enumerate = udev_enumerate_new(udev);
1226 1227
    if (udevEnumerateAddMatches(udev_enumerate) < 0)
        goto cleanup;
1228 1229

    ret = udev_enumerate_scan_devices(udev_enumerate);
1230
    if (ret != 0) {
1231 1232 1233
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("udev scan devices returned %d"),
                       ret);
1234
        goto cleanup;
1235 1236 1237 1238 1239 1240 1241 1242
    }

    udev_list_entry_foreach(list_entry,
                            udev_enumerate_get_list_entry(udev_enumerate)) {

        udevProcessDeviceListEntry(udev, list_entry);
    }

1243
 cleanup:
1244 1245 1246 1247 1248
    udev_enumerate_unref(udev_enumerate);
    return ret;
}


1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260
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;
}


1261
static int nodeStateCleanup(void)
1262
{
1263
    udevPrivate *priv = NULL;
1264 1265 1266
    struct udev_monitor *udev_monitor = NULL;
    struct udev *udev = NULL;

J
Ján Tomko 已提交
1267 1268
    if (!driver)
        return -1;
1269

J
Ján Tomko 已提交
1270
    nodeDeviceLock();
1271

1272 1273
    virObjectEventStateFree(driver->nodeDeviceEventState);

J
Ján Tomko 已提交
1274
    priv = driver->privateData;
1275

1276 1277 1278
    if (priv) {
        if (priv->watch != -1)
            virEventRemoveHandle(priv->watch);
1279

1280
        udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
1281

1282 1283 1284 1285
        if (udev_monitor != NULL) {
            udev = udev_monitor_get_udev(udev_monitor);
            udev_monitor_unref(udev_monitor);
        }
J
Ján Tomko 已提交
1286
    }
1287

J
Ján Tomko 已提交
1288 1289
    if (udev != NULL)
        udev_unref(udev);
1290

J
Ján Tomko 已提交
1291 1292 1293 1294 1295
    virNodeDeviceObjListFree(&driver->devs);
    nodeDeviceUnlock();
    virMutexDestroy(&driver->lock);
    VIR_FREE(driver);
    VIR_FREE(priv);
1296

J
Ján Tomko 已提交
1297 1298
    udevPCITranslateDeinit();
    return 0;
1299 1300 1301 1302 1303 1304 1305 1306 1307
}


static void udevEventHandleCallback(int watch ATTRIBUTE_UNUSED,
                                    int fd,
                                    int events ATTRIBUTE_UNUSED,
                                    void *data ATTRIBUTE_UNUSED)
{
    struct udev_device *device = NULL;
1308
    struct udev_monitor *udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
1309 1310 1311
    const char *action = NULL;
    int udev_fd = -1;

1312
    nodeDeviceLock();
1313 1314
    udev_fd = udev_monitor_get_fd(udev_monitor);
    if (fd != udev_fd) {
1315 1316 1317 1318
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("File descriptor returned by udev %d does not "
                         "match node device file descriptor %d"),
                       fd, udev_fd);
1319
        goto cleanup;
1320 1321 1322 1323
    }

    device = udev_monitor_receive_device(udev_monitor);
    if (device == NULL) {
1324 1325
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("udev_monitor_receive_device returned NULL"));
1326
        goto cleanup;
1327 1328 1329
    }

    action = udev_device_get_action(device);
1330
    VIR_DEBUG("udev action: '%s'", action);
1331 1332 1333

    if (STREQ(action, "add") || STREQ(action, "change")) {
        udevAddOneDevice(device);
1334
        goto cleanup;
1335 1336 1337 1338
    }

    if (STREQ(action, "remove")) {
        udevRemoveOneDevice(device);
1339
        goto cleanup;
1340 1341
    }

1342
 cleanup:
1343
    udev_device_unref(device);
1344
    nodeDeviceUnlock();
1345 1346 1347 1348
    return;
}


1349 1350
/* DMI is intel-compatible specific */
#if defined(__x86_64__) || defined(__i386__) || defined(__amd64__)
1351
static void
1352
udevGetDMIData(virNodeDevCapDataPtr data)
1353 1354 1355 1356
{
    struct udev *udev = NULL;
    struct udev_device *device = NULL;

1357
    udev = udev_monitor_get_udev(DRV_STATE_UDEV_MONITOR(driver));
1358

1359 1360
    device = udev_device_new_from_syspath(udev, DMI_DEVPATH);
    if (device == NULL) {
1361 1362
        device = udev_device_new_from_syspath(udev, DMI_DEVPATH_FALLBACK);
        if (device == NULL) {
1363 1364 1365
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to get udev device for syspath '%s' or '%s'"),
                           DMI_DEVPATH, DMI_DEVPATH_FALLBACK);
1366
            return;
1367
        }
1368 1369
    }

1370 1371
    if (udevGetStringSysfsAttr(device, "product_name",
                               &data->system.product_name) < 0)
1372
        goto cleanup;
1373 1374
    if (udevGetStringSysfsAttr(device, "sys_vendor",
                               &data->system.hardware.vendor_name) < 0)
1375
        goto cleanup;
1376 1377
    if (udevGetStringSysfsAttr(device, "product_version",
                               &data->system.hardware.version) < 0)
1378
        goto cleanup;
1379 1380
    if (udevGetStringSysfsAttr(device, "product_serial",
                               &data->system.hardware.serial) < 0)
1381
        goto cleanup;
1382

1383
    if (virGetHostUUID(data->system.hardware.uuid))
1384
        goto cleanup;
1385

1386 1387
    if (udevGetStringSysfsAttr(device, "bios_vendor",
                               &data->system.firmware.vendor_name) < 0)
1388
        goto cleanup;
1389 1390
    if (udevGetStringSysfsAttr(device, "bios_version",
                               &data->system.firmware.version) < 0)
1391
        goto cleanup;
1392 1393
    if (udevGetStringSysfsAttr(device, "bios_date",
                               &data->system.firmware.release_date) < 0)
1394
        goto cleanup;
1395

1396
 cleanup:
1397
    if (device != NULL)
1398 1399 1400
        udev_device_unref(device);
    return;
}
1401
#endif
1402 1403 1404 1405 1406 1407 1408 1409


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

1410 1411
    if (VIR_ALLOC(def) < 0)
        return -1;
1412

1413
    if (VIR_STRDUP(def->name, "computer") < 0)
1414
        goto cleanup;
1415

1416
    if (VIR_ALLOC(def->caps) != 0)
1417
        goto cleanup;
1418

1419
#if defined(__x86_64__) || defined(__i386__) || defined(__amd64__)
1420
    udevGetDMIData(&def->caps->data);
1421
#endif
1422

1423
    dev = virNodeDeviceAssignDef(&driver->devs, def);
1424
    if (dev == NULL)
1425
        goto cleanup;
1426 1427 1428 1429 1430

    virNodeDeviceObjUnlock(dev);

    ret = 0;

1431
 cleanup:
1432
    if (ret == -1)
1433 1434
        virNodeDeviceDefFree(def);

1435 1436 1437
    return ret;
}

1438
static int udevPCITranslateInit(bool privileged ATTRIBUTE_UNUSED)
1439
{
1440 1441 1442 1443
#if defined __s390__ || defined __s390x_
    /* On s390(x) system there is no PCI bus.
     * Therefore there is nothing to initialize here. */
#else
1444
    int rc;
1445

1446
    if ((rc = pci_system_init()) != 0) {
1447 1448 1449
        /* 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.  */
1450
        if (errno != ENOENT && (privileged  || errno != EACCES)) {
1451 1452
            virReportSystemError(rc, "%s",
                                 _("Failed to initialize libpciaccess"));
1453
            return -1;
1454
        }
1455
    }
1456
#endif
1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467
    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;

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

    priv->watch = -1;
1472
    priv->privileged = privileged;
1473

1474
    if (VIR_ALLOC(driver) < 0) {
1475
        VIR_FREE(priv);
1476
        return -1;
1477 1478
    }

1479
    if (virMutexInit(&driver->lock) < 0) {
1480 1481
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to initialize mutex"));
1482
        VIR_FREE(priv);
1483
        VIR_FREE(driver);
1484
        return -1;
1485 1486
    }

1487
    driver->privateData = priv;
1488
    nodeDeviceLock();
1489
    driver->nodeDeviceEventState = virObjectEventStateNew();
1490

1491
    if (udevPCITranslateInit(privileged) < 0)
1492
        goto cleanup;
1493

1494 1495 1496 1497 1498 1499 1500
    /*
     * http://www.kernel.org/pub/linux/utils/kernel/hotplug/libudev/libudev-udev.html#udev-new
     *
     * indicates no return value other than success, so we don't check
     * its return value.
     */
    udev = udev_new();
1501
#if HAVE_UDEV_LOGGING
J
Ján Tomko 已提交
1502 1503
    /* cast to get rid of missing-format-attribute warning */
    udev_set_log_fn(udev, (udevLogFunctionPtr) udevLogFunction);
1504
#endif
1505

1506 1507
    priv->udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
    if (priv->udev_monitor == NULL) {
1508 1509
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("udev_monitor_new_from_netlink returned NULL"));
1510
        goto cleanup;
1511 1512
    }

1513
    udev_monitor_enable_receiving(priv->udev_monitor);
1514 1515 1516 1517 1518 1519 1520 1521 1522

    /* 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.  */
1523 1524 1525
    priv->watch = virEventAddHandle(udev_monitor_get_fd(priv->udev_monitor),
                                    VIR_EVENT_HANDLE_READABLE,
                                    udevEventHandleCallback, NULL, NULL);
1526
    if (priv->watch == -1)
1527
        goto cleanup;
1528 1529

    /* Create a fictional 'computer' device to root the device tree. */
1530
    if (udevSetupSystemDev() != 0)
1531
        goto cleanup;
1532 1533 1534

    /* Populate with known devices */

1535
    if (udevEnumerateDevices(udev) != 0)
1536
        goto cleanup;
1537 1538

    ret = 0;
1539

1540
 cleanup:
1541
    nodeDeviceUnlock();
1542

1543
    if (ret == -1)
1544
        nodeStateCleanup();
1545 1546 1547 1548
    return ret;
}


1549
static int nodeStateReload(void)
1550 1551 1552 1553 1554
{
    return 0;
}


1555
static virNodeDeviceDriver udevNodeDeviceDriver = {
1556
    .name = "udev",
1557 1558
    .nodeNumOfDevices = nodeNumOfDevices, /* 0.7.3 */
    .nodeListDevices = nodeListDevices, /* 0.7.3 */
1559
    .connectListAllNodeDevices = nodeConnectListAllNodeDevices, /* 0.10.2 */
1560 1561
    .connectNodeDeviceEventRegisterAny = nodeConnectNodeDeviceEventRegisterAny, /* 2.2.0 */
    .connectNodeDeviceEventDeregisterAny = nodeConnectNodeDeviceEventDeregisterAny, /* 2.2.0 */
1562 1563 1564 1565 1566 1567 1568 1569
    .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 */
1570 1571 1572
};

static virStateDriver udevStateDriver = {
M
Matthias Bolte 已提交
1573
    .name = "udev",
1574 1575 1576
    .stateInitialize = nodeStateInitialize, /* 0.7.3 */
    .stateCleanup = nodeStateCleanup, /* 0.7.3 */
    .stateReload = nodeStateReload, /* 0.7.3 */
1577 1578 1579 1580
};

int udevNodeRegister(void)
{
1581
    VIR_DEBUG("Registering udev node device backend");
1582

1583
    if (virSetSharedNodeDeviceDriver(&udevNodeDeviceDriver) < 0)
1584 1585 1586 1587
        return -1;

    return virRegisterStateDriver(&udevStateDriver);
}