node_device_driver.c 20.3 KB
Newer Older
1
/*
2
 * node_device_driver.c: node device enumeration
3
 *
4
 * Copyright (C) 2010-2015 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * Copyright (C) 2008 Virtual Iron Software, Inc.
 * Copyright (C) 2008 David F. Lively
 *
 * 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
19
 * License along with this library.  If not, see
O
Osier Yang 已提交
20
 * <http://www.gnu.org/licenses/>.
21 22 23 24 25 26 27 28
 *
 * Author: David F. Lively <dlively@virtualiron.com>
 */

#include <config.h>

#include <unistd.h>
#include <errno.h>
29 30
#include <fcntl.h>
#include <time.h>
31

32
#include "virerror.h"
33
#include "datatypes.h"
34
#include "viralloc.h"
35
#include "virfile.h"
36
#include "virstring.h"
37
#include "node_device_conf.h"
38
#include "node_device_event.h"
39
#include "node_device_driver.h"
40 41
#include "node_device_hal.h"
#include "node_device_linux_sysfs.h"
42 43
#include "virutil.h"
#include "viraccessapicheck.h"
44
#include "virnetdev.h"
45

46 47
#define VIR_FROM_THIS VIR_FROM_NODEDEV

48 49
virNodeDeviceDriverStatePtr driver;

50 51 52 53 54
static int update_caps(virNodeDeviceObjPtr dev)
{
    virNodeDevCapsDefPtr cap = dev->def->caps;

    while (cap) {
55 56
        switch (cap->data.type) {
        case VIR_NODE_DEV_CAP_SCSI_HOST:
57
            nodeDeviceSysfsGetSCSIHostCaps(&dev->def->caps->data);
58 59 60 61
            break;
        case VIR_NODE_DEV_CAP_NET:
            if (virNetDevGetLinkInfo(cap->data.net.ifname, &cap->data.net.lnk) < 0)
                return -1;
62 63 64
            virBitmapFree(cap->data.net.features);
            if (virNetDevGetFeatures(cap->data.net.ifname, &cap->data.net.features) < 0)
                return -1;
65
            break;
66 67 68 69 70
        case VIR_NODE_DEV_CAP_PCI_DEV:
           if (nodeDeviceSysfsGetPCIRelatedDevCaps(dev->def->sysfs_path,
                                                   &dev->def->caps->data) < 0)
              return -1;
           break;
71

72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
        /* all types that (supposedly) don't require any updates
         * relative to what's in the cache.
         */
        case VIR_NODE_DEV_CAP_SYSTEM:
        case VIR_NODE_DEV_CAP_USB_DEV:
        case VIR_NODE_DEV_CAP_USB_INTERFACE:
        case VIR_NODE_DEV_CAP_SCSI_TARGET:
        case VIR_NODE_DEV_CAP_SCSI:
        case VIR_NODE_DEV_CAP_STORAGE:
        case VIR_NODE_DEV_CAP_FC_HOST:
        case VIR_NODE_DEV_CAP_VPORTS:
        case VIR_NODE_DEV_CAP_SCSI_GENERIC:
        case VIR_NODE_DEV_CAP_LAST:
            break;
        }
87
        cap = cap->next;
88 89 90 91 92 93
    }

    return 0;
}


94 95 96 97 98 99 100 101 102
#if defined (__linux__) && ( defined (WITH_HAL) || defined(WITH_UDEV))
/* NB: It was previously believed that changes in driver name were
 * relayed to libvirt as "change" events by udev, and the udev event
 * notification is setup to recognize such events and effectively
 * recreate the device entry in the cache. However, neither the kernel
 * nor udev sends such an event, so it is necessary to manually update
 * the driver name for a device each time its entry is used, both for
 * udev *and* HAL backends.
 */
