node_device_driver.c 17.5 KB
Newer Older
1 2 3
/*
 * node_device.c: node device enumeration
 *
E
Eric Blake 已提交
4
 * Copyright (C) 2010-2011 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>
E
Eric Blake 已提交
31
#include <sys/stat.h>
32 33 34

#include "virterror_internal.h"
#include "datatypes.h"
35
#include "viralloc.h"
36
#include "virlog.h"
37
#include "node_device_conf.h"
38
#include "node_device_hal.h"
39
#include "node_device_driver.h"
D
Daniel P. Berrange 已提交
40
#include "util.h"
41

42 43
#define VIR_FROM_THIS VIR_FROM_NODEDEV

44 45 46 47 48 49

static int update_caps(virNodeDeviceObjPtr dev)
{
    virNodeDevCapsDefPtr cap = dev->def->caps;

    while (cap) {
50
        /* The only caps that currently need updating are FC related. */
51
        if (cap->type == VIR_NODE_DEV_CAP_SCSI_HOST) {
52
            check_fc_host(&dev->def->caps->data);
53
        }
54
        cap = cap->next;
55 56 57 58 59 60
    }

    return 0;
}


61 62 63 64
#if defined (__linux__) && defined (HAVE_HAL)
/* Under libudev changes to the driver name should be picked up as
 * "change" events, so we don't call update driver name unless we're
 * using the HAL backend. */
65
static int update_driver_name(virNodeDeviceObjPtr dev)
66 67
{
    char *driver_link = NULL;
68
    char *devpath = NULL;
69 70 71 72 73
    char *p;
    int ret = -1;

    VIR_FREE(dev->def->driver);

74
    if (virAsprintf(&driver_link, "%s/driver", dev->def->sysfs_path) < 0) {
75
        virReportOOMError();
76 77 78 79 80 81 82 83 84 85
        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;
    }

86
    if (virFileResolveLink(driver_link, &devpath) < 0) {
87
        virReportSystemError(errno,
88 89 90 91 92 93 94 95
                             _("cannot resolve driver link %s"), driver_link);
        goto cleanup;
    }

    p = strrchr(devpath, '/');
    if (p) {
        dev->def->driver = strdup(p+1);
        if (!dev->def->driver) {
96
            virReportOOMError();
97 98 99 100 101 102 103
            goto cleanup;
        }
    }
    ret = 0;

cleanup:
    VIR_FREE(driver_link);
104
    VIR_FREE(devpath);
105 106 107 108
    return ret;
}
#else
/* XXX: Implement me for non-linux */
109
static int update_driver_name(virNodeDeviceObjPtr dev ATTRIBUTE_UNUSED)
110 111 112 113 114
{
    return 0;
}
#endif

115

116 117
void nodeDeviceLock(virDeviceMonitorStatePtr driver)
{
118
    virMutexLock(&driver->lock);
119 120 121
}
void nodeDeviceUnlock(virDeviceMonitorStatePtr driver)
{
122
    virMutexUnlock(&driver->lock);
123 124
}

125 126 127
int
nodeNumOfDevices(virConnectPtr conn,
                 const char *cap,
E
Eric Blake 已提交
128
                 unsigned int flags)
129 130 131 132 133
{
    virDeviceMonitorStatePtr driver = conn->devMonPrivateData;
    int ndevs = 0;
    unsigned int i;

E
Eric Blake 已提交
134 135
    virCheckFlags(0, -1);

136 137 138
    nodeDeviceLock(driver);
    for (i = 0; i < driver->devs.count; i++) {
        virNodeDeviceObjLock(driver->devs.objs[i]);
139
        if ((cap == NULL) ||
140
            virNodeDeviceHasCap(driver->devs.objs[i], cap))
141
            ++ndevs;
142 143 144
        virNodeDeviceObjUnlock(driver->devs.objs[i]);
    }
    nodeDeviceUnlock(driver);
145 146 147 148

    return ndevs;
}

149
int
150 151 152
nodeListDevices(virConnectPtr conn,
                const char *cap,
                char **const names, int maxnames,
E
Eric Blake 已提交
153
                unsigned int flags)
