node_device_udev.c 45.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 108
    if (str && virStrToLong_i(str, NULL, base, value) < 0) {
        VIR_ERROR(_("Failed to convert '%s' to int"), str);
109
        return -1;
110
    }
111
    return 0;
112 113 114 115 116 117 118 119
}


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

122
    str = udevGetDeviceProperty(udev_device, property_key);
123

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


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

137
    ret = udev_device_get_sysattr_value(udev_device, attr_name);
138 139

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


static int udevGetStringSysfsAttr(struct udev_device *udev_device,
                                  const char *attr_name,
                                  char **value)
{
151 152
    if (VIR_STRDUP(*value, udevGetDeviceSysfsAttr(udev_device, attr_name)) < 0)
        return PROPERTY_ERROR;
153

154
    virStringStripControlChars(*value);
155

156 157
    if (*value != NULL && (STREQ(*value, "")))
        VIR_FREE(*value);
158

159
    return *value == NULL ? PROPERTY_MISSING : PROPERTY_FOUND;
160 161 162 163 164 165 166 167
}


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

170
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
171

172 173 174
    if (str && virStrToLong_i(str, NULL, base, value) < 0) {
        VIR_ERROR(_("Failed to convert '%s' to int"), str);
        return PROPERTY_ERROR;
175 176
    }

177
    return str == NULL ? PROPERTY_MISSING : PROPERTY_FOUND;
178 179 180 181 182 183 184 185
}


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

188
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
189

190 191 192
    if (str && virStrToLong_ui(str, NULL, base, value) < 0) {
        VIR_ERROR(_("Failed to convert '%s' to unsigned int"), str);
        return PROPERTY_ERROR;
193 194
    }

195
    return str == NULL ? PROPERTY_MISSING : PROPERTY_FOUND;
196 197 198 199 200 201 202
}


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

205
    str = udevGetDeviceSysfsAttr(udev_device, attr_name);
206

207 208 209
    if (str && virStrToLong_ull(str, NULL, 0, value) < 0) {
        VIR_ERROR(_("Failed to convert '%s' to unsigned long long"), str);
        return PROPERTY_ERROR;
210 211
    }

212
    return str == NULL ? PROPERTY_MISSING : PROPERTY_FOUND;
213 214 215 216 217 218 219
}


static int udevGenerateDeviceName(struct udev_device *device,
                                  virNodeDeviceDefPtr def,
                                  const char *s)
{
220 221
    int ret = 0;
    size_t i;
222 223
    virBuffer buf = VIR_BUFFER_INITIALIZER;

224
    virBufferAsprintf(&buf, "%s_%s",
225 226 227
                      udev_device_get_subsystem(device),
                      udev_device_get_sysname(device));

228
    if (s != NULL)
229
        virBufferAsprintf(&buf, "_%s", s);
230

231 232
    if (virBufferCheckError(&buf) < 0)
        return -1;
233 234 235

    def->name = virBufferContentAndReset(&buf);

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

    return ret;
}

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

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

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

    format = virBufferContentAndReset(&buf);

271
    virLogVMessage(&virLogSelf,
J
Ján Tomko 已提交
272 273 274 275
                   virLogPriorityFromSyslog(priority),
                   file, line, fn, NULL, format ? format : fmt, args);

    VIR_FREE(format);
276
}
277
#endif
278 279


280 281 282 283 284
static int udevTranslatePCIIds(unsigned int vendor,
                               unsigned int product,
                               char **vendor_string,
                               char **product_string)
{
285
    int ret = -1;
286 287 288 289 290 291 292 293 294 295 296 297 298 299
    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,
300
                    &vendor_name,
301 302 303
                    NULL,
                    NULL);

304 305 306
    if (VIR_STRDUP(*vendor_string, vendor_name) < 0||
        VIR_STRDUP(*product_string, device_name) < 0)
        goto out;
307 308 309

    ret = 0;

310
 out:
311 312 313 314
    return ret;
}


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
    int rc;
326

327
    syspath = udev_device_get_syspath(device);
328

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

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 341 342 343 344 345
        goto out;
    }

    if (udevGetUintSysfsAttr(device,
                             "vendor",
                             &data->pci_dev.vendor,
346
                             16) == PROPERTY_ERROR) {
347 348 349 350 351 352
        goto out;
    }

    if (udevGetUintSysfsAttr(device,
                             "device",
                             &data->pci_dev.product,
353
                             16) == PROPERTY_ERROR) {
354 355 356
        goto out;
    }

357 358 359 360 361 362
    if (udevTranslatePCIIds(data->pci_dev.vendor,
                            data->pci_dev.product,
                            &data->pci_dev.vendor_name,
                            &data->pci_dev.product_name) != 0) {
        goto out;
    }
363

364
    if (udevGenerateDeviceName(device, def, NULL) != 0)
