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
        /* all types that (supposedly) don't require any updates
         * relative to what's in the cache.
         */
M
Marc-André Lureau 已提交
75
        case VIR_NODE_DEV_CAP_DRM:
76 77 78 79 80 81 82 83 84 85 86 87
        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;
        }
88
        cap = cap->next;
89 90 91 92 93 94
    }

    return 0;
}


95 96 97 98 99 100 101 102 103
#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.
 */
104
static int update_driver_name(virNodeDeviceObjPtr dev)
105 106
{
    char *driver_link = NULL;
107
    char *devpath = NULL;
108 109 110 111 112
    char *p;
    int ret = -1;

    VIR_FREE(dev->def->driver);

113
    if (virAsprintf(&driver_link, "%s/driver", dev->def->sysfs_path) < 0)
114 115 116 117 118 119 120 121 122
        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;
    }

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

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

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

147

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

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

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

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

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

    return ndevs;
}

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

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

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

199
    nodeDeviceLock();
200
    for (i = 0; i < driver->devs.count && ndevs < maxnames; i++) {
201 202 203 204 205 206 207
        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);
208
                goto failure;
209 210
            }
        }
211
        virNodeDeviceObjUnlock(obj);
212
    }
213
    nodeDeviceUnlock();
214 215 216 217

    return ndevs;

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

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

    virCheckFlags(VIR_CONNECT_LIST_NODE_DEVICES_FILTERS_CAP, -1);

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

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

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

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

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

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

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

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

276

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

289 290
    virCheckFlags(0, NULL);

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

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

        while (cap) {
299
            if (cap->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) {
300
                nodeDeviceSysfsGetSCSIHostCaps(&cap->data);
301 302 303 304
                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)) {
305 306 307 308

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

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

        virNodeDeviceObjUnlock(obj);
    }

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


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

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

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

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

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

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

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

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


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

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

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

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

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

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


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

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

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

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

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

426
        if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) {
427 428 429 430 431 432 433 434 435 436
            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++;
        }
    }

437
    ret = ncaps;
438

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


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

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

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

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

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

472
        if (caps->data.type == VIR_NODE_DEV_CAP_SCSI_HOST) {
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
            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;
            }
        }
489
    }
490
    ret = ncaps;
491

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

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

    *t = time(NULL);
    if (*t == (time_t)-1) {
510 511
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("Could not get current time"));
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 544

        *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.  */
545
    nodeDeviceUnlock();
546

547
    get_time(&start);
548 549 550

    while ((now - start) < LINUX_NEW_DEVICE_WAIT_TIME) {

551
        virFileWaitForDevices();
552

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

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

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

563
    nodeDeviceLock();
564 565 566 567

    return dev;
}

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

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

582
    nodeDeviceLock();
583

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

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

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

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

619 620 621 622
    if (virManageVport(parent_host,
                       wwpn,
                       wwnn,
                       VPORT_CREATE) == -1) {
623 624 625 626 627 628 629
        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... */

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


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

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

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

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

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


670
    /* virNodeDeviceGetParentHost will cause the device object's lock to be
671 672 673
     * 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.  */
674 675 676
    if (VIR_STRDUP(parent_name, obj->def->parent) < 0) {
        virNodeDeviceObjUnlock(obj);
        obj = NULL;
677 678
        goto out;
    }
679 680
    virNodeDeviceObjUnlock(obj);
    obj = NULL;
681

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

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

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

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 746
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;
}

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