154 155 156 157 158
{
    virDeviceMonitorStatePtr driver = conn->devMonPrivateData;
    int ndevs = 0;
    unsigned int i;

E
Eric Blake 已提交
159 160
    virCheckFlags(0, -1);

161 162 163
    nodeDeviceLock(driver);
    for (i = 0; i < driver->devs.count && ndevs < maxnames; i++) {
        virNodeDeviceObjLock(driver->devs.objs[i]);
164
        if (cap == NULL ||
165
            virNodeDeviceHasCap(driver->devs.objs[i], cap)) {
166 167
            if ((names[ndevs++] = strdup(driver->devs.objs[i]->def->name)) == NULL) {
                virNodeDeviceObjUnlock(driver->devs.objs[i]);
168
                virReportOOMError();
169
                goto failure;
170 171 172 173 174
            }
        }
        virNodeDeviceObjUnlock(driver->devs.objs[i]);
    }
    nodeDeviceUnlock(driver);
175 176 177 178

    return ndevs;

 failure:
179
    nodeDeviceUnlock(driver);
180 181 182 183 184 185
    --ndevs;
    while (--ndevs >= 0)
        VIR_FREE(names[ndevs]);
    return -1;
}

O
Osier Yang 已提交
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
int
nodeListAllNodeDevices(virConnectPtr conn,
                       virNodeDevicePtr **devices,
                       unsigned int flags)
{
    virDeviceMonitorStatePtr driver = conn->devMonPrivateData;
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_NODE_DEVICES_FILTERS_CAP, -1);

    nodeDeviceLock(driver);
    ret = virNodeDeviceList(conn, driver->devs, devices, flags);
    nodeDeviceUnlock(driver);
    return ret;
}
201

202 203
virNodeDevicePtr
nodeDeviceLookupByName(virConnectPtr conn, const char *name)
204 205
{
    virDeviceMonitorStatePtr driver = conn->devMonPrivateData;
206 207
    virNodeDeviceObjPtr obj;
    virNodeDevicePtr ret = NULL;
208

209
    nodeDeviceLock(driver);
210
    obj = virNodeDeviceFindByName(&driver->devs, name);
211 212
    nodeDeviceUnlock(driver);

213
    if (!obj) {
214
        virReportError(VIR_ERR_NO_NODE_DEVICE, NULL);
215
        goto cleanup;
216 217
    }

218
    ret = virGetNodeDevice(conn, name);
219

220
cleanup:
221 222
    if (obj)
        virNodeDeviceObjUnlock(obj);
223
    return ret;
224 225
}

226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249

static virNodeDevicePtr
nodeDeviceLookupByWWN(virConnectPtr conn,
                      const char *wwnn,
                      const char *wwpn)
{
    unsigned int i;
    virDeviceMonitorStatePtr driver = conn->devMonPrivateData;
    virNodeDeviceObjListPtr devs = &driver->devs;
    virNodeDevCapsDefPtr cap = NULL;
    virNodeDeviceObjPtr obj = NULL;
    virNodeDevicePtr dev = NULL;

    nodeDeviceLock(driver);

    for (i = 0; i < devs->count; i++) {

        obj = devs->objs[i];
        virNodeDeviceObjLock(obj);
        cap = obj->def->caps;

        while (cap) {

            if (cap->type == VIR_NODE_DEV_CAP_SCSI_HOST) {
250
                check_fc_host(&cap->data);
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
                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)) {
                        dev = virGetNodeDevice(conn, obj->def->name);
                        virNodeDeviceObjUnlock(obj);
                        goto out;
                    }
                }
            }
            cap = cap->next;
        }

        virNodeDeviceObjUnlock(obj);
    }

out:
    nodeDeviceUnlock(driver);
    return dev;
}


274 275
char *
nodeDeviceGetXMLDesc(virNodeDevicePtr dev,
E
Eric Blake 已提交
276
                     unsigned int flags)
277 278
{
    virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData;
279 280
    virNodeDeviceObjPtr obj;
    char *ret = NULL;
281

E
Eric Blake 已提交
282 283
    virCheckFlags(0, NULL);

284
    nodeDeviceLock(driver);
285
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
286 287
    nodeDeviceUnlock(driver);

288
    if (!obj) {
289 290 291
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
292
        goto cleanup;
293 294
    }

295
    update_driver_name(obj);
296 297
    update_caps(obj);

298
    ret = virNodeDeviceDefFormat(obj->def);
299 300

cleanup:
301 302
    if (obj)
        virNodeDeviceObjUnlock(obj);
303
    return ret;
304 305 306
}