365 366
        goto out;

367 368 369 370 371 372 373 374 375 376 377 378
    rc = udevGetIntSysfsAttr(device,
                            "numa_node",
                            &data->pci_dev.numa_node,
                            10);
    if (rc == PROPERTY_ERROR) {
        goto out;
    } else if (rc == PROPERTY_MISSING) {
        /* The default value is -1, because it can't be 0
         * as zero is valid node number. */
        data->pci_dev.numa_node = -1;
    }

379
    if (nodeDeviceSysfsGetPCIRelatedDevCaps(syspath, data) < 0)
380 381
        goto out;

382 383 384 385 386 387
    if (!(pciDev = virPCIDeviceNew(data->pci_dev.domain,
                                   data->pci_dev.bus,
                                   data->pci_dev.slot,
                                   data->pci_dev.function)))
        goto out;

388
    /* We need to be root to read PCI device configs */
389
    if (priv->privileged) {
390 391 392
        if (virPCIGetHeaderType(pciDev, &data->pci_dev.hdrType) < 0)
            goto out;

393 394
        if (virPCIDeviceIsPCIExpress(pciDev) > 0) {
            if (VIR_ALLOC(pci_express) < 0)
395 396
                goto out;

397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
            if (virPCIDeviceHasPCIExpressLink(pciDev) > 0) {
                if (VIR_ALLOC(pci_express->link_cap) < 0 ||
                    VIR_ALLOC(pci_express->link_sta) < 0)
                    goto out;

                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)
                    goto out;

                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;
415 416 417
        }
    }

418 419
    ret = 0;

420
 out:
421
    virPCIDeviceFree(pciDev);
422
    virPCIEDeviceInfoFree(pci_express);
423 424 425 426 427 428 429
    return ret;
}


static int udevProcessUSBDevice(struct udev_device *device,
                                virNodeDeviceDefPtr def)
{
430
    virNodeDevCapDataPtr data = &def->caps->data;
431 432
    int ret = -1;

433
    if (udevGetUintProperty(device, "BUSNUM", &data->usb_dev.bus, 10) < 0)
434
        goto out;
435
    if (udevGetUintProperty(device, "DEVNUM", &data->usb_dev.device, 10) < 0)
436
        goto out;
437
    if (udevGetUintProperty(device, "ID_VENDOR_ID", &data->usb_dev.vendor, 16) < 0)
438 439
        goto out;

440 441 442 443 444 445 446 447 448
    if (udevGetStringProperty(device,
                              "ID_VENDOR_FROM_DATABASE",
                              &data->usb_dev.vendor_name) < 0)
        goto out;

    if (!data->usb_dev.vendor_name &&
        udevGetStringSysfsAttr(device,
                               "manufacturer",
                               &data->usb_dev.vendor_name) == PROPERTY_ERROR)
449 450
        goto out;

451
    if (udevGetUintProperty(device, "ID_MODEL_ID", &data->usb_dev.product, 16) < 0)
452 453
        goto out;

454 455 456 457 458 459 460 461 462
    if (udevGetStringProperty(device,
                              "ID_MODEL_FROM_DATABASE",
                              &data->usb_dev.product_name) < 0)
        goto out;

    if (!data->usb_dev.product_name &&
        udevGetStringSysfsAttr(device,
                               "product",
                               &data->usb_dev.product_name) == PROPERTY_ERROR)
463 464
        goto out;

465
    if (udevGenerateDeviceName(device, def, NULL) != 0)
466 467 468 469
        goto out;

    ret = 0;

470
 out:
471 472 473 474 475 476 477 478
    return ret;
}


static int udevProcessUSBInterface(struct udev_device *device,
                                   virNodeDeviceDefPtr def)
{
    int ret = -1;
479
    virNodeDevCapDataPtr data = &def->caps->data;
480 481 482 483

    if (udevGetUintSysfsAttr(device,
                             "bInterfaceNumber",
                             &data->usb_if.number,
484
                             16) == PROPERTY_ERROR) {
485 486 487 488 489 490
        goto out;
    }

    if (udevGetUintSysfsAttr(device,
                             "bInterfaceClass",
                             &data->usb_if._class,
491
                             16) == PROPERTY_ERROR) {
492 493 494 495 496 497
        goto out;
    }

    if (udevGetUintSysfsAttr(device,
                             "bInterfaceSubClass",
                             &data->usb_if.subclass,
498
                             16) == PROPERTY_ERROR) {
499 500 501 502 503 504
        goto out;
    }

    if (udevGetUintSysfsAttr(device,
                             "bInterfaceProtocol",
                             &data->usb_if.protocol,
505
                             16) == PROPERTY_ERROR) {
506 507 508
        goto out;
    }

509
    if (udevGenerateDeviceName(device, def, NULL) != 0)
510 511 512 513
        goto out;

    ret = 0;

514
 out:
515 516 517 518 519 520 521 522
    return ret;
}


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

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

