node_device_udev.c 44.8 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 31
#include "node_device_conf.h"
#include "node_device_driver.h"
32 33 34
#include "node_device_linux_sysfs.h"
#include "node_device_udev.h"
#include "virerror.h"
35 36
#include "driver.h"
#include "datatypes.h"
37
#include "virlog.h"
38
#include "viralloc.h"
39
#include "viruuid.h"
40
#include "virbuffer.h"
41
#include "virfile.h"
42
#include "virpci.h"
43
#include "virstring.h"
44
#include "virnetdev.h"
45 46 47

#define VIR_FROM_THIS VIR_FROM_NODEDEV

48 49
VIR_LOG_INIT("node_device.node_device_udev");

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

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

60

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

    return false;
}


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

77
    ret = udev_device_get_property_value(udev_device, property_key);
78

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

    return ret;
}


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

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


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

105
    str = udevGetDeviceProperty(udev_device, property_key);
106

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


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

123
    str = udevGetDeviceProperty(udev_device, property_key);
124

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


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

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

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


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

156
    virStringStripControlChars(*value);
157

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

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


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

172
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
173

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

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


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

191
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
192

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

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


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

209
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
210

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

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


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

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

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

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

    def->name = virBufferContentAndReset(&buf);

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

245
    return 0;
246 247
}

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

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

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

    format = virBufferContentAndReset(&buf);

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

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


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

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

311
    return 0;
312 313 314
}


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

326
    syspath = udev_device_get_syspath(device);
327

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

331 332 333 334 335 336 337 338
    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);
339
        goto cleanup;
340 341
    }

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

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

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

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

358 359 360 361 362
    /* 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)
363
        goto cleanup;
364

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

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

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

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

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

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

                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;
401 402 403
        }
    }

404 405
    ret = 0;

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


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

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

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

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

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

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

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

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

451
    return 0;
452 453 454 455 456 457
}


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

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

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

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

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

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

479
    return 0;
480 481 482 483 484 485
}


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

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

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

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

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

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

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

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

516
    return 0;
517 518 519 520 521 522
}


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

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

529 530 531 532 533
    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);
534
        return -1;
535 536
    }

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

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

542
    return 0;
543 544 545
}


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

    sysname = udev_device_get_sysname(device);

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

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

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


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

    *typestring = NULL;

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

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

    return ret;
}


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

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

632 633 634 635 636 637 638 639
    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;
640 641
    }

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

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

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

    ret = 0;

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


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

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

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

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

680
    return 0;
681 682 683
}


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

762 763 764 765

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

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

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

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

779
    return 0;
780 781 782 783
}



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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return 0;
}

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

927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946
    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. */
947
        if (udevHasDeviceProperty(device, "PCI_CLASS"))
948
            *type = VIR_NODE_DEV_CAP_PCI_DEV;
949

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

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

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

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

    return ret;
}


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

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

    return ret;
}


static int udevRemoveOneDevice(struct udev_device *device)
{
    virNodeDeviceObjPtr dev = NULL;
    const char *name = NULL;
    int ret = 0;

    name = udev_device_get_syspath(device);
1031
    dev = virNodeDeviceFindBySysfsPath(&driver->devs, name);
1032

1033
    if (dev != NULL) {
1034
        VIR_DEBUG("Removing device '%s' with sysfs path '%s'",
1035
                  dev->def->name, name);
1036
        virNodeDeviceObjRemove(&driver->devs, dev);
1037
    } else {
1038 1039
        VIR_DEBUG("Failed to find device to remove that has udev name '%s'",
                  name);
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054
        ret = -1;
    }

    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;

1055 1056
    parent_device = device;
    do {
1057

1058
        parent_device = udev_device_get_parent(parent_device);
1059
        if (parent_device == NULL)
1060
            break;
1061

1062 1063
        parent_sysfs_path = udev_device_get_syspath(parent_device);
        if (parent_sysfs_path == NULL) {
1064 1065 1066
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not get syspath for parent of '%s'"),
                           udev_device_get_syspath(parent_device));
1067
            goto cleanup;
1068 1069
        }

1070
        dev = virNodeDeviceFindBySysfsPath(&driver->devs,
1071 1072
                                           parent_sysfs_path);
        if (dev != NULL) {
1073 1074
            if (VIR_STRDUP(def->parent, dev->def->name) < 0) {
                virNodeDeviceObjUnlock(dev);
1075
                goto cleanup;
1076
            }
1077
            virNodeDeviceObjUnlock(dev);
1078

1079
            if (VIR_STRDUP(def->parent_sysfs_path, parent_sysfs_path) < 0)
1080
                goto cleanup;
1081 1082 1083 1084
        }

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

1085
    if (!def->parent && VIR_STRDUP(def->parent, "computer") < 0)
1086
        goto cleanup;
1087 1088 1089

    ret = 0;

1090
 cleanup:
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
    return ret;
}