307 308
char *
nodeDeviceGetParent(virNodeDevicePtr dev)
309 310
{
    virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData;
311 312
    virNodeDeviceObjPtr obj;
    char *ret = NULL;
313

314
    nodeDeviceLock(driver);
315
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
316 317
    nodeDeviceUnlock(driver);

318
    if (!obj) {
319 320 321
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
322
        goto cleanup;
323 324
    }

325 326 327
    if (obj->def->parent) {
        ret = strdup(obj->def->parent);
        if (!ret)
328
            virReportOOMError();
329
    } else {
330 331
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no parent for this device"));
332
    }
333 334

cleanup:
335 336
    if (obj)
        virNodeDeviceObjUnlock(obj);
337
    return ret;
338 339 340
}


341 342
int
nodeDeviceNumOfCaps(virNodeDevicePtr dev)
343 344
{
    virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData;
345
    virNodeDeviceObjPtr obj;
346 347
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
348
    int ret = -1;
349

350
    nodeDeviceLock(driver);
351
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
352 353
    nodeDeviceUnlock(driver);

354
    if (!obj) {
355 356 357
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
358
        goto cleanup;
359 360 361 362
    }

    for (caps = obj->def->caps; caps; caps = caps->next)
        ++ncaps;
363
    ret = ncaps;
364

365
cleanup:
366 367
    if (obj)
        virNodeDeviceObjUnlock(obj);
368
    return ret;
369 370 371
}


372
int
373 374 375
nodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames)
{
    virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData;
376
    virNodeDeviceObjPtr obj;
377 378
    virNodeDevCapsDefPtr caps;
    int ncaps = 0;
379
    int ret = -1;
380

381
    nodeDeviceLock(driver);
382
    obj = virNodeDeviceFindByName(&driver->devs, dev->name);
383 384
    nodeDeviceUnlock(driver);

385
    if (!obj) {
386 387 388
        virReportError(VIR_ERR_NO_NODE_DEVICE,
                       _("no node device with matching name '%s'"),
                       dev->name);
389
        goto cleanup;
390 391 392 393
    }

    for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) {
        names[ncaps] = strdup(virNodeDevCapTypeToString(caps->type));
394
        if (names[ncaps++] == NULL) {
395
            virReportOOMError();
396
            goto cleanup;
397
        }
398
    }
399
    ret = ncaps;
400

401
cleanup:
402 403
    if (obj)
        virNodeDeviceObjUnlock(obj);
404 405 406 407 408 409
    if (ret == -1) {
        --ncaps;
        while (--ncaps >= 0)
            VIR_FREE(names[ncaps]);
    }
    return ret;
410 411 412
}


413
static int
414
nodeDeviceVportCreateDelete(const int parent_host,
415 416 417 418 419 420 421
                            const char *wwpn,
                            const char *wwnn,
                            int operation)
{
    int retval = 0;
    char *operation_path = NULL, *vport_name = NULL;
    const char *operation_file = NULL;
422
    struct stat st;
423 424 425 426 427 428 429 430 431

    switch (operation) {
    case VPORT_CREATE:
        operation_file = LINUX_SYSFS_VPORT_CREATE_POSTFIX;
        break;
    case VPORT_DELETE:
        operation_file = LINUX_SYSFS_VPORT_DELETE_POSTFIX;
        break;
    default:
432 433
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Invalid vport operation (%d)"), operation);
434 435 436 437 438 439 440 441 442 443 444
        retval = -1;
        goto cleanup;
        break;
    }

    if (virAsprintf(&operation_path,
                    "%shost%d%s",
                    LINUX_SYSFS_FC_HOST_PREFIX,
                    parent_host,
                    operation_file) < 0) {

445
        virReportOOMError();
446 447 448 449
        retval = -1;
        goto cleanup;
    }

450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469
    if (stat(operation_path, &st) != 0) {
        VIR_FREE(operation_path);
        if (virAsprintf(&operation_path,
                        "%shost%d%s",
                        LINUX_SYSFS_SCSI_HOST_PREFIX,
                        parent_host,
                        operation_file) < 0) {
            virReportOOMError();
            retval = -1;
            goto cleanup;
        }

        if (stat(operation_path, &st) != 0) {
            VIR_ERROR(_("No vport operation path found for host%d"),
                      parent_host);
            retval = -1;
            goto cleanup;
        }
    }

470
    VIR_DEBUG("Vport operation path is '%s'", operation_path);
471 472 473 474 475 476

    if (virAsprintf(&vport_name,
                    "%s:%s",
                    wwpn,
                    wwnn) < 0) {

477
        virReportOOMError();
478 479 480 481
        retval = -1;
        goto cleanup;
    }

482
    if (virFileWriteStr(operation_path, vport_name, 0) == -1) {
483
        virReportSystemError(errno,
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
                             _("Write of '%s' to '%s' during "
                               "vport create/delete failed"),
                             vport_name, operation_path);
        retval = -1;
    }

cleanup:
    VIR_FREE(vport_name);
    VIR_FREE(operation_path);
    VIR_DEBUG("%s", _("Vport operation complete"));
    return retval;
}