103
static int update_driver_name(virNodeDeviceObjPtr dev)
104 105
{
    char *driver_link = NULL;
106
    char *devpath = NULL;
107 108 109 110 111
    char *p;
    int ret = -1;

    VIR_FREE(dev->def->driver);

112
    if (virAsprintf(&driver_link, "%s/driver", dev->def->sysfs_path) < 0)
113 114 115 116 117 118 119 120 121
        goto cleanup;

    /* Some devices don't have an explicit driver, so just return
       without a name */
    if (access(driver_link, R_OK) < 0) {
        ret = 0;
        goto cleanup;
    }

122
    if (virFileResolveLink(driver_link, &devpath) < 0) {
123
        virReportSystemError(errno,
124 125 126 127 128
                             _("cannot resolve driver link %s"), driver_link);
        goto cleanup;
    }

    p = strrchr(devpath, '/');
129 130
    if (p && VIR_STRDUP(dev->def->driver, p + 1) < 0)
        goto cleanup;
131 132
    ret = 0;

133
 cleanup:
134
    VIR_FREE(driver_link);
135
    VIR_FREE(devpath);
136 137 138 139
    return ret;
}
#else
/* XXX: Implement me for non-linux */
140
static int update_driver_name(virNodeDeviceObjPtr dev ATTRIBUTE_UNUSED)
141 142 143 144 145
{
    return 0;
}
#endif

146

147
void nodeDeviceLock(void)
148
{
149
    virMutexLock(&driver->lock);
150
}
151
void nodeDeviceUnlock(void)
152
{
153
    virMutexUnlock(&driver->lock);
154 155
}

156 157 158
int
nodeNumOfDevices(virConnectPtr conn,
                 const char *cap,
E
Eric Blake 已提交
159
                 unsigned int flags)
160 161
{
    int ndevs = 0;
162
    size_t i;
163

164 165 166
    if (virNodeNumOfDevicesEnsureACL(conn) < 0)
        return -1;

E
Eric Blake 已提交
167 168
    virCheckFlags(0, -1);

169
    nodeDeviceLock();
170
    for (i = 0; i < driver->devs.count; i++) {
171 172 173 174 175
        virNodeDeviceObjPtr obj = driver->devs.objs[i];
        virNodeDeviceObjLock(obj);
        if (virNodeNumOfDevicesCheckACL(conn, obj->def) &&
            ((cap == NULL) ||
             virNodeDeviceHasCap(obj, cap)))
176
            ++ndevs;
177
        virNodeDeviceObjUnlock(obj);
178
    }
179
    nodeDeviceUnlock();
180 181 182 183

    return ndevs;
}

184
int
185 186 187
nodeListDevices(virConnectPtr conn,
                const char *cap,
                char **const names, int maxnames,
E
Eric Blake 已提交
188
                unsigned int flags)
189 190
{
    int ndevs = 0;
191
    size_t i;
192

193 194 195
    if (virNodeListDevicesEnsureACL(conn) < 0)
        return -1;

E
Eric Blake 已提交
196 197
    virCheckFlags(0, -1);

198
    nodeDeviceLock();
199
    for (i = 0; i < driver->devs.count && ndevs < maxnames; i++) {
200 201 202 203 204 205 206
        virNodeDeviceObjPtr obj = driver->devs.objs[i];
        virNodeDeviceObjLock(obj);
        if (virNodeListDevicesCheckACL(conn, obj->def) &&
            (cap == NULL ||
             virNodeDeviceHasCap(obj, cap))) {
            if (VIR_STRDUP(names[ndevs++], obj->def->name) < 0) {
                virNodeDeviceObjUnlock(obj);
207
                goto failure;
208 209
            }
        }
210
        virNodeDeviceObjUnlock(obj);
211
    }
212
    nodeDeviceUnlock();
213 214 215 216

    return ndevs;

 failure:
217
    nodeDeviceUnlock();
218 219 220 221 222 223
    --ndevs;
    while (--ndevs >= 0)
        VIR_FREE(names[ndevs]);
    return -1;
}

O
Osier Yang 已提交
224
int
225 226 227
nodeConnectListAllNodeDevices(virConnectPtr conn,
                              virNodeDevicePtr **devices,
                              unsigned int flags)