static int udevAddOneDevice(struct udev_device *device)
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDeviceObjPtr dev = NULL;
    int ret = -1;

1101
    if (VIR_ALLOC(def) != 0)
1102
        goto cleanup;
1103

1104
    if (VIR_STRDUP(def->sysfs_path, udev_device_get_syspath(device)) < 0)
1105
        goto cleanup;
1106

1107
    if (udevGetStringProperty(device, "DRIVER", &def->driver) < 0)
1108
        goto cleanup;
1109

1110
    if (VIR_ALLOC(def->caps) != 0)
1111
        goto cleanup;
1112

1113
    if (udevGetDeviceType(device, &def->caps->data.type) != 0)
1114
        goto cleanup;
1115

1116
    if (udevGetDeviceDetails(device, def) != 0)
1117
        goto cleanup;
1118

1119
    if (udevSetParent(device, def) != 0)
1120
        goto cleanup;
1121

1122 1123
    /* If this is a device change, the old definition will be freed
     * and the current definition will take its place. */
1124
    dev = virNodeDeviceAssignDef(&driver->devs, def);
1125
    if (dev == NULL)
1126
        goto cleanup;
1127 1128 1129 1130 1131

    virNodeDeviceObjUnlock(dev);

    ret = 0;

1132
 cleanup:
1133
    if (ret != 0) {
1134
        VIR_DEBUG("Discarding device %d %p %s", ret, def,
1135
                  def ? NULLSTR(def->sysfs_path) : "");
1136 1137 1138
        virNodeDeviceDefFree(def);
    }

1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152
    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);
1153

1154 1155
    if (device != NULL) {
        if (udevAddOneDevice(device) != 0) {
1156 1157
            VIR_DEBUG("Failed to create node device for udev device '%s'",
                      name);
1158 1159 1160 1161
        }
        ret = 0;
    }

1162 1163
    udev_device_unref(device);

1164 1165 1166 1167
    return ret;
}