532 533
    if (udevGetStringProperty(device,
                              "INTERFACE",
534
                              &data->net.ifname) < 0)
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
        goto out;

    if (udevGetStringSysfsAttr(device,
                               "address",
                               &data->net.address) == PROPERTY_ERROR) {
        goto out;
    }

    if (udevGetUintSysfsAttr(device,
                             "addr_len",
                             &data->net.address_len,
                             0) == PROPERTY_ERROR) {
        goto out;
    }

550
    if (udevGenerateDeviceName(device, def, data->net.address) != 0)
551 552
        goto out;

553 554 555
    if (virNetDevGetLinkInfo(data->net.ifname, &data->net.lnk) < 0)
        goto out;

556 557 558
    if (virNetDevGetFeatures(data->net.ifname, &data->net.features) < 0)
        goto out;

559 560
    ret = 0;

561
 out:
562 563 564 565 566 567 568 569
    return ret;
}


static int udevProcessSCSIHost(struct udev_device *device ATTRIBUTE_UNUSED,
                               virNodeDeviceDefPtr def)
{
    int ret = -1;
570
    virNodeDevCapDataPtr data = &def->caps->data;
571
    char *filename = NULL;
J
Ján Tomko 已提交
572
    char *str;
573

574
    filename = last_component(def->sysfs_path);
575

576 577 578 579 580
    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);
581 582 583
        goto out;
    }

584
    nodeDeviceSysfsGetSCSIHostCaps(&def->caps->data);
585

586
    if (udevGenerateDeviceName(device, def, NULL) != 0)
587 588 589 590
        goto out;

    ret = 0;

591
 out:
592 593 594 595
    return ret;
}


D
David Allan 已提交
596 597 598 599 600
static int udevProcessSCSITarget(struct udev_device *device ATTRIBUTE_UNUSED,
                                 virNodeDeviceDefPtr def)
{
    int ret = -1;
    const char *sysname = NULL;
601
    virNodeDevCapDataPtr data = &def->caps->data;
D
David Allan 已提交
602 603 604

    sysname = udev_device_get_sysname(device);

605
    if (VIR_STRDUP(data->scsi_target.name, sysname) < 0)
D
David Allan 已提交
606 607
        goto out;

608
    if (udevGenerateDeviceName(device, def, NULL) != 0)
D
David Allan 已提交
609 610 611 612
        goto out;

    ret = 0;

613
 out:
D
David Allan 已提交
614 615 616 617
    return ret;
}


618
static int udevGetSCSIType(virNodeDeviceDefPtr def ATTRIBUTE_UNUSED,
619
                           unsigned int type, char **typestring)
620 621 622 623 624 625 626 627
{
    int ret = 0;
    int foundtype = 1;

    *typestring = NULL;

    switch (type) {
    case TYPE_DISK:
628
        ignore_value(VIR_STRDUP(*typestring, "disk"));
629 630
        break;
    case TYPE_TAPE:
631
        ignore_value(VIR_STRDUP(*typestring, "tape"));
632 633
        break;
    case TYPE_PROCESSOR:
634
        ignore_value(VIR_STRDUP(*typestring, "processor"));
635 636
        break;
    case TYPE_WORM:
637
        ignore_value(VIR_STRDUP(*typestring, "worm"));
638 639
        break;
    case TYPE_ROM:
640
        ignore_value(VIR_STRDUP(*typestring, "cdrom"));
641 642
        break;
    case TYPE_SCANNER:
643
        ignore_value(VIR_STRDUP(*typestring, "scanner"));
644 645
        break;
    case TYPE_MOD:
646
        ignore_value(VIR_STRDUP(*typestring, "mod"));
647 648
        break;
    case TYPE_MEDIUM_CHANGER:
649
        ignore_value(VIR_STRDUP(*typestring, "changer"));
650 651
        break;
    case TYPE_ENCLOSURE:
652
        ignore_value(VIR_STRDUP(*typestring, "enclosure"));
653
        break;
654
    case TYPE_RAID:
655
        ignore_value(VIR_STRDUP(*typestring, "raid"));
656
        break;
657 658 659 660 661 662 663 664 665 666
    case TYPE_NO_LUN:
    default:
        foundtype = 0;
        break;
    }

    if (*typestring == NULL) {
        if (foundtype == 1) {
            ret = -1;
        } else {
667 668
            VIR_DEBUG("Failed to find SCSI device type %d for %s",
                      type, def->sysfs_path);
669 670 671 672 673 674 675 676 677 678 679 680
        }
    }

    return ret;
}


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

684
    filename = last_component(def->sysfs_path);
685

686 687 688 689 690 691 692 693
    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;