O
Osier Yang 已提交
228 229 230 231 232
{
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_NODE_DEVICES_FILTERS_CAP, -1);

233 234 235
    if (virConnectListAllNodeDevicesEnsureACL(conn) < 0)
        return -1;

236
    nodeDeviceLock();
237 238 239
    ret = virNodeDeviceObjListExport(conn, driver->devs, devices,
                                     virConnectListAllNodeDevicesCheckACL,
                                     flags);
240
    nodeDeviceUnlock();
O
Osier Yang 已提交
241 242
    return ret;
}
243

244 245
virNodeDevicePtr
nodeDeviceLookupByName(virConnectPtr conn, const char *name)
246
{
247 248
    virNodeDeviceObjPtr obj;
    virNodeDevicePtr ret = NULL;
249

250
    nodeDeviceLock();
251
    obj = virNodeDeviceFindByName(&driver->devs, name);
252
    nodeDeviceUnlock();
253

254
    if (!obj) {
255 256 257
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       name);
258
        goto cleanup;
259 260
    }

261 262 263
    if (virNodeDeviceLookupByNameEnsureACL(conn, obj->def) < 0)
        goto cleanup;

264 265 266 267
    if ((ret = virGetNodeDevice(conn, name))) {
        if (VIR_STRDUP(ret->parent, obj->def->parent) < 0)
            virObjectUnref(ret);
    }
268

269
 cleanup:
270 271
    if (obj)
        virNodeDeviceObjUnlock(obj);
272
    return ret;
273 274
}

275

276 277 278 279 280
virNodeDevicePtr
nodeDeviceLookupSCSIHostByWWN(virConnectPtr conn,
                              const char *wwnn,
                              const char *wwpn,
                              unsigned int flags)
281
{
282
    size_t i;
283 284 285 286 287
    virNodeDeviceObjListPtr devs = &driver->devs;
    virNodeDevCapsDefPtr cap = NULL;
    virNodeDeviceObjPtr obj = NULL;
    virNodeDevicePtr dev = NULL;

288 289
    virCheckFlags(0, NULL);

290
    nodeDeviceLock();
291 292 293 294 295 296 297

    for (i = 0; i < devs->count; i++) {
        obj = devs->objs[i];
        virNodeDeviceObjLock(obj);
        cap = obj->def->caps;

        while (cap) {
298
            if (cap->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) {
299
                nodeDeviceSysfsGetSCSIHostCaps(&cap->data);
300 301 302 303
                if (cap->data.scsi_host.flags &
                    VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST) {
                    if (STREQ(cap->data.scsi_host.wwnn, wwnn) &&
                        STREQ(cap->data.scsi_host.wwpn, wwpn)) {
304 305 306 307

                        if (virNodeDeviceLookupSCSIHostByWWNEnsureACL(conn, obj->def) < 0)
                            goto out;

308 309 310 311
                        if ((dev = virGetNodeDevice(conn, obj->def->name))) {
                            if (VIR_STRDUP(dev->parent, obj->def->parent) < 0)
                                virObjectUnref(dev);
                        }
312 313 314 315 316 317 318 319 320 321 322
                        virNodeDeviceObjUnlock(obj);
                        goto out;
                    }
                }
            }
            cap = cap->next;
        }

        virNodeDeviceObjUnlock(obj);
    }

323
 out:
324
    nodeDeviceUnlock();
325 326 327 328
    return dev;
}


329 330
char *
nodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
331
                     unsigned int flags)
332
{
333 334
    virNodeDeviceObjPtr obj;
    char *ret = NULL;
335

E
Eric Blake 已提交
336 337
    virCheckFlags(0, NULL);

338
    nodeDeviceLock();
339
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
340
    nodeDeviceUnlock();
341

342
    if (!obj) {
343 344 345
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
346
        goto cleanup;
347 348
    }

349 350 351
    if (virNodeDeviceGetXMLDescEnsureACL(dev->conn, obj->def) < 0)
        goto cleanup;

352
    update_driver_name(obj);
353 354
    if (update_caps(obj) < 0)
        goto cleanup;
355

356
    ret = virNodeDeviceDefFormat(obj->def);
357

358
 cleanup:
359 360
    if (obj)
        virNodeDeviceObjUnlock(obj);
361
    return ret;
362 363 364
}