1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
/* 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;
}


1191 1192 1193 1194
static int udevEnumerateDevices(struct udev *udev)
{
    struct udev_enumerate *udev_enumerate = NULL;
    struct udev_list_entry *list_entry = NULL;
1195
    int ret = -1;
1196 1197

    udev_enumerate = udev_enumerate_new(udev);
1198 1199
    if (udevEnumerateAddMatches(udev_enumerate) < 0)
        goto cleanup;
1200 1201

    ret = udev_enumerate_scan_devices(udev_enumerate);
1202
    if (ret != 0) {
1203 1204 1205
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("udev scan devices returned %d"),
                       ret);
1206
        goto cleanup;
1207 1208 1209 1210 1211 1212 1213 1214
    }

    udev_list_entry_foreach(list_entry,
                            udev_enumerate_get_list_entry(udev_enumerate)) {

        udevProcessDeviceListEntry(udev, list_entry);
    }

1215
 cleanup:
1216 1217 1218 1219 1220
    udev_enumerate_unref(udev_enumerate);
    return ret;
}


1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232
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;
}


1233
static int nodeStateCleanup(void)
1234
{
1235
    udevPrivate *priv = NULL;
1236 1237 1238
    struct udev_monitor *udev_monitor = NULL;
    struct udev *udev = NULL;

J
Ján Tomko 已提交
1239 1240
    if (!driver)
        return -1;
1241

J
Ján Tomko 已提交
1242
    nodeDeviceLock();
1243

J
Ján Tomko 已提交
1244
    priv = driver->privateData;
1245

1246 1247 1248
    if (priv) {
        if (priv->watch != -1)
            virEventRemoveHandle(priv->watch);
1249

1250
        udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
1251

1252 1253 1254 1255
        if (udev_monitor != NULL) {
            udev = udev_monitor_get_udev(udev_monitor);
            udev_monitor_unref(udev_monitor);
        }
J
Ján Tomko 已提交
1256
    }
1257

J
Ján Tomko 已提交
1258 1259
    if (udev != NULL)
        udev_unref(udev);
1260

J
Ján Tomko 已提交
1261 1262 1263 1264 1265
    virNodeDeviceObjListFree(&driver->devs);
    nodeDeviceUnlock();
    virMutexDestroy(&driver->lock);
    VIR_FREE(driver);
    VIR_FREE(priv);
1266

J
Ján Tomko 已提交
1267 1268
    udevPCITranslateDeinit();
    return 0;
1269 1270 1271 1272 1273 1274 1275 1276 1277
}


static void udevEventHandleCallback(int watch ATTRIBUTE_UNUSED,
                                    int fd,
                                    int events ATTRIBUTE_UNUSED,
                                    void *data ATTRIBUTE_UNUSED)
{
    struct udev_device *device = NULL;
1278
    struct udev_monitor *udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
1279 1280 1281
    const char *action = NULL;
    int udev_fd = -1;

1282
    nodeDeviceLock();
1283 1284
    udev_fd = udev_monitor_get_fd(udev_monitor);
    if (fd != udev_fd) {
1285 1286 1287 1288
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("File descriptor returned by udev %d does not "
                         "match node device file descriptor %d"),
                       fd, udev_fd);
1289
        goto cleanup;
1290 1291 1292 1293
    }

    device = udev_monitor_receive_device(udev_monitor);
    if (device == NULL) {
1294 1295
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("udev_monitor_receive_device returned NULL"));
1296
        goto cleanup;
1297 1298 1299
    }

    action = udev_device_get_action(device);
1300
    VIR_DEBUG("udev action: '%s'", action);
1301 1302 1303

    if (STREQ(action, "add") || STREQ(action, "change")) {
        udevAddOneDevice(device);
1304
        goto cleanup;
1305 1306 1307 1308
    }

    if (STREQ(action, "remove")) {
        udevRemoveOneDevice(device);
1309
        goto cleanup;
1310 1311
    }

1312
 cleanup:
1313
    udev_device_unref(device);
1314
    nodeDeviceUnlock();
1315 1316 1317 1318
    return;
}


1319 1320
/* DMI is intel-compatible specific */
#if defined(__x86_64__) || defined(__i386__) || defined(__amd64__)
1321
static void
1322
udevGetDMIData(virNodeDevCapDataPtr data)
1323 1324 1325 1326
{
    struct udev *udev = NULL;
    struct udev_device *device = NULL;

1327
    udev = udev_monitor_get_udev(DRV_STATE_UDEV_MONITOR(driver));
1328

1329 1330
    device = udev_device_new_from_syspath(udev, DMI_DEVPATH);
    if (device == NULL) {
1331 1332
        device = udev_device_new_from_syspath(udev, DMI_DEVPATH_FALLBACK);
        if (device == NULL) {
1333 1334 1335
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to get udev device for syspath '%s' or '%s'"),
                           DMI_DEVPATH, DMI_DEVPATH_FALLBACK);
1336
            return;
1337
        }
1338 1339
    }

1340 1341
    if (udevGetStringSysfsAttr(device, "product_name",
                               &data->system.product_name) < 0)
1342
        goto cleanup;
1343 1344
    if (udevGetStringSysfsAttr(device, "sys_vendor",
                               &data->system.hardware.vendor_name) < 0)
1345
        goto cleanup;
1346 1347
    if (udevGetStringSysfsAttr(device, "product_version",
                               &data->system.hardware.version) < 0)
1348
        goto cleanup;
1349 1350
    if (udevGetStringSysfsAttr(device, "product_serial",
                               &data->system.hardware.serial) < 0)
1351
        goto cleanup;
1352

1353
    if (virGetHostUUID(data->system.hardware.uuid))
1354
        goto cleanup;
1355

1356 1357
    if (udevGetStringSysfsAttr(device, "bios_vendor",
                               &data->system.firmware.vendor_name) < 0)
1358
        goto cleanup;
1359 1360
    if (udevGetStringSysfsAttr(device, "bios_version",
                               &data->system.firmware.version) < 0)
1361
        goto cleanup;
1362 1363
    if (udevGetStringSysfsAttr(device, "bios_date",
                               &data->system.firmware.release_date) < 0)
1364
        goto cleanup;
1365

1366
 cleanup:
1367
    if (device != NULL)
1368 1369 1370
        udev_device_unref(device);
    return;
}
1371
#endif
1372 1373 1374 1375 1376 1377 1378 1379


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

1380 1381
    if (VIR_ALLOC(def) < 0)
        return -1;
1382

1383
    if (VIR_STRDUP(def->name, "computer") < 0)
1384
        goto cleanup;
1385

1386
    if (VIR_ALLOC(def->caps) != 0)
1387
        goto cleanup;
1388

1389
#if defined(__x86_64__) || defined(__i386__) || defined(__amd64__)
1390
    udevGetDMIData(&def->caps->data);
1391
#endif
1392

1393
    dev = virNodeDeviceAssignDef(&driver->devs, def);
1394
    if (dev == NULL)