static int
499
get_time(time_t *t)
500 501 502 503 504
{
    int ret = 0;

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

        *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)
{
    virDeviceMonitorStatePtr driver = conn->devMonPrivateData;
    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.  */
    nodeDeviceUnlock(driver);

543
    get_time(&start);
544 545 546

    while ((now - start) < LINUX_NEW_DEVICE_WAIT_TIME) {

547
        virFileWaitForDevices();
548 549 550 551 552 553 554 555

        dev = nodeDeviceLookupByWWN(conn, wwnn, wwpn);

        if (dev != NULL) {
            break;
        }

        sleep(5);
556
        if (get_time(&now) == -1) {
557 558 559 560 561 562 563 564 565
            break;
        }
    }

    nodeDeviceLock(driver);

    return dev;
}

566
virNodeDevicePtr
567 568
nodeDeviceCreateXML(virConnectPtr conn,
                    const char *xmlDesc,
E
Eric Blake 已提交
569
                    unsigned int flags)
570 571 572 573 574 575
{
    virDeviceMonitorStatePtr driver = conn->devMonPrivateData;
    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 582
    nodeDeviceLock(driver);

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

588
    if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1) {
589 590 591
        goto cleanup;
    }

592
    if (virNodeDeviceGetParentHost(&driver->devs,
593 594 595
                                   def->name,
                                   def->parent,
                                   &parent_host) == -1) {
596 597 598
        goto cleanup;
    }

599
    if (nodeDeviceVportCreateDelete(parent_host,
600 601 602 603 604 605 606 607 608 609 610
                                    wwpn,
                                    wwnn,
                                    VPORT_CREATE) == -1) {
        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... */

    if (dev == NULL) {
611
        virReportError(VIR_ERR_NO_NODE_DEVICE, NULL);
612 613 614 615 616 617 618 619 620 621 622
    }

cleanup:
    nodeDeviceUnlock(driver);
    virNodeDeviceDefFree(def);
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return dev;
}


623
int
624 625
nodeDeviceDestroy(virNodeDevicePtr dev)
{
D
David Allan 已提交
626
    int ret = -1;
627 628 629 630 631 632 633 634 635 636
    virDeviceMonitorStatePtr driver = dev->conn->devMonPrivateData;
    virNodeDeviceObjPtr obj = NULL;
    char *parent_name = NULL, *wwnn = NULL, *wwpn = NULL;
    int parent_host = -1;

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

    if (!obj) {
637
        virReportError(VIR_ERR_NO_NODE_DEVICE, NULL);
638 639 640
        goto out;
    }

641
    if (virNodeDeviceGetWWNs(obj->def, &wwnn, &wwpn) == -1) {
642 643 644 645 646
        goto out;
    }

    parent_name = strdup(obj->def->parent);

647
    /* virNodeDeviceGetParentHost will cause the device object's lock to be
648 649 650 651 652 653 654
     * 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.  */
    virNodeDeviceObjUnlock(obj);
    obj = NULL;

    if (parent_name == NULL) {
655
        virReportOOMError();
656 657 658
        goto out;
    }

659
    if (virNodeDeviceGetParentHost(&driver->devs,
660 661 662
                                   dev->name,
                                   parent_name,
                                   &parent_host) == -1) {
663 664 665
        goto out;
    }

666
    if (nodeDeviceVportCreateDelete(parent_host,
667 668 669 670 671 672
                                    wwpn,
                                    wwnn,
                                    VPORT_DELETE) == -1) {
        goto out;
    }

D
David Allan 已提交
673
    ret = 0;
674
out:
675 676
    if (obj)
        virNodeDeviceObjUnlock(obj);
677 678 679 680 681 682
    VIR_FREE(parent_name);
    VIR_FREE(wwnn);
    VIR_FREE(wwpn);
    return ret;
}

683
int nodedevRegister(void) {
684
#if defined(HAVE_HAL) && defined(HAVE_UDEV)
685
    /* Register only one of these two - they conflict */
686 687
    if (udevNodeRegister() == -1)
        return halNodeRegister();
688 689
    return 0;
#else
690
# ifdef HAVE_HAL
691
    return halNodeRegister();
692 693
# endif
# ifdef HAVE_UDEV
694
    return udevNodeRegister();
695
# endif
696 697
#endif
}