365 366
char *
nodeDeviceGetParent(virNodeDevicePtr dev)
367
{
368 369
    virNodeDeviceObjPtr obj;
    char *ret = NULL;
370

371
    nodeDeviceLock();
372
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
373
    nodeDeviceUnlock();
374

375
    if (!obj) {
376 377 378
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
379
        goto cleanup;
380 381
    }

382 383 384
    if (virNodeDeviceGetParentEnsureACL(dev->conn, obj->def) < 0)
        goto cleanup;

385
    if (obj->def->parent) {
386 387
        if (VIR_STRDUP(ret, obj->def->parent) < 0)
            goto cleanup;
388
    } else {
389 390
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
391
    }
392

393
 cleanup:
394 395
    if (obj)
        virNodeDeviceObjUnlock(obj);
396
    return ret;
397 398 399
}


400 401
int
nodeDeviceNumOfCaps(virNodeDevicePtr dev)
402
{
403
    virNodeDeviceObjPtr obj;
404 405
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
406
    int ret = -1;
407

408
    nodeDeviceLock();
409
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
410
    nodeDeviceUnlock();
411

412
    if (!obj) {
413 414 415
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
416
        goto cleanup;
417 418
    }

419 420 421
    if (virNodeDeviceNumOfCapsEnsureACL(dev->conn, obj->def) < 0)
        goto cleanup;

422
    for (caps = obj->def->caps; caps; caps = caps->next) {
423
        ++ncaps;
424

425
        if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) {
426 427 428 429 430 431 432 433 434 435
            if (caps->data.scsi_host.flags &
                VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST)
                ncaps++;

            if (caps->data.scsi_host.flags &
                VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS)
                ncaps++;
        }
    }

436
    ret = ncaps;
437

438
 cleanup:
439 440
    if (obj)
        virNodeDeviceObjUnlock(obj);
441
    return ret;
442 443 444
}


445
int
446 447
nodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
448
    virNodeDeviceObjPtr obj;
449 450
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
451
    int ret = -1;
452

453
    nodeDeviceLock();
454
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
455
    nodeDeviceUnlock();
456

457
    if (!obj) {
458 459 460
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
461
        goto cleanup;
462 463
    }

464 465 466
    if (virNodeDeviceListCapsEnsureACL(dev->conn, obj->def) < 0)
        goto cleanup;

467
    for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) {
468
        if (VIR_STRDUP(names[ncaps++], virNodeDevCapTypeToString(caps->data.type)) < 0)
469
            goto cleanup;
470

471
        if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) {
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
            if (ncaps < maxnames &&
                caps->data.scsi_host.flags &
                VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST) {
                if (VIR_STRDUP(names[ncaps++],
                               virNodeDevCapTypeToString(VIR_NODE_DEV_CAP_FC_HOST)) < 0)
                    goto cleanup;
            }

            if (ncaps < maxnames &&
                caps->data.scsi_host.flags &
                VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS) {
                if (VIR_STRDUP(names[ncaps++],
                               virNodeDevCapTypeToString(VIR_NODE_DEV_CAP_VPORTS)) < 0)
                    goto cleanup;
            }
        }
488
    }
489
    ret = ncaps;
490

491
 cleanup:
492 493
    if (obj)
        virNodeDeviceObjUnlock(obj);
494 495 496 497 498 499
    if (ret == -1) {
        --ncaps;
        while (--ncaps >= 0)
            VIR_FREE(names[ncaps]);
    }
    return ret;
500 501
}