1395
        goto cleanup;
1396 1397 1398 1399 1400

    virNodeDeviceObjUnlock(dev);

    ret = 0;

1401
 cleanup:
1402
    if (ret == -1)
1403 1404
        virNodeDeviceDefFree(def);

1405 1406 1407
    return ret;
}

1408
static int udevPCITranslateInit(bool privileged ATTRIBUTE_UNUSED)
1409
{
1410 1411 1412 1413
#if defined __s390__ || defined __s390x_
    /* On s390(x) system there is no PCI bus.
     * Therefore there is nothing to initialize here. */
#else
1414
    int rc;
1415

1416
    if ((rc = pci_system_init()) != 0) {
1417 1418 1419
        /* 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.  */
1420
        if (errno != ENOENT && (privileged  || errno != EACCES)) {
1421 1422
            virReportSystemError(rc, "%s",
                                 _("Failed to initialize libpciaccess"));
1423
            return -1;
1424
        }
1425
    }
1426
#endif
1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437
    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;

1438
    if (VIR_ALLOC(priv) < 0)
1439
        return -1;
1440 1441

    priv->watch = -1;
1442
    priv->privileged = privileged;
1443

1444
    if (VIR_ALLOC(driver) < 0) {
1445
        VIR_FREE(priv);
1446
        return -1;
1447 1448
    }

1449
    if (virMutexInit(&driver->lock) < 0) {
1450 1451
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to initialize mutex"));
1452
        VIR_FREE(priv);
1453
        VIR_FREE(driver);
1454
        return -1;
1455 1456
    }

1457
    driver->privateData = priv;
1458
    nodeDeviceLock();
1459

1460
    if (udevPCITranslateInit(privileged) < 0)
1461
        goto cleanup;
1462

1463 1464 1465 1466 1467 1468 1469
    /*
     * 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();
1470
#if HAVE_UDEV_LOGGING
J
Ján Tomko 已提交
1471 1472
    /* cast to get rid of missing-format-attribute warning */
    udev_set_log_fn(udev, (udevLogFunctionPtr) udevLogFunction);
1473
#endif
1474

1475 1476
    priv->udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
    if (priv->udev_monitor == NULL) {
1477 1478
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("udev_monitor_new_from_netlink returned NULL"));
1479
        goto cleanup;
1480 1481
    }

1482
    udev_monitor_enable_receiving(priv->udev_monitor);
1483 1484 1485 1486 1487 1488 1489 1490 1491

    /* 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.  */
1492 1493 1494
    priv->watch = virEventAddHandle(udev_monitor_get_fd(priv->udev_monitor),
                                    VIR_EVENT_HANDLE_READABLE,
                                    udevEventHandleCallback, NULL, NULL);
1495
    if (priv->watch == -1)
1496
        goto cleanup;
1497 1498

    /* Create a fictional 'computer' device to root the device tree. */
1499
    if (udevSetupSystemDev() != 0)
1500
        goto cleanup;
1501 1502 1503

    /* Populate with known devices */

1504
    if (udevEnumerateDevices(udev) != 0)
1505
        goto cleanup;
1506 1507

    ret = 0;
1508

1509
 cleanup:
1510
    nodeDeviceUnlock();
1511

1512
    if (ret == -1)
1513
        nodeStateCleanup();
1514 1515 1516 1517
    return ret;
}


1518
static int nodeStateReload(void)
1519 1520 1521 1522 1523
{
    return 0;
}


1524
static virNodeDeviceDriver udevNodeDeviceDriver = {
1525
    .name = "udev",
1526 1527
    .nodeNumOfDevices = nodeNumOfDevices, /* 0.7.3 */
    .nodeListDevices = nodeListDevices, /* 0.7.3 */
1528
    .connectListAllNodeDevices = nodeConnectListAllNodeDevices, /* 0.10.2 */
1529 1530 1531 1532 1533 1534 1535 1536
    .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 */
1537 1538 1539
};

static virStateDriver udevStateDriver = {
M
Matthias Bolte 已提交
1540
    .name = "udev",
1541 1542 1543
    .stateInitialize = nodeStateInitialize, /* 0.7.3 */
    .stateCleanup = nodeStateCleanup, /* 0.7.3 */
    .stateReload = nodeStateReload, /* 0.7.3 */
1544 1545 1546 1547
};

int udevNodeRegister(void)
{
1548
    VIR_DEBUG("Registering udev node device backend");
1549

1550
    if (virSetSharedNodeDeviceDriver(&udevNodeDeviceDriver) < 0)
1551 1552 1553 1554
        return -1;

    return virRegisterStateDriver(&udevStateDriver);
}