694 695 696 697
    }

    switch (udevGetUintSysfsAttr(device, "type", &tmp, 0)) {
    case PROPERTY_FOUND:
698
        if (udevGetSCSIType(def, tmp, &data->scsi.type) == -1)
699 700 701 702 703 704 705 706 707 708
            goto out;
        break;
    case PROPERTY_MISSING:
        break; /* No type is not an error */
    case PROPERTY_ERROR:
    default:
        goto out;
        break;
    }

709
    if (udevGenerateDeviceName(device, def, NULL) != 0)
710 711 712 713
        goto out;

    ret = 0;

714
 out:
715
    if (ret != 0) {
716
        VIR_ERROR(_("Failed to process SCSI device with sysfs path '%s'"),
717 718 719 720 721 722 723 724 725
                  def->sysfs_path);
    }
    return ret;
}


static int udevProcessDisk(struct udev_device *device,
                           virNodeDeviceDefPtr def)
{
726
    virNodeDevCapDataPtr data = &def->caps->data;
727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
    int ret = 0;

    if (udevGetUint64SysfsAttr(device,
                               "size",
                               &data->storage.num_blocks) == PROPERTY_ERROR) {
        goto out;
    }

    if (udevGetUint64SysfsAttr(device,
                               "queue/logical_block_size",
                               &data->storage.logical_block_size)
        == PROPERTY_ERROR) {
        goto out;
    }

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

745
 out:
746 747 748 749
    return ret;
}


750 751 752
static int udevProcessRemoveableMedia(struct udev_device *device,
                                      virNodeDeviceDefPtr def,
                                      int has_media)
753
{
754
    virNodeDevCapDataPtr data = &def->caps->data;
755 756 757 758 759 760 761
    int tmp_int = 0, ret = 0;

    if ((udevGetIntSysfsAttr(device, "removable", &tmp_int, 0) == PROPERTY_FOUND) &&
        (tmp_int == 1)) {
        def->caps->data.storage.flags |= VIR_NODE_DEV_CAP_STORAGE_REMOVABLE;
    }

762
    if (has_media) {
763 764 765 766

        def->caps->data.storage.flags |=
            VIR_NODE_DEV_CAP_STORAGE_REMOVABLE_MEDIA_AVAILABLE;

767
        if (udevGetStringProperty(device, "ID_FS_LABEL",
768
                                  &data->storage.media_label) < 0)
769 770
            goto out;

771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791
        if (udevGetUint64SysfsAttr(device,
                                   "size",
                                   &data->storage.num_blocks) == PROPERTY_ERROR) {
            goto out;
        }

        if (udevGetUint64SysfsAttr(device,
                                   "queue/logical_block_size",
                                   &data->storage.logical_block_size) == PROPERTY_ERROR) {
            goto out;
        }

        /* 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;
    }

792
 out:
793 794 795
    return ret;
}

796 797 798 799 800 801 802 803 804 805 806
static int udevProcessCDROM(struct udev_device *device,
                            virNodeDeviceDefPtr def)
{
    int ret = -1;
    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);
807
    if (VIR_STRDUP(def->caps->data.storage.drive_type, "cdrom") < 0)
808 809
        goto out;

810 811 812
    if (udevHasDeviceProperty(device, "ID_CDROM_MEDIA") &&
        udevGetIntProperty(device, "ID_CDROM_MEDIA", &has_media, 0) < 0)
        goto out;
813 814

    ret = udevProcessRemoveableMedia(device, def, has_media);
815
 out:
816 817 818 819 820 821 822 823
    return ret;
}

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

824
    if (udevHasDeviceProperty(device, "ID_CDROM_MEDIA")) {
825
        /* USB floppy */
826 827
        if (udevGetIntProperty(device, "DKD_MEDIA_AVAILABLE", &has_media, 0) < 0)
            return -1;
828
    } else if (udevHasDeviceProperty(device, "ID_FS_LABEL")) {
829 830 831 832 833 834
        /* Legacy floppy */
        has_media = 1;
    }

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

836 837 838 839

static int udevProcessSD(struct udev_device *device,
                         virNodeDeviceDefPtr def)
{
840
    virNodeDevCapDataPtr data = &def->caps->data;
841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
    int ret = 0;

    if (udevGetUint64SysfsAttr(device,
                               "size",
                               &data->storage.num_blocks) == PROPERTY_ERROR) {
        goto out;
    }

    if (udevGetUint64SysfsAttr(device,
                               "queue/logical_block_size",
                               &data->storage.logical_block_size)
        == PROPERTY_ERROR) {
        goto out;
    }

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

859
 out:
860 861 862 863 864
    return ret;
}



865 866 867 868 869 870
/* 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)
{
871 872 873
    VIR_DEBUG("Could not find definitive storage type for device "
              "with sysfs path '%s', trying to guess it",
              def->sysfs_path);
874

875 876 877
    /* virtio disk */
    if (STRPREFIX(def->caps->data.storage.block, "/dev/vd") &&
        VIR_STRDUP(def->caps->data.storage.drive_type, "disk") > 0) {
878
        VIR_DEBUG("Found storage type '%s' for device "
879
                  "with sysfs path '%s'",
880 881
                  def->caps->data.storage.drive_type,
                  def->sysfs_path);
882
        return 0;
883
    }
884 885 886
    VIR_DEBUG("Could not determine storage type "
              "for device with sysfs path '%s'", def->sysfs_path);
    return -1;
887 888 889 890 891
}