502
static int
503
get_time(time_t *t)
504 505 506 507 508
{
    int ret = 0;

    *t = time(NULL);
    if (*t == (time_t)-1) {
509 510
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("Could not get current time"));
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543

        *t = 0;
        ret = -1;
    }

    return ret;
}


/* When large numbers of devices are present on the host, it's
 * possible for udev not to realize that it has work to do before we
 * get here.  We thus keep trying to find the new device we just
 * created for up to LINUX_NEW_DEVICE_WAIT_TIME.  Note that udev's
 * default settle time is 180 seconds, so once udev realizes that it
 * has work to do, it might take that long for the udev wait to
 * return.  Thus the total maximum time for this function to return is
 * the udev settle time plus LINUX_NEW_DEVICE_WAIT_TIME.
 *
 * This whole area is a race, but if we retry the udev wait for
 * LINUX_NEW_DEVICE_WAIT_TIME seconds and there's still no device,
 * it's probably safe to assume it's not going to appear.
 */
static virNodeDevicePtr
find_new_device(virConnectPtr conn, const char *wwnn, const char *wwpn)
{
    virNodeDevicePtr dev = NULL;
    time_t start = 0, now = 0;

    /* The thread that creates the device takes the driver lock, so we
     * must release it in order to allow the device to be created.
     * We're not doing anything with the driver pointer at this point,
     * so it's safe to release it, assuming that the pointer itself
     * doesn't become invalid.  */
544
    nodeDeviceUnlock();
545

546
    get_time(&start);
547 548 549

    while ((now - start) < LINUX_NEW_DEVICE_WAIT_TIME) {

550
        virFileWaitForDevices();
551

552
        dev = nodeDeviceLookupSCSIHostByWWN(conn, wwnn, wwpn, 0);
553

554
        if (dev != NULL)
555 556 557
            break;

        sleep(5);
558
        if (get_time(&now) == -1)
559 560 561
            break;
    }

562
    nodeDeviceLock();
563 564 565 566

    return dev;
}

567
virNodeDevicePtr
568 569
nodeDeviceCreateXML(virConnectPtr conn,
                    const char *xmlDesc,
E
Eric Blake 已提交
570
                    unsigned int flags)
571 572 573 574 575
{
    virNodeDeviceDefPtr def = NULL;
    char *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;
    virNodeDevicePtr dev = NULL;
576
    const char *virt_type = NULL;
577

E
Eric Blake 已提交
578
    virCheckFlags(0, NULL);
579
    virt_type  = virConnectGetType(conn);
E
Eric Blake 已提交
580

581
    nodeDeviceLock();
582

583
    def = virNodeDeviceDefParseString(xmlDesc, CREATE_DEVICE, virt_type);
584
    if (def == NULL)
585 586
        goto cleanup;

587 588 589
    if (virNodeDeviceCreateXMLEnsureACL(conn, def) < 0)
        goto cleanup;

590
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1)
591 592
        goto cleanup;

593 594 595 596 597 598
    if (def->parent) {
        if (virNodeDeviceGetParentHost(&driver->devs,
                                       def->name,
                                       def->parent,
                                       &parent_host) < 0)
            goto cleanup;
599 600 601 602 603 604 605 606 607 608 609 610 611
    } else if (def->parent_wwnn && def->parent_wwpn) {
        if (virNodeDeviceGetParentHostByWWNs(&driver->devs,
                                             def->name,
                                             def->parent_wwnn,
                                             def->parent_wwpn,
                                             &parent_host) < 0)
            goto cleanup;
    } else if (def->parent_fabric_wwn) {
        if (virNodeDeviceGetParentHostByFabricWWN(&driver->devs,
                                                  def->name,
                                                  def->parent_fabric_wwn,
                                                  &parent_host) < 0)
            goto cleanup;
612 613 614 615
    } else {
        /* Try to find a vport capable scsi_host when no parent supplied */
        if (virNodeDeviceFindVportParentHost(&driver->devs, &parent_host) < 0)
            goto cleanup;
616 617
    }

618 619 620 621
    if (virManageVport(parent_host,
                       wwpn,
                       wwnn,
                       VPORT_CREATE) == -1) {
622 623 624 625 626 627 628
        goto cleanup;
    }

    dev = find_new_device(conn, wwnn, wwpn);
    /* We don't check the return value, because one way or another,
     * we're returning what we get... */

629
    if (dev == NULL)
630 631 632 633
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device for '%s' with matching "
                         "wwnn '%s' and wwpn '%s'"),
                       def->name, wwnn, wwpn);
634
 cleanup:
635
    nodeDeviceUnlock();
636 637 638 639 640 641 642
    virNodeDeviceDefFree(def);
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return dev;
}


643
int
644 645
nodeDeviceDestroy(virNodeDevicePtr dev)
{
D
David Allan 已提交
646
    int ret = -1;
647 648 649 650
    virNodeDeviceObjPtr obj = NULL;
    char *parent_name = NULL, *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;

651
    nodeDeviceLock();
652
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
653
    nodeDeviceUnlock();
654 655

    if (!obj) {
656 657 658
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
659 660 661
        goto out;
    }

662 663 664
    if (virNodeDeviceDestroyEnsureACL(dev->conn, obj->def) < 0)
        goto out;

665
    if (virNodeDeviceGetWWNs(obj->def, &wwnn, &wwpn) == -1)
666 667 668
        goto out;


669
    /* virNodeDeviceGetParentHost will cause the device object's lock to be
670 671 672
     * taken, so we have to dup the parent's name and drop the lock
     * before calling it.  We don't need the reference to the object
     * any more once we have the parent's name.  */
673 674 675
    if (VIR_STRDUP(parent_name, obj->def->parent) < 0) {
        virNodeDeviceObjUnlock(obj);
        obj = NULL;
676 677
        goto out;
    }
678 679
    virNodeDeviceObjUnlock(obj);
    obj = NULL;
680

681
    if (virNodeDeviceGetParentHost(&driver->devs,
682 683 684
                                   dev->name,
                                   parent_name,
                                   &parent_host) == -1) {
685 686 687
        goto out;
    }

688 689 690 691
    if (virManageVport(parent_host,
                       wwpn,
                       wwnn,
                       VPORT_DELETE) == -1) {
692 693 694
        goto out;
    }

D
David Allan 已提交
695
    ret = 0;
696
 out:
697 698
    if (obj)
        virNodeDeviceObjUnlock(obj);
699 700 701 702 703 704
    VIR_FREE(parent_name);
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return ret;
}

705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745
int
nodeConnectNodeDeviceEventRegisterAny(virConnectPtr conn,
                                      virNodeDevicePtr dev,
                                      int eventID,
                                      virConnectNodeDeviceEventGenericCallback callback,
                                      void *opaque,
                                      virFreeCallback freecb)
{
    int callbackID = -1;

    if (virConnectNodeDeviceEventRegisterAnyEnsureACL(conn) < 0)
        goto cleanup;

    if (virNodeDeviceEventStateRegisterID(conn, driver->nodeDeviceEventState,
                                          dev, eventID, callback,
                                          opaque, freecb, &callbackID) < 0)
        callbackID = -1;
 cleanup:
    return callbackID;
}

int
nodeConnectNodeDeviceEventDeregisterAny(virConnectPtr conn,
                                        int callbackID)
{
    int ret = -1;

    if (virConnectNodeDeviceEventDeregisterAnyEnsureACL(conn) < 0)
        goto cleanup;

    if (virObjectEventStateDeregisterID(conn,
                                        driver->nodeDeviceEventState,
                                        callbackID) < 0)
        goto cleanup;

    ret = 0;

 cleanup:
    return ret;
}

746 747
int nodedevRegister(void)
{
748 749
#ifdef WITH_UDEV
    return udevNodeRegister();
750
#else
751
# ifdef WITH_HAL
752
    return halNodeRegister();
753
# endif
754 755
#endif
}