static void udevStripSpaces(char *s)
{
892
    if (s == NULL)
893 894 895 896 897 898 899 900 901 902 903 904 905 906
        return;

    while (virFileStripSuffix(s, " ")) {
        /* do nothing */
        ;
    }

    return;
}


static int udevProcessStorage(struct udev_device *device,
                              virNodeDeviceDefPtr def)
{
907
    virNodeDevCapDataPtr data = &def->caps->data;
908
    int ret = -1;
909
    const char* devnode;
910

911
    devnode = udev_device_get_devnode(device);
912
    if (!devnode) {
913
        VIR_DEBUG("No devnode for '%s'", udev_device_get_devpath(device));
914 915
        goto out;
    }
916 917 918

    if (VIR_STRDUP(data->storage.block, devnode) < 0)
        goto out;
919

920
    if (udevGetStringProperty(device, "ID_BUS", &data->storage.bus) < 0)
921
        goto out;
922
    if (udevGetStringProperty(device, "ID_SERIAL", &data->storage.serial) < 0)
923
        goto out;
924

925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941
    if (udevGetStringSysfsAttr(device,
                               "device/vendor",
                               &data->storage.vendor) == PROPERTY_ERROR) {
        goto out;
    }
    udevStripSpaces(def->caps->data.storage.vendor);
    if (udevGetStringSysfsAttr(device,
                               "device/model",
                               &data->storage.model) == PROPERTY_ERROR) {
        goto out;
    }
    udevStripSpaces(def->caps->data.storage.model);
    /* 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. */

942 943 944 945
    if (udevGetStringProperty(device, "ID_TYPE", &data->storage.drive_type) < 0)
        goto out;

    if (!data->storage.drive_type ||
946
        STREQ(def->caps->data.storage.drive_type, "generic")) {
947 948
        int val = 0;
        const char *str = NULL;
949 950 951

        /* All floppy drives have the ID_DRIVE_FLOPPY prop. This is
         * needed since legacy floppies don't have a drive_type */
952
        if (udevGetIntProperty(device, "ID_DRIVE_FLOPPY", &val, 0) < 0)
953 954 955
            goto out;
        else if (val == 1)
            str = "floppy";
956

957
        if (!str) {
958
            if (udevGetIntProperty(device, "ID_CDROM", &val, 0) < 0)
959
                goto out;
960 961 962
            else if (val == 1)
                str = "cd";
        }
963

964
        if (!str) {
965
            if (udevGetIntProperty(device, "ID_DRIVE_FLASH_SD", &val, 0) < 0)
966
                goto out;
967 968 969
            if (val == 1)
                str = "sd";
        }
970

971 972
        if (str) {
            if (VIR_STRDUP(data->storage.drive_type, str) < 0)
973
                goto out;
974 975
        } else {
            /* If udev doesn't have it, perhaps we can guess it. */
976
            if (udevKludgeStorageType(def) != 0)
977
                goto out;
978 979 980 981 982 983 984
        }
    }

    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);
985 986
    } else if (STREQ(def->caps->data.storage.drive_type, "floppy")) {
        ret = udevProcessFloppy(device, def);
987 988
    } else if (STREQ(def->caps->data.storage.drive_type, "sd")) {
        ret = udevProcessSD(device, def);
989
    } else {
990 991
        VIR_DEBUG("Unsupported storage type '%s'",
                  def->caps->data.storage.drive_type);
992 993 994
        goto out;
    }

995
    if (udevGenerateDeviceName(device, def, data->storage.serial) != 0)
996 997
        goto out;

998
 out:
999
    VIR_DEBUG("Storage ret=%d", ret);
1000 1001 1002
    return ret;
}

1003
static int
1004
udevProcessSCSIGeneric(struct udev_device *dev,
1005 1006
                       virNodeDeviceDefPtr def)
{
1007 1008
    if (udevGetStringProperty(dev, "DEVNAME", &def->caps->data.sg.path) < 0 ||
        !def->caps->data.sg.path)
1009 1010 1011 1012 1013 1014 1015 1016
        return -1;

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

    return 0;
}

1017 1018
static int
udevGetDeviceType(struct udev_device *device,
1019
                  virNodeDevCapType *type)
1020 1021
{
    const char *devtype = NULL;
1022
    char *subsystem = NULL;
1023
    int ret = -1;
D
David Allan 已提交
1024

1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
    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. */
1045
        if (udevHasDeviceProperty(device, "PCI_CLASS"))
1046
            *type = VIR_NODE_DEV_CAP_PCI_DEV;
1047

1048 1049 1050 1051
        /* 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. */
1052
        if (udevHasDeviceProperty(device, "INTERFACE"))
1053
            *type = VIR_NODE_DEV_CAP_NET;
1054 1055

        /* SCSI generic device doesn't set DEVTYPE property */
1056 1057 1058 1059
        if (udevGetStringProperty(device, "SUBSYSTEM", &subsystem) < 0)
            return -1;

        if (STREQ_NULLABLE(subsystem, "scsi_generic"))
1060 1061
            *type = VIR_NODE_DEV_CAP_SCSI_GENERIC;
        VIR_FREE(subsystem);
1062 1063
    }

1064 1065 1066 1067 1068 1069
    if (!*type)
        VIR_DEBUG("Could not determine device type for device "
                  "with sysfs name '%s'",
                  udev_device_get_sysname(device));
    else
        ret = 0;
1070 1071 1072 1073 1074 1075 1076 1077 1078 1079

    return ret;
}


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

1080
    switch (def->caps->data.type) {
1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098
    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 已提交
1099 1100 1101
    case VIR_NODE_DEV_CAP_SCSI_TARGET:
        ret = udevProcessSCSITarget(device, def);
        break;
1102 1103 1104 1105 1106 1107
    case VIR_NODE_DEV_CAP_SCSI:
        ret = udevProcessSCSIDevice(device, def);
        break;
    case VIR_NODE_DEV_CAP_STORAGE:
        ret = udevProcessStorage(device, def);
        break;
1108
    case VIR_NODE_DEV_CAP_SCSI_GENERIC:
1109
        ret = udevProcessSCSIGeneric(device, def);
1110
        break;
1111
    default:
1112
        VIR_ERROR(_("Unknown device type %d"), def->caps->data.type);
1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127
        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);
1128
    dev = virNodeDeviceFindBySysfsPath(&driver->devs, name);
1129

1130
    if (dev != NULL) {
1131
        VIR_DEBUG("Removing device '%s' with sysfs path '%s'",
1132
                  dev->def->name, name);
1133
        virNodeDeviceObjRemove(&driver->devs, dev);
1134
    } else {
1135 1136
        VIR_DEBUG("Failed to find device to remove that has udev name '%s'",
                  name);
1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151
        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;

1152 1153
    parent_device = device;
    do {
1154

1155
        parent_device = udev_device_get_parent(parent_device);
1156
        if (parent_device == NULL)
1157
            break;
1158

1159 1160
        parent_sysfs_path = udev_device_get_syspath(parent_device);
        if (parent_sysfs_path == NULL) {
1161 1162 1163
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not get syspath for parent of '%s'"),
                           udev_device_get_syspath(parent_device));
1164
            goto out;
1165 1166
        }

1167
        dev = virNodeDeviceFindBySysfsPath(&driver->devs,
1168 1169
                                           parent_sysfs_path);
        if (dev != NULL) {
1170 1171
            if (VIR_STRDUP(def->parent, dev->def->name) < 0) {
                virNodeDeviceObjUnlock(dev);
1172 1173
                goto out;
            }
1174
            virNodeDeviceObjUnlock(dev);
1175

1176
            if (VIR_STRDUP(def->parent_sysfs_path, parent_sysfs_path) < 0)
1177 1178 1179 1180 1181
                goto out;
        }

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

1182
    if (!def->parent && VIR_STRDUP(def->parent, "computer") < 0)
1183 1184 1185 1186
        goto out;

    ret = 0;

1187
 out:
1188 1189 1190 1191 1192 1193 1194 1195 1196 1197
    return ret;
}


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

1198
    if (VIR_ALLOC(def) != 0)
1199 1200
        goto out;

1201 1202 1203
    if (VIR_STRDUP(def->sysfs_path, udev_device_get_syspath(device)) < 0)
        goto out;

1204
    if (udevGetStringProperty(device, "DRIVER", &def->driver) < 0)
1205 1206
        goto out;

1207
    if (VIR_ALLOC(def->caps) != 0)
1208 1209
        goto out;

1210
    if (udevGetDeviceType(device, &def->caps->data.type) != 0)
1211 1212
        goto out;

1213
    if (udevGetDeviceDetails(device, def) != 0)
1214 1215
        goto out;

1216
    if (udevSetParent(device, def) != 0)
1217 1218
        goto out;

1219 1220
    /* If this is a device change, the old definition will be freed
     * and the current definition will take its place. */
1221
    dev = virNodeDeviceAssignDef(&driver->devs, def);
1222
    if (dev == NULL)
1223 1224 1225 1226 1227 1228
        goto out;

    virNodeDeviceObjUnlock(dev);

    ret = 0;

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

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

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

1259 1260
    udev_device_unref(device);

1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274
    return ret;
}


static int udevEnumerateDevices(struct udev *udev)
{
    struct udev_enumerate *udev_enumerate = NULL;
    struct udev_list_entry *list_entry = NULL;
    int ret = 0;

    udev_enumerate = udev_enumerate_new(udev);

    ret = udev_enumerate_scan_devices(udev_enumerate);
    if (0 != ret) {
1275
        VIR_ERROR(_("udev scan devices returned %d"), ret);
1276 1277 1278 1279 1280 1281 1282 1283 1284
        goto out;
    }

    udev_list_entry_foreach(list_entry,
                            udev_enumerate_get_list_entry(udev_enumerate)) {

        udevProcessDeviceListEntry(udev, list_entry);
    }

1285
 out:
1286 1287 1288 1289 1290
    udev_enumerate_unref(udev_enumerate);
    return ret;
}


1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302
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;
}


1303
static int nodeStateCleanup(void)
1304
{
1305
    udevPrivate *priv = NULL;
1306 1307 1308
    struct udev_monitor *udev_monitor = NULL;
    struct udev *udev = NULL;

J
Ján Tomko 已提交
1309 1310
    if (!driver)
        return -1;
1311

J
Ján Tomko 已提交
1312
    nodeDeviceLock();
1313

J
Ján Tomko 已提交
1314
    priv = driver->privateData;
1315

1316 1317 1318
    if (priv) {
        if (priv->watch != -1)
            virEventRemoveHandle(priv->watch);
1319

1320
        udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
1321

1322 1323 1324 1325
        if (udev_monitor != NULL) {
            udev = udev_monitor_get_udev(udev_monitor);
            udev_monitor_unref(udev_monitor);
        }
J
Ján Tomko 已提交
1326
    }
1327

J
Ján Tomko 已提交
1328 1329
    if (udev != NULL)
        udev_unref(udev);
1330

J
Ján Tomko 已提交
1331 1332 1333 1334 1335
    virNodeDeviceObjListFree(&driver->devs);
    nodeDeviceUnlock();
    virMutexDestroy(&driver->lock);
    VIR_FREE(driver);
    VIR_FREE(priv);
1336

J
Ján Tomko 已提交
1337 1338
    udevPCITranslateDeinit();
    return 0;
1339 1340 1341 1342 1343 1344 1345 1346 1347
}


static void udevEventHandleCallback(int watch ATTRIBUTE_UNUSED,
                                    int fd,
                                    int events ATTRIBUTE_UNUSED,
                                    void *data ATTRIBUTE_UNUSED)
{
    struct udev_device *device = NULL;
1348
    struct udev_monitor *udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
1349 1350 1351
    const char *action = NULL;
    int udev_fd = -1;

1352
    nodeDeviceLock();
1353 1354
    udev_fd = udev_monitor_get_fd(udev_monitor);
    if (fd != udev_fd) {
1355 1356
        VIR_ERROR(_("File descriptor returned by udev %d does not "
                    "match node device file descriptor %d"), fd, udev_fd);
1357 1358 1359 1360 1361
        goto out;
    }

    device = udev_monitor_receive_device(udev_monitor);
    if (device == NULL) {
1362
        VIR_ERROR(_("udev_monitor_receive_device returned NULL"));
1363 1364 1365 1366
        goto out;
    }

    action = udev_device_get_action(device);
1367
    VIR_DEBUG("udev action: '%s'", action);
1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378

    if (STREQ(action, "add") || STREQ(action, "change")) {
        udevAddOneDevice(device);
        goto out;
    }

    if (STREQ(action, "remove")) {
        udevRemoveOneDevice(device);
        goto out;
    }

1379
 out:
1380
    udev_device_unref(device);
1381
    nodeDeviceUnlock();
1382 1383 1384 1385
    return;
}


1386 1387
/* DMI is intel-compatible specific */
#if defined(__x86_64__) || defined(__i386__) || defined(__amd64__)
1388
static void
1389
udevGetDMIData(virNodeDevCapDataPtr data)
1390 1391 1392 1393
{
    struct udev *udev = NULL;
    struct udev_device *device = NULL;

1394
    udev = udev_monitor_get_udev(DRV_STATE_UDEV_MONITOR(driver));
1395

1396 1397
    device = udev_device_new_from_syspath(udev, DMI_DEVPATH);
    if (device == NULL) {
1398 1399
        device = udev_device_new_from_syspath(udev, DMI_DEVPATH_FALLBACK);
        if (device == NULL) {
1400
            VIR_ERROR(_("Failed to get udev device for syspath '%s' or '%s'"),
1401
                      DMI_DEVPATH, DMI_DEVPATH_FALLBACK);
1402 1403
            goto out;
        }
1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429
    }

    if (udevGetStringSysfsAttr(device,
                               "product_name",
                               &data->system.product_name) == PROPERTY_ERROR) {
        goto out;
    }
    if (udevGetStringSysfsAttr(device,
                               "sys_vendor",
                               &data->system.hardware.vendor_name)
        == PROPERTY_ERROR) {
        goto out;
    }
    if (udevGetStringSysfsAttr(device,
                               "product_version",
                               &data->system.hardware.version)
        == PROPERTY_ERROR) {
        goto out;
    }
    if (udevGetStringSysfsAttr(device,
                               "product_serial",
                               &data->system.hardware.serial)
        == PROPERTY_ERROR) {
        goto out;
    }

1430
    if (virGetHostUUID(data->system.hardware.uuid))
1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451
        goto out;

    if (udevGetStringSysfsAttr(device,
                               "bios_vendor",
                               &data->system.firmware.vendor_name)
        == PROPERTY_ERROR) {
        goto out;
    }
    if (udevGetStringSysfsAttr(device,
                               "bios_version",
                               &data->system.firmware.version)
        == PROPERTY_ERROR) {
        goto out;
    }
    if (udevGetStringSysfsAttr(device,
                               "bios_date",
                               &data->system.firmware.release_date)
        == PROPERTY_ERROR) {
        goto out;
    }

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


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

1466
    if (VIR_ALLOC(def) != 0)
1467 1468
        goto out;

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

1472
    if (VIR_ALLOC(def->caps) != 0)
1473 1474
        goto out;

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

1479
    dev = virNodeDeviceAssignDef(&driver->devs, def);
1480
    if (dev == NULL)
1481 1482 1483 1484 1485 1486
        goto out;

    virNodeDeviceObjUnlock(dev);

    ret = 0;

1487
 out:
1488
    if (ret == -1)
1489 1490
        virNodeDeviceDefFree(def);

1491 1492 1493
    return ret;
}

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

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

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

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

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

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

1536 1537
    if (virMutexInit(&driver->lock) < 0) {
        VIR_ERROR(_("Failed to initialize mutex for driver"));
1538
        VIR_FREE(priv);
1539
        VIR_FREE(driver);
1540
        return -1;
1541 1542
    }

1543
    driver->privateData = priv;
1544
    nodeDeviceLock();
1545

1546
    if (udevPCITranslateInit(privileged) < 0)
1547 1548
        goto out_unlock;

1549 1550 1551 1552 1553 1554 1555
    /*
     * 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();
1556
#if HAVE_UDEV_LOGGING
J
Ján Tomko 已提交
1557 1558
    /* cast to get rid of missing-format-attribute warning */
    udev_set_log_fn(udev, (udevLogFunctionPtr) udevLogFunction);
1559
#endif
1560

1561 1562
    priv->udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
    if (priv->udev_monitor == NULL) {
1563
        VIR_ERROR(_("udev_monitor_new_from_netlink returned NULL"));
1564
        goto out_unlock;
1565 1566
    }

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

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

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

    /* Populate with known devices */

1589
    if (udevEnumerateDevices(udev) != 0)
1590
        goto out_unlock;
1591 1592

    ret = 0;
1593

1594
 out_unlock:
1595
    nodeDeviceUnlock();
1596

1597
    if (ret == -1)
1598
        nodeStateCleanup();
1599 1600 1601 1602
    return ret;
}


1603
static int nodeStateReload(void)
1604 1605 1606 1607 1608
{
    return 0;
}


1609
static virNodeDeviceDriver udevNodeDeviceDriver = {
1610
    .name = "udev",
1611 1612
    .nodeNumOfDevices = nodeNumOfDevices, /* 0.7.3 */
    .nodeListDevices = nodeListDevices, /* 0.7.3 */
1613
    .connectListAllNodeDevices = nodeConnectListAllNodeDevices, /* 0.10.2 */
1614 1615 1616 1617 1618 1619 1620 1621
    .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 */
1622 1623 1624
};

static virStateDriver udevStateDriver = {
M
Matthias Bolte 已提交
1625
    .name = "udev",
1626 1627 1628
    .stateInitialize = nodeStateInitialize, /* 0.7.3 */
    .stateCleanup = nodeStateCleanup, /* 0.7.3 */
    .stateReload = nodeStateReload, /* 0.7.3 */
1629 1630 1631 1632
};

int udevNodeRegister(void)
{
1633
    VIR_DEBUG("Registering udev node device backend");
1634

1635
    if (virSetSharedNodeDeviceDriver(&udevNodeDeviceDriver) < 0)
1636 1637 1638 1639
        return -1;

    return virRegisterStateDriver(&udevStateDriver);
}