storage_driver.c 50.7 KB
Newer Older
1 2 3
/*
 * storage_driver.c: core driver for storage APIs
 *
4
 * Copyright (C) 2006-2009 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 * Copyright (C) 2006-2008 Daniel P. Berrange
 *
 * 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
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 */

#include <config.h>

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
R
Richard W.M. Jones 已提交
29
#if HAVE_PWD_H
30
#include <pwd.h>
R
Richard W.M. Jones 已提交
31
#endif
32 33 34
#include <errno.h>
#include <string.h>

35
#include "virterror_internal.h"
36
#include "datatypes.h"
37 38 39 40
#include "driver.h"
#include "util.h"
#include "storage_driver.h"
#include "storage_conf.h"
41
#include "memory.h"
42 43
#include "storage_backend.h"

44 45
#define VIR_FROM_THIS VIR_FROM_STORAGE

46 47 48 49 50 51
#define storageLog(msg...) fprintf(stderr, msg)

static virStorageDriverStatePtr driverState;

static int storageDriverShutdown(void);

52 53
static void storageDriverLock(virStorageDriverStatePtr driver)
{
54
    virMutexLock(&driver->lock);
55 56 57
}
static void storageDriverUnlock(virStorageDriverStatePtr driver)
{
58
    virMutexUnlock(&driver->lock);
59
}
60 61 62

static void
storageDriverAutostart(virStorageDriverStatePtr driver) {
63
    unsigned int i;
64

65 66
    for (i = 0 ; i < driver->pools.count ; i++) {
        virStoragePoolObjPtr pool = driver->pools.objs[i];
67

68
        virStoragePoolObjLock(pool);
69 70 71 72 73 74
        if (pool->autostart &&
            !virStoragePoolObjIsActive(pool)) {
            virStorageBackendPtr backend;
            if ((backend = virStorageBackendForType(pool->def->type)) == NULL) {
                storageLog("Missing backend %d",
                           pool->def->type);
75
                virStoragePoolObjUnlock(pool);
76 77 78 79 80 81 82
                continue;
            }

            if (backend->startPool &&
                backend->startPool(NULL, pool) < 0) {
                virErrorPtr err = virGetLastError();
                storageLog("Failed to autostart storage pool '%s': %s",
83 84
                           pool->def->name, err ? err->message :
                           "no error message found");
85
                virStoragePoolObjUnlock(pool);
86 87 88 89 90 91 92 93
                continue;
            }

            if (backend->refreshPool(NULL, pool) < 0) {
                virErrorPtr err = virGetLastError();
                if (backend->stopPool)
                    backend->stopPool(NULL, pool);
                storageLog("Failed to autostart storage pool '%s': %s",
94 95
                           pool->def->name, err ? err->message :
                           "no error message found");
96
                virStoragePoolObjUnlock(pool);
97 98 99 100
                continue;
            }
            pool->active = 1;
        }
101
        virStoragePoolObjUnlock(pool);
102 103 104 105 106 107 108 109 110
    }
}

/**
 * virStorageStartup:
 *
 * Initialization function for the QEmu daemon
 */
static int
111
storageDriverStartup(int privileged) {
112 113 114
    char *base = NULL;
    char driverConf[PATH_MAX];

115
    if (VIR_ALLOC(driverState) < 0)
116 117
        return -1;

118 119 120 121
    if (virMutexInit(&driverState->lock) < 0) {
        VIR_FREE(driverState);
        return -1;
    }
122 123
    storageDriverLock(driverState);

124
    if (privileged) {
125 126 127
        if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
            goto out_of_memory;
    } else {
128
        uid_t uid = geteuid();
129 130 131 132
        char *userdir = virGetUserDirectory(NULL, uid);

        if (!userdir)
            goto error;
133

134
        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
135
            storageLog("out of memory in virAsprintf");
136
            VIR_FREE(userdir);
137 138
            goto out_of_memory;
        }
139
        VIR_FREE(userdir);
140 141 142 143 144 145 146 147 148 149
    }

    /* Configuration paths are either ~/.libvirt/storage/... (session) or
     * /etc/libvirt/storage/... (system).
     */
    if (snprintf (driverConf, sizeof(driverConf),
                  "%s/storage.conf", base) == -1)
        goto out_of_memory;
    driverConf[sizeof(driverConf)-1] = '\0';

150 151
    if (virAsprintf(&driverState->configDir,
                    "%s/storage", base) == -1)
152 153
        goto out_of_memory;

154 155
    if (virAsprintf(&driverState->autostartDir,
                    "%s/storage/autostart", base) == -1)
156 157
        goto out_of_memory;

158
    VIR_FREE(base);
159 160 161 162 163 164 165 166

    /*
    if (virStorageLoadDriverConfig(driver, driverConf) < 0) {
        virStorageDriverShutdown();
        return -1;
    }
    */

167 168 169
    if (virStoragePoolLoadAllConfigs(NULL,
                                     &driverState->pools,
                                     driverState->configDir,
170 171
                                     driverState->autostartDir) < 0)
        goto error;
172 173
    storageDriverAutostart(driverState);

174
    storageDriverUnlock(driverState);
175 176
    return 0;

177
out_of_memory:
178
    storageLog("virStorageStartup: out of memory");
179 180 181 182
error:
    VIR_FREE(base);
    storageDriverUnlock(driverState);
    storageDriverShutdown();
183 184 185 186 187 188 189 190 191 192 193
    return -1;
}

/**
 * virStorageReload:
 *
 * Function to restart the storage driver, it will recheck the configuration
 * files and update its state
 */
static int
storageDriverReload(void) {
194 195 196
    if (!driverState)
        return -1;

197
    storageDriverLock(driverState);
198 199 200 201
    virStoragePoolLoadAllConfigs(NULL,
                                 &driverState->pools,
                                 driverState->configDir,
                                 driverState->autostartDir);
202
    storageDriverAutostart(driverState);
203
    storageDriverUnlock(driverState);
204 205 206 207 208 209 210 211 212 213 214 215 216

    return 0;
}

/**
 * virStorageActive:
 *
 * Checks if the storage driver is active, i.e. has an active pool
 *
 * Returns 1 if active, 0 otherwise
 */
static int
storageDriverActive(void) {
217
    unsigned int i;
218
    int active = 0;
219 220 221 222

    if (!driverState)
        return 0;

223 224 225 226
    storageDriverLock(driverState);

    for (i = 0 ; i < driverState->pools.count ; i++) {
        virStoragePoolObjLock(driverState->pools.objs[i]);
227
        if (virStoragePoolObjIsActive(driverState->pools.objs[i]))
228 229 230
            active = 1;
        virStoragePoolObjUnlock(driverState->pools.objs[i]);
    }
231

232 233
    storageDriverUnlock(driverState);
    return active;
234 235 236 237 238 239 240 241 242 243 244 245
}

/**
 * virStorageShutdown:
 *
 * Shutdown the storage driver, it will stop all active storage pools
 */
static int
storageDriverShutdown(void) {
    if (!driverState)
        return -1;

246
    storageDriverLock(driverState);
247 248

    /* free inactive pools */
249 250 251 252
    virStoragePoolObjListFree(&driverState->pools);

    VIR_FREE(driverState->configDir);
    VIR_FREE(driverState->autostartDir);
253
    storageDriverUnlock(driverState);
254
    virMutexDestroy(&driverState->lock);
255
    VIR_FREE(driverState);
256 257 258 259 260 261 262 263 264

    return 0;
}



static virStoragePoolPtr
storagePoolLookupByUUID(virConnectPtr conn,
                        const unsigned char *uuid) {
265 266 267
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
268

269
    storageDriverLock(driver);
270
    pool = virStoragePoolObjFindByUUID(&driver->pools, uuid);
271 272
    storageDriverUnlock(driver);

273 274
    if (!pool) {
        virStorageReportError(conn, VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
275
                              "%s", _("no pool with matching uuid"));
276
        goto cleanup;
277 278 279
    }

    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
280 281

cleanup:
282 283
    if (pool)
        virStoragePoolObjUnlock(pool);
284 285 286 287 288 289
    return ret;
}

static virStoragePoolPtr
storagePoolLookupByName(virConnectPtr conn,
                        const char *name) {
290 291 292
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
293

294
    storageDriverLock(driver);
295
    pool = virStoragePoolObjFindByName(&driver->pools, name);
296 297
    storageDriverUnlock(driver);

298 299
    if (!pool) {
        virStorageReportError(conn, VIR_ERR_NO_STORAGE_POOL,
300
                              _("no pool with matching name '%s'"), name);
301
        goto cleanup;
302 303 304
    }

    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
305 306

cleanup:
307 308
    if (pool)
        virStoragePoolObjUnlock(pool);
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
    return ret;
}

static virStoragePoolPtr
storagePoolLookupByVolume(virStorageVolPtr vol) {
    return storagePoolLookupByName(vol->conn, vol->pool);
}

static virDrvOpenStatus
storageOpen(virConnectPtr conn,
            virConnectAuthPtr auth ATTRIBUTE_UNUSED,
            int flags ATTRIBUTE_UNUSED) {
    if (!driverState)
        return VIR_DRV_OPEN_DECLINED;

    conn->storagePrivateData = driverState;
    return VIR_DRV_OPEN_SUCCESS;
}

static int
storageClose(virConnectPtr conn) {
    conn->storagePrivateData = NULL;
    return 0;
}

static int
storageNumPools(virConnectPtr conn) {
336
    virStorageDriverStatePtr driver = conn->storagePrivateData;
337 338
    unsigned int i, nactive = 0;

339 340 341
    storageDriverLock(driver);
    for (i = 0 ; i < driver->pools.count ; i++) {
        virStoragePoolObjLock(driver->pools.objs[i]);
342 343
        if (virStoragePoolObjIsActive(driver->pools.objs[i]))
            nactive++;
344 345 346
        virStoragePoolObjUnlock(driver->pools.objs[i]);
    }
    storageDriverUnlock(driver);
347 348

    return nactive;
349 350 351 352 353 354
}

static int
storageListPools(virConnectPtr conn,
                 char **const names,
                 int nnames) {
355
    virStorageDriverStatePtr driver = conn->storagePrivateData;
356
    int got = 0, i;
357

358
    storageDriverLock(driver);
359
    for (i = 0 ; i < driver->pools.count && got < nnames ; i++) {
360
        virStoragePoolObjLock(driver->pools.objs[i]);
361 362
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
            if (!(names[got] = strdup(driver->pools.objs[i]->def->name))) {
363
                virStoragePoolObjUnlock(driver->pools.objs[i]);
364
                virReportOOMError(conn);
365 366 367 368
                goto cleanup;
            }
            got++;
        }
369
        virStoragePoolObjUnlock(driver->pools.objs[i]);
370
    }
371
    storageDriverUnlock(driver);
372 373 374
    return got;

 cleanup:
375 376 377
    storageDriverUnlock(driver);
    for (i = 0 ; i < got ; i++)
        VIR_FREE(names[i]);
378
    memset(names, 0, nnames * sizeof(*names));
379 380 381 382 383
    return -1;
}

static int
storageNumDefinedPools(virConnectPtr conn) {
384
    virStorageDriverStatePtr driver = conn->storagePrivateData;
385 386
    unsigned int i, nactive = 0;

387 388 389
    storageDriverLock(driver);
    for (i = 0 ; i < driver->pools.count ; i++) {
        virStoragePoolObjLock(driver->pools.objs[i]);
390 391
        if (!virStoragePoolObjIsActive(driver->pools.objs[i]))
            nactive++;
392 393 394
        virStoragePoolObjUnlock(driver->pools.objs[i]);
    }
    storageDriverUnlock(driver);
395 396

    return nactive;
397 398 399 400 401 402
}

static int
storageListDefinedPools(virConnectPtr conn,
                        char **const names,
                        int nnames) {
403
    virStorageDriverStatePtr driver = conn->storagePrivateData;
404
    int got = 0, i;
405

406
    storageDriverLock(driver);
407
    for (i = 0 ; i < driver->pools.count && got < nnames ; i++) {
408
        virStoragePoolObjLock(driver->pools.objs[i]);
409 410
        if (!virStoragePoolObjIsActive(driver->pools.objs[i])) {
            if (!(names[got] = strdup(driver->pools.objs[i]->def->name))) {
411
                virStoragePoolObjUnlock(driver->pools.objs[i]);
412
                virReportOOMError(conn);
413 414 415 416
                goto cleanup;
            }
            got++;
        }
417
        virStoragePoolObjUnlock(driver->pools.objs[i]);
418
    }
419
    storageDriverUnlock(driver);
420 421 422
    return got;

 cleanup:
423
    storageDriverUnlock(driver);
424 425 426 427
    for (i = 0 ; i < got ; i++) {
        free(names[i]);
        names[i] = NULL;
    }
428
    memset(names, 0, nnames * sizeof(*names));
429 430 431
    return -1;
}

432 433
/* This method is required to be re-entrant / thread safe, so
   uses no driver lock */
434 435 436 437 438 439 440 441
static char *
storageFindPoolSources(virConnectPtr conn,
                       const char *type,
                       const char *srcSpec,
                       unsigned int flags)
{
    int backend_type;
    virStorageBackendPtr backend;
442
    char *ret = NULL;
443

444
    backend_type = virStoragePoolTypeFromString(type);
445 446 447
    if (backend_type < 0) {
        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
                              _("unknown storage pool type %s"), type);
448
        goto cleanup;
449
    }
450 451 452

    backend = virStorageBackendForType(backend_type);
    if (backend == NULL)
453
        goto cleanup;
454

455 456 457 458 459 460 461 462
    if (!backend->findPoolSources) {
        virStorageReportError(conn, VIR_ERR_NO_SUPPORT,
                              _("pool type '%s' does not support source "
                                "discovery"), type);
        goto cleanup;
    }

    ret = backend->findPoolSources(conn, srcSpec, flags);
463

464 465
cleanup:
    return ret;
466 467 468
}


469 470 471 472
static virStoragePoolPtr
storagePoolCreate(virConnectPtr conn,
                  const char *xml,
                  unsigned int flags ATTRIBUTE_UNUSED) {
473
    virStorageDriverStatePtr driver = conn->storagePrivateData;
474
    virStoragePoolDefPtr def;
475
    virStoragePoolObjPtr pool = NULL;
476
    virStoragePoolPtr ret = NULL;
477 478
    virStorageBackendPtr backend;

479
    storageDriverLock(driver);
480
    if (!(def = virStoragePoolDefParseString(conn, xml)))
481
        goto cleanup;
482

483 484 485 486 487
    pool = virStoragePoolObjFindByUUID(&driver->pools, def->uuid);
    if (!pool)
        pool = virStoragePoolObjFindByName(&driver->pools, def->name);

    if (pool) {
488
        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
489
                              "%s", _("storage pool already exists"));
490 491
        virStoragePoolObjUnlock(pool);
        pool = NULL;
492
        goto cleanup;
493 494
    }

495 496
    if ((backend = virStorageBackendForType(def->type)) == NULL)
        goto cleanup;
497

498 499 500
    if (!(pool = virStoragePoolObjAssignDef(conn, &driver->pools, def)))
        goto cleanup;
    def = NULL;
501

502
    if (backend->startPool &&
503 504 505
        backend->startPool(conn, pool) < 0) {
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
506
        goto cleanup;
507
    }
508

509 510 511
    if (backend->refreshPool(conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(conn, pool);
512 513
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
514
        goto cleanup;
515 516 517 518 519
    }
    pool->active = 1;

    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);

520 521
cleanup:
    virStoragePoolDefFree(def);
522
    if (pool)
523
        virStoragePoolObjUnlock(pool);
524
    storageDriverUnlock(driver);
525 526 527 528 529 530 531
    return ret;
}

static virStoragePoolPtr
storagePoolDefine(virConnectPtr conn,
                  const char *xml,
                  unsigned int flags ATTRIBUTE_UNUSED) {
532
    virStorageDriverStatePtr driver = conn->storagePrivateData;
533
    virStoragePoolDefPtr def;
534
    virStoragePoolObjPtr pool = NULL;
535
    virStoragePoolPtr ret = NULL;
536

537
    storageDriverLock(driver);
538
    if (!(def = virStoragePoolDefParseString(conn, xml)))
539
        goto cleanup;
540

541
    if (virStorageBackendForType(def->type) == NULL)
542
        goto cleanup;
543

544 545
    if (!(pool = virStoragePoolObjAssignDef(conn, &driver->pools, def)))
        goto cleanup;
546 547

    if (virStoragePoolObjSaveDef(conn, driver, pool, def) < 0) {
548
        virStoragePoolObjRemove(&driver->pools, pool);
549
        def = NULL;
550
        goto cleanup;
551
    }
552
    def = NULL;
553 554

    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
555 556 557

cleanup:
    virStoragePoolDefFree(def);
558 559 560
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
561 562 563 564 565
    return ret;
}

static int
storagePoolUndefine(virStoragePoolPtr obj) {
566 567 568
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
569

570
    storageDriverLock(driver);
571
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
572 573
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
574
                              "%s", _("no storage pool with matching uuid"));
575
        goto cleanup;
576 577 578 579
    }

    if (virStoragePoolObjIsActive(pool)) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
580
                              "%s", _("pool is still active"));
581
        goto cleanup;
582 583
    }

584 585 586 587 588 589 590
    if (pool->asyncjobs > 0) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
                              _("pool '%s' has asynchronous jobs running."),
                              pool->def->name);
        goto cleanup;
    }

591
    if (virStoragePoolObjDeleteDef(obj->conn, pool) < 0)
592
        goto cleanup;
593

594 595
    if (unlink(pool->autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
        char ebuf[1024];
596
        storageLog("Failed to delete autostart link '%s': %s",
597 598
                   pool->autostartLink, virStrerror(errno, ebuf, sizeof ebuf));
    }
599

600 601
    VIR_FREE(pool->configFile);
    VIR_FREE(pool->autostartLink);
602

603
    virStoragePoolObjRemove(&driver->pools, pool);
604
    pool = NULL;
605
    ret = 0;
606

607
cleanup:
608 609 610
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
611
    return ret;
612 613 614 615 616
}

static int
storagePoolStart(virStoragePoolPtr obj,
                 unsigned int flags ATTRIBUTE_UNUSED) {
617 618
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
619
    virStorageBackendPtr backend;
620
    int ret = -1;
621

622
    storageDriverLock(driver);
623
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
624 625
    storageDriverUnlock(driver);

626 627
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
628
                              "%s", _("no storage pool with matching uuid"));
629
        goto cleanup;
630 631
    }

632 633
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
634 635 636

    if (virStoragePoolObjIsActive(pool)) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
637
                              "%s", _("pool already active"));
638
        goto cleanup;
639 640 641
    }
    if (backend->startPool &&
        backend->startPool(obj->conn, pool) < 0)
642 643
        goto cleanup;

644 645 646
    if (backend->refreshPool(obj->conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(obj->conn, pool);
647
        goto cleanup;
648 649 650
    }

    pool->active = 1;
651
    ret = 0;
652

653
cleanup:
654 655
    if (pool)
        virStoragePoolObjUnlock(pool);
656
    return ret;
657 658 659 660 661
}

static int
storagePoolBuild(virStoragePoolPtr obj,
                 unsigned int flags) {
662 663
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
664
    virStorageBackendPtr backend;
665
    int ret = -1;
666

667
    storageDriverLock(driver);
668
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
669 670
    storageDriverUnlock(driver);

671 672
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
673
                              "%s", _("no storage pool with matching uuid"));
674
        goto cleanup;
675 676
    }

677 678
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
679 680 681

    if (virStoragePoolObjIsActive(pool)) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
682
                              "%s", _("storage pool is already active"));
683
        goto cleanup;
684 685 686 687
    }

    if (backend->buildPool &&
        backend->buildPool(obj->conn, pool, flags) < 0)
688 689
        goto cleanup;
    ret = 0;
690

691
cleanup:
692 693
    if (pool)
        virStoragePoolObjUnlock(pool);
694
    return ret;
695 696 697 698 699
}


static int
storagePoolDestroy(virStoragePoolPtr obj) {
700 701
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
702
    virStorageBackendPtr backend;
703
    int ret = -1;
704

705
    storageDriverLock(driver);
706
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
707

708 709
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
710
                              "%s", _("no storage pool with matching uuid"));
711
        goto cleanup;
712 713
    }

714 715
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
716 717 718

    if (!virStoragePoolObjIsActive(pool)) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
719
                              "%s", _("storage pool is not active"));
720
        goto cleanup;
721 722
    }

723 724 725 726 727 728 729
    if (pool->asyncjobs > 0) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
                              _("pool '%s' has asynchronous jobs running."),
                              pool->def->name);
        goto cleanup;
    }

730 731
    if (backend->stopPool &&
        backend->stopPool(obj->conn, pool) < 0)
732
        goto cleanup;
733 734 735 736 737

    virStoragePoolObjClearVols(pool);

    pool->active = 0;

738
    if (pool->configFile == NULL) {
739
        virStoragePoolObjRemove(&driver->pools, pool);
740 741
        pool = NULL;
    }
742
    ret = 0;
743

744
cleanup:
745 746 747
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
748
    return ret;
749 750 751 752 753 754
}


static int
storagePoolDelete(virStoragePoolPtr obj,
                  unsigned int flags) {
755 756
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
757
    virStorageBackendPtr backend;
758
    int ret = -1;
759

760
    storageDriverLock(driver);
761
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
762 763
    storageDriverUnlock(driver);

764 765
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
766
                              "%s", _("no storage pool with matching uuid"));
767
        goto cleanup;
768 769
    }

770 771
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
772 773 774

    if (virStoragePoolObjIsActive(pool)) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
775
                              "%s", _("storage pool is still active"));
776
        goto cleanup;
777 778
    }

779 780 781 782 783 784 785
    if (pool->asyncjobs > 0) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
                              _("pool '%s' has asynchronous jobs running."),
                              pool->def->name);
        goto cleanup;
    }

786 787
    if (!backend->deletePool) {
        virStorageReportError(obj->conn, VIR_ERR_NO_SUPPORT,
J
Jim Meyering 已提交
788
                              "%s", _("pool does not support volume delete"));
789
        goto cleanup;
790 791
    }
    if (backend->deletePool(obj->conn, pool, flags) < 0)
792 793
        goto cleanup;
    ret = 0;
794

795
cleanup:
796 797
    if (pool)
        virStoragePoolObjUnlock(pool);
798
    return ret;
799 800 801 802 803 804
}


static int
storagePoolRefresh(virStoragePoolPtr obj,
                   unsigned int flags ATTRIBUTE_UNUSED) {
805 806
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
807
    virStorageBackendPtr backend;
808
    int ret = -1;
809

810
    storageDriverLock(driver);
811
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
812

813 814
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
815
                              "%s", _("no storage pool with matching uuid"));
816
        goto cleanup;
817 818
    }

819 820
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
821 822 823

    if (!virStoragePoolObjIsActive(pool)) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
824
                              "%s", _("storage pool is not active"));
825
        goto cleanup;
826 827
    }

828 829 830 831 832 833 834
    if (pool->asyncjobs > 0) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
                              _("pool '%s' has asynchronous jobs running."),
                              pool->def->name);
        goto cleanup;
    }

835
    virStoragePoolObjClearVols(pool);
836
    if (backend->refreshPool(obj->conn, pool) < 0) {
837 838 839 840 841
        if (backend->stopPool)
            backend->stopPool(obj->conn, pool);

        pool->active = 0;

842
        if (pool->configFile == NULL) {
843
            virStoragePoolObjRemove(&driver->pools, pool);
844 845
            pool = NULL;
        }
846
        goto cleanup;
847
    }
848
    ret = 0;
849

850
cleanup:
851 852
    if (pool)
        virStoragePoolObjUnlock(pool);
853
    storageDriverUnlock(driver);
854 855 856 857 858 859 860
    return ret;
}


static int
storagePoolGetInfo(virStoragePoolPtr obj,
                   virStoragePoolInfoPtr info) {
861 862 863
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
864

865
    storageDriverLock(driver);
866
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
867 868
    storageDriverUnlock(driver);

869 870
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
871
                              "%s", _("no storage pool with matching uuid"));
872
        goto cleanup;
873 874
    }

875
    if (virStorageBackendForType(pool->def->type) == NULL)
876
        goto cleanup;
877 878 879 880 881 882 883 884 885

    memset(info, 0, sizeof(virStoragePoolInfo));
    if (pool->active)
        info->state = VIR_STORAGE_POOL_RUNNING;
    else
        info->state = VIR_STORAGE_POOL_INACTIVE;
    info->capacity = pool->def->capacity;
    info->allocation = pool->def->allocation;
    info->available = pool->def->available;
886
    ret = 0;
887

888
cleanup:
889 890
    if (pool)
        virStoragePoolObjUnlock(pool);
891
    return ret;
892 893 894 895 896
}

static char *
storagePoolDumpXML(virStoragePoolPtr obj,
                   unsigned int flags ATTRIBUTE_UNUSED) {
897 898 899
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    char *ret = NULL;
900

901
    storageDriverLock(driver);
902
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
903 904
    storageDriverUnlock(driver);

905 906
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
907
                              "%s", _("no storage pool with matching uuid"));
908
        goto cleanup;
909 910
    }

911 912 913
    ret = virStoragePoolDefFormat(obj->conn, pool->def);

cleanup:
914 915
    if (pool)
        virStoragePoolObjUnlock(pool);
916
    return ret;
917 918 919 920 921
}

static int
storagePoolGetAutostart(virStoragePoolPtr obj,
                        int *autostart) {
922 923 924
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
925

926
    storageDriverLock(driver);
927
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
928 929
    storageDriverUnlock(driver);

930 931
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
932
                              "%s", _("no pool with matching uuid"));
933
        goto cleanup;
934 935 936 937 938 939 940
    }

    if (!pool->configFile) {
        *autostart = 0;
    } else {
        *autostart = pool->autostart;
    }
941
    ret = 0;
942

943
cleanup:
944 945
    if (pool)
        virStoragePoolObjUnlock(pool);
946
    return ret;
947 948 949 950 951
}

static int
storagePoolSetAutostart(virStoragePoolPtr obj,
                        int autostart) {
952 953 954
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
955

956
    storageDriverLock(driver);
957
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
958

959 960
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
961
                              "%s", _("no pool with matching uuid"));
962
        goto cleanup;
963 964 965 966
    }

    if (!pool->configFile) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_ARG,
J
Jim Meyering 已提交
967
                              "%s", _("pool has no config file"));
968
        goto cleanup;
969 970 971 972
    }

    autostart = (autostart != 0);

973 974 975
    if (pool->autostart != autostart) {
        if (autostart) {
            int err;
976

977
            if ((err = virFileMakePath(driver->autostartDir))) {
978 979 980
                virReportSystemError(obj->conn, err,
                                     _("cannot create autostart directory %s"),
                                     driver->autostartDir);
981 982
                goto cleanup;
            }
983

984
            if (symlink(pool->configFile, pool->autostartLink) < 0) {
985 986 987
                virReportSystemError(obj->conn, errno,
                                     _("Failed to create symlink '%s' to '%s'"),
                                     pool->autostartLink, pool->configFile);
988 989 990 991 992
                goto cleanup;
            }
        } else {
            if (unlink(pool->autostartLink) < 0 &&
                errno != ENOENT && errno != ENOTDIR) {
993 994 995
                virReportSystemError(obj->conn, errno,
                                     _("Failed to delete symlink '%s'"),
                                     pool->autostartLink);
996 997
                goto cleanup;
            }
998
        }
999
        pool->autostart = autostart;
1000
    }
1001
    ret = 0;
1002

1003
cleanup:
1004 1005
    if (pool)
        virStoragePoolObjUnlock(pool);
1006
    storageDriverUnlock(driver);
1007
    return ret;
1008 1009 1010 1011 1012
}


static int
storagePoolNumVolumes(virStoragePoolPtr obj) {
1013 1014 1015
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
1016

1017
    storageDriverLock(driver);
1018
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1019 1020
    storageDriverUnlock(driver);

1021 1022
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
1023
                              "%s", _("no storage pool with matching uuid"));
1024
        goto cleanup;
1025 1026 1027 1028
    }

    if (!virStoragePoolObjIsActive(pool)) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1029
                              "%s", _("storage pool is not active"));
1030
        goto cleanup;
1031
    }
1032
    ret = pool->volumes.count;
1033

1034
cleanup:
1035 1036
    if (pool)
        virStoragePoolObjUnlock(pool);
1037
    return ret;
1038 1039 1040 1041 1042 1043
}

static int
storagePoolListVolumes(virStoragePoolPtr obj,
                       char **const names,
                       int maxnames) {
1044 1045
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1046
    int i, n = 0;
1047

1048 1049
    memset(names, 0, maxnames * sizeof(*names));

1050
    storageDriverLock(driver);
1051
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1052 1053
    storageDriverUnlock(driver);

1054 1055
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
1056
                              "%s", _("no storage pool with matching uuid"));
1057
        goto cleanup;
1058 1059 1060 1061
    }

    if (!virStoragePoolObjIsActive(pool)) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1062
                              "%s", _("storage pool is not active"));
1063
        goto cleanup;
1064 1065
    }

1066 1067
    for (i = 0 ; i < pool->volumes.count && n < maxnames ; i++) {
        if ((names[n++] = strdup(pool->volumes.objs[i]->name)) == NULL) {
1068
            virReportOOMError(obj->conn);
1069 1070 1071 1072
            goto cleanup;
        }
    }

1073
    virStoragePoolObjUnlock(pool);
1074
    return n;
1075 1076

 cleanup:
1077 1078
    if (pool)
        virStoragePoolObjUnlock(pool);
1079
    for (n = 0 ; n < maxnames ; n++)
1080
        VIR_FREE(names[n]);
1081

1082
    memset(names, 0, maxnames * sizeof(*names));
1083 1084 1085 1086 1087 1088 1089
    return -1;
}


static virStorageVolPtr
storageVolumeLookupByName(virStoragePoolPtr obj,
                          const char *name) {
1090 1091
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1092
    virStorageVolDefPtr vol;
1093
    virStorageVolPtr ret = NULL;
1094

1095
    storageDriverLock(driver);
1096
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1097 1098
    storageDriverUnlock(driver);

1099 1100
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
1101
                              "%s", _("no storage pool with matching uuid"));
1102
        goto cleanup;
1103 1104 1105 1106
    }

    if (!virStoragePoolObjIsActive(pool)) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1107
                              "%s", _("storage pool is not active"));
1108
        goto cleanup;
1109 1110 1111 1112 1113
    }

    vol = virStorageVolDefFindByName(pool, name);

    if (!vol) {
1114 1115 1116
        virStorageReportError(obj->conn, VIR_ERR_NO_STORAGE_VOL,
                             _("no storage vol with matching name '%s'"),
                              name);
1117
        goto cleanup;
1118 1119
    }

1120 1121 1122
    ret = virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key);

cleanup:
1123 1124
    if (pool)
        virStoragePoolObjUnlock(pool);
1125
    return ret;
1126 1127 1128 1129 1130 1131
}


static virStorageVolPtr
storageVolumeLookupByKey(virConnectPtr conn,
                         const char *key) {
1132
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1133
    unsigned int i;
1134
    virStorageVolPtr ret = NULL;
1135

1136 1137 1138
    storageDriverLock(driver);
    for (i = 0 ; i < driver->pools.count && !ret ; i++) {
        virStoragePoolObjLock(driver->pools.objs[i]);
1139 1140 1141
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
            virStorageVolDefPtr vol =
                virStorageVolDefFindByKey(driver->pools.objs[i], key);
1142

1143
            if (vol)
1144
                ret = virGetStorageVol(conn,
1145 1146 1147
                                       driver->pools.objs[i]->def->name,
                                       vol->name,
                                       vol->key);
1148
        }
1149
        virStoragePoolObjUnlock(driver->pools.objs[i]);
1150
    }
1151
    storageDriverUnlock(driver);
1152

1153 1154 1155 1156 1157
    if (!ret)
        virStorageReportError(conn, VIR_ERR_INVALID_STORAGE_VOL,
                              "%s", _("no storage vol with matching key"));

    return ret;
1158 1159 1160 1161 1162
}

static virStorageVolPtr
storageVolumeLookupByPath(virConnectPtr conn,
                          const char *path) {
1163
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1164
    unsigned int i;
1165
    virStorageVolPtr ret = NULL;
1166

1167 1168 1169
    storageDriverLock(driver);
    for (i = 0 ; i < driver->pools.count && !ret ; i++) {
        virStoragePoolObjLock(driver->pools.objs[i]);
1170
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
1171
            virStorageVolDefPtr vol;
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181
            const char *stable_path;

            stable_path = virStorageBackendStablePath(conn,
                                                      driver->pools.objs[i],
                                                      path);
            /*
             * virStorageBackendStablePath already does
             * virStorageReportError if it fails; we just need to keep
             * propagating the return code
             */
1182 1183
            if (stable_path == NULL) {
                virStoragePoolObjUnlock(driver->pools.objs[i]);
1184
                goto cleanup;
1185
            }
1186 1187 1188 1189

            vol = virStorageVolDefFindByPath(driver->pools.objs[i],
                                             stable_path);
            VIR_FREE(stable_path);
1190

1191
            if (vol)
1192 1193 1194 1195
                ret = virGetStorageVol(conn,
                                       driver->pools.objs[i]->def->name,
                                       vol->name,
                                       vol->key);
1196
        }
1197
        virStoragePoolObjUnlock(driver->pools.objs[i]);
1198 1199
    }

1200 1201 1202 1203 1204
    if (!ret)
        virStorageReportError(conn, VIR_ERR_INVALID_STORAGE_VOL,
                              "%s", _("no storage vol with matching path"));

cleanup:
1205
    storageDriverUnlock(driver);
1206
    return ret;
1207 1208
}

1209 1210
static int storageVolumeDelete(virStorageVolPtr obj, unsigned int flags);

1211 1212 1213 1214
static virStorageVolPtr
storageVolumeCreateXML(virStoragePoolPtr obj,
                       const char *xmldesc,
                       unsigned int flags ATTRIBUTE_UNUSED) {
1215 1216
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1217
    virStorageBackendPtr backend;
1218 1219
    virStorageVolDefPtr voldef = NULL;
    virStorageVolPtr ret = NULL, volobj = NULL;
1220

1221
    storageDriverLock(driver);
1222
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1223 1224
    storageDriverUnlock(driver);

1225 1226
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
1227
                              "%s", _("no storage pool with matching uuid"));
1228
        goto cleanup;
1229 1230 1231 1232
    }

    if (!virStoragePoolObjIsActive(pool)) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1233
                              "%s", _("storage pool is not active"));
1234
        goto cleanup;
1235 1236 1237
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
1238
        goto cleanup;
1239

1240
    voldef = virStorageVolDefParseString(obj->conn, pool->def, xmldesc);
1241
    if (voldef == NULL)
1242
        goto cleanup;
1243

1244
    if (virStorageVolDefFindByName(pool, voldef->name)) {
1245
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
1246
                              "%s", _("storage vol already exists"));
1247
        goto cleanup;
1248 1249
    }

1250 1251
    if (VIR_REALLOC_N(pool->volumes.objs,
                      pool->volumes.count+1) < 0) {
1252
        virReportOOMError(obj->conn);
1253
        goto cleanup;
1254 1255
    }

1256 1257
    if (!backend->createVol) {
        virStorageReportError(obj->conn, VIR_ERR_NO_SUPPORT,
1258 1259
                              "%s", _("storage pool does not support volume "
                                      "creation"));
1260
        goto cleanup;
1261 1262
    }

1263
    if (backend->createVol(obj->conn, pool, voldef) < 0) {
1264
        goto cleanup;
1265 1266
    }

1267 1268 1269
    pool->volumes.objs[pool->volumes.count++] = voldef;
    volobj = virGetStorageVol(obj->conn, pool->def->name, voldef->name,
                              voldef->key);
1270

1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293
    if (volobj && backend->buildVol) {
        int buildret;
        virStorageVolDefPtr buildvoldef = NULL;

        if (VIR_ALLOC(buildvoldef) < 0) {
            virReportOOMError(obj->conn);
            voldef = NULL;
            goto cleanup;
        }

        /* Make a shallow copy of the 'defined' volume definition, since the
         * original allocation value will change as the user polls 'info',
         * but we only need the initial requested values
         */
        memcpy(buildvoldef, voldef, sizeof(*voldef));

        /* Drop the pool lock during volume allocation */
        pool->asyncjobs++;
        voldef->building = 1;
        virStoragePoolObjUnlock(pool);

        buildret = backend->buildVol(obj->conn, buildvoldef);

1294
        storageDriverLock(driver);
1295
        virStoragePoolObjLock(pool);
1296 1297
        storageDriverUnlock(driver);

1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315
        voldef->building = 0;
        pool->asyncjobs--;

        voldef = NULL;
        VIR_FREE(buildvoldef);

        if (buildret < 0) {
            virStoragePoolObjUnlock(pool);
            storageVolumeDelete(volobj, 0);
            pool = NULL;
            goto cleanup;
        }

    }

    ret = volobj;
    volobj = NULL;
    voldef = NULL;
1316

1317
cleanup:
1318 1319 1320
    if (volobj)
        virUnrefStorageVol(volobj);
    virStorageVolDefFree(voldef);
1321 1322
    if (pool)
        virStoragePoolObjUnlock(pool);
1323
    return ret;
1324 1325
}

1326 1327 1328 1329 1330 1331 1332 1333 1334 1335
static virStorageVolPtr
storageVolumeCreateXMLFrom(virStoragePoolPtr obj,
                           const char *xmldesc,
                           virStorageVolPtr vobj,
                           unsigned int flags ATTRIBUTE_UNUSED) {
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool, origpool = NULL;
    virStorageBackendPtr backend;
    virStorageVolDefPtr origvol = NULL, newvol = NULL;
    virStorageVolPtr ret = NULL, volobj = NULL;
1336
    int buildret;
1337 1338 1339

    storageDriverLock(driver);
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1340
    if (pool && STRNEQ(obj->name, vobj->pool)) {
1341
        virStoragePoolObjUnlock(pool);
1342
        origpool = virStoragePoolObjFindByName(&driver->pools, vobj->pool);
1343
        virStoragePoolObjLock(pool);
1344
    }
1345 1346 1347 1348 1349 1350 1351
    storageDriverUnlock(driver);
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
                              "%s", _("no storage pool with matching uuid"));
        goto cleanup;
    }

1352
    if (STRNEQ(obj->name, vobj->pool) && !origpool) {
1353 1354 1355
        virStorageReportError(obj->conn, VIR_ERR_NO_STORAGE_POOL,
                             _("no storage pool with matching name '%s'"),
                              vobj->pool);
1356 1357 1358 1359 1360 1361 1362 1363 1364
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(pool)) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
                              "%s", _("storage pool is not active"));
        goto cleanup;
    }

1365
    if (origpool && !virStoragePoolObjIsActive(origpool)) {
1366 1367 1368 1369 1370 1371 1372 1373
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
                              "%s", _("storage pool is not active"));
        goto cleanup;
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;

1374
    origvol = virStorageVolDefFindByName(origpool ? origpool : pool, vobj->name);
1375
    if (!origvol) {
1376 1377 1378
        virStorageReportError(obj->conn, VIR_ERR_NO_STORAGE_VOL,
                             _("no storage vol with matching name '%s'"),
                              vobj->name);
1379 1380 1381
        goto cleanup;
    }

1382
    newvol = virStorageVolDefParseString(obj->conn, pool->def, xmldesc);
1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396
    if (newvol == NULL)
        goto cleanup;

    if (virStorageVolDefFindByName(pool, newvol->name)) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
                              _("storage volume name '%s' already in use."),
                              newvol->name);
        goto cleanup;
    }

    /* Is there ever a valid case for this? */
    if (newvol->capacity < origvol->capacity)
        newvol->capacity = origvol->capacity;

1397 1398 1399 1400 1401
    /* Make sure allocation is at least as large as the destination cap,
     * to make absolutely sure we copy all possible contents */
    if (newvol->allocation < origvol->capacity)
        newvol->allocation = origvol->capacity;

1402 1403 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 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439
    if (!backend->buildVolFrom) {
        virStorageReportError(obj->conn, VIR_ERR_NO_SUPPORT,
                              "%s", _("storage pool does not support volume creation from an existing volume"));
        goto cleanup;
    }

    if (origvol->building) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
                              _("volume '%s' is still being allocated."),
                              origvol->name);
        goto cleanup;
    }

    if (backend->refreshVol &&
        backend->refreshVol(obj->conn, pool, origvol) < 0)
        goto cleanup;

    if (VIR_REALLOC_N(pool->volumes.objs,
                      pool->volumes.count+1) < 0) {
        virReportOOMError(obj->conn);
        goto cleanup;
    }

    /* 'Define' the new volume so we get async progress reporting */
    if (backend->createVol(obj->conn, pool, newvol) < 0) {
        goto cleanup;
    }

    pool->volumes.objs[pool->volumes.count++] = newvol;
    volobj = virGetStorageVol(obj->conn, pool->def->name, newvol->name,
                              newvol->key);

    /* Drop the pool lock during volume allocation */
    pool->asyncjobs++;
    origvol->building = 1;
    newvol->building = 1;
    virStoragePoolObjUnlock(pool);

1440
    if (origpool) {
1441 1442 1443 1444 1445 1446 1447 1448
        origpool->asyncjobs++;
        virStoragePoolObjUnlock(origpool);
    }

    buildret = backend->buildVolFrom(obj->conn, newvol, origvol, flags);

    storageDriverLock(driver);
    virStoragePoolObjLock(pool);
1449
    if (origpool)
1450 1451 1452 1453 1454 1455 1456 1457
        virStoragePoolObjLock(origpool);
    storageDriverUnlock(driver);

    origvol->building = 0;
    newvol->building = 0;
    newvol = NULL;
    pool->asyncjobs--;

1458
    if (origpool) {
1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479
        origpool->asyncjobs--;
        virStoragePoolObjUnlock(origpool);
        origpool = NULL;
    }

    if (buildret < 0) {
        virStoragePoolObjUnlock(pool);
        storageVolumeDelete(volobj, 0);
        pool = NULL;
        goto cleanup;
    }

    ret = volobj;
    volobj = NULL;

cleanup:
    if (volobj)
        virUnrefStorageVol(volobj);
    virStorageVolDefFree(newvol);
    if (pool)
        virStoragePoolObjUnlock(pool);
1480
    if (origpool)
1481 1482 1483 1484
        virStoragePoolObjUnlock(origpool);
    return ret;
}

1485 1486 1487
static int
storageVolumeDelete(virStorageVolPtr obj,
                    unsigned int flags) {
1488 1489
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1490
    virStorageBackendPtr backend;
1491
    virStorageVolDefPtr vol = NULL;
1492
    unsigned int i;
1493
    int ret = -1;
1494

1495
    storageDriverLock(driver);
1496
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
1497 1498
    storageDriverUnlock(driver);

1499 1500
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
1501
                              "%s", _("no storage pool with matching uuid"));
1502
        goto cleanup;
1503 1504 1505 1506
    }

    if (!virStoragePoolObjIsActive(pool)) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1507
                              "%s", _("storage pool is not active"));
1508
        goto cleanup;
1509 1510 1511
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
1512
        goto cleanup;
1513 1514 1515 1516

    vol = virStorageVolDefFindByName(pool, obj->name);

    if (!vol) {
1517 1518 1519
        virStorageReportError(obj->conn, VIR_ERR_NO_STORAGE_VOL,
                             _("no storage vol with matching name '%s'"),
                              obj->name);
1520
        goto cleanup;
1521 1522
    }

1523 1524 1525 1526 1527 1528 1529
    if (vol->building) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
                              _("volume '%s' is still being allocated."),
                              vol->name);
        goto cleanup;
    }

1530 1531
    if (!backend->deleteVol) {
        virStorageReportError(obj->conn, VIR_ERR_NO_SUPPORT,
J
Jim Meyering 已提交
1532
                              "%s", _("storage pool does not support vol deletion"));
1533

1534
        goto cleanup;
1535 1536
    }

1537 1538 1539
    if (backend->deleteVol(obj->conn, pool, vol, flags) < 0)
        goto cleanup;

1540 1541 1542
    for (i = 0 ; i < pool->volumes.count ; i++) {
        if (pool->volumes.objs[i] == vol) {
            virStorageVolDefFree(vol);
1543
            vol = NULL;
1544 1545 1546 1547 1548 1549 1550 1551 1552 1553

            if (i < (pool->volumes.count - 1))
                memmove(pool->volumes.objs + i, pool->volumes.objs + i + 1,
                        sizeof(*(pool->volumes.objs)) * (pool->volumes.count - (i + 1)));

            if (VIR_REALLOC_N(pool->volumes.objs, pool->volumes.count - 1) < 0) {
                ; /* Failure to reduce memory allocation isn't fatal */
            }
            pool->volumes.count--;

1554 1555 1556
            break;
        }
    }
1557
    ret = 0;
1558

1559
cleanup:
1560 1561
    if (pool)
        virStoragePoolObjUnlock(pool);
1562
    return ret;
1563 1564 1565 1566 1567
}

static int
storageVolumeGetInfo(virStorageVolPtr obj,
                     virStorageVolInfoPtr info) {
1568 1569
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1570 1571
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
1572
    int ret = -1;
1573

1574
    storageDriverLock(driver);
1575
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
1576 1577
    storageDriverUnlock(driver);

1578 1579
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
1580
                              "%s", _("no storage pool with matching uuid"));
1581
        goto cleanup;
1582 1583 1584 1585
    }

    if (!virStoragePoolObjIsActive(pool)) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1586
                              "%s", _("storage pool is not active"));
1587
        goto cleanup;
1588 1589 1590 1591 1592
    }

    vol = virStorageVolDefFindByName(pool, obj->name);

    if (!vol) {
1593 1594 1595
        virStorageReportError(obj->conn, VIR_ERR_NO_STORAGE_VOL,
                             _("no storage vol with matching name '%s'"),
                              obj->name);
1596
        goto cleanup;
1597 1598 1599
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
1600
        goto cleanup;
1601 1602 1603

    if (backend->refreshVol &&
        backend->refreshVol(obj->conn, pool, vol) < 0)
1604
        goto cleanup;
1605 1606

    memset(info, 0, sizeof(*info));
1607
    info->type = vol->type;
1608 1609
    info->capacity = vol->capacity;
    info->allocation = vol->allocation;
1610
    ret = 0;
1611

1612
cleanup:
1613 1614
    if (pool)
        virStoragePoolObjUnlock(pool);
1615
    return ret;
1616 1617 1618 1619 1620
}

static char *
storageVolumeGetXMLDesc(virStorageVolPtr obj,
                        unsigned int flags ATTRIBUTE_UNUSED) {
1621 1622
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1623 1624
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
1625
    char *ret = NULL;
1626

1627
    storageDriverLock(driver);
1628
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
1629 1630
    storageDriverUnlock(driver);

1631 1632
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
1633
                              "%s", _("no storage pool with matching uuid"));
1634
        goto cleanup;
1635 1636 1637 1638
    }

    if (!virStoragePoolObjIsActive(pool)) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1639
                              "%s", _("storage pool is not active"));
1640
        goto cleanup;
1641 1642 1643 1644 1645
    }

    vol = virStorageVolDefFindByName(pool, obj->name);

    if (!vol) {
1646 1647 1648
        virStorageReportError(obj->conn, VIR_ERR_NO_STORAGE_VOL,
                             _("no storage vol with matching name '%s'"),
                              obj->name);
1649
        goto cleanup;
1650 1651 1652
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
1653
        goto cleanup;
1654 1655 1656 1657

    if (backend->refreshVol &&
        backend->refreshVol(obj->conn, pool, vol) < 0)
        goto cleanup;
1658

1659 1660 1661
    ret = virStorageVolDefFormat(obj->conn, pool->def, vol);

cleanup:
1662 1663 1664
    if (pool)
        virStoragePoolObjUnlock(pool);

1665
    return ret;
1666 1667 1668 1669
}

static char *
storageVolumeGetPath(virStorageVolPtr obj) {
1670
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
1671
    virStoragePoolObjPtr pool;
1672
    virStorageVolDefPtr vol;
1673
    char *ret = NULL;
1674

1675 1676 1677
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
    storageDriverUnlock(driver);
1678 1679
    if (!pool) {
        virStorageReportError(obj->conn, VIR_ERR_INVALID_STORAGE_POOL,
J
Jim Meyering 已提交
1680
                              "%s", _("no storage pool with matching uuid"));
1681
        goto cleanup;
1682 1683 1684 1685
    }

    if (!virStoragePoolObjIsActive(pool)) {
        virStorageReportError(obj->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1686
                              "%s", _("storage pool is not active"));
1687
        goto cleanup;
1688 1689 1690 1691 1692
    }

    vol = virStorageVolDefFindByName(pool, obj->name);

    if (!vol) {
1693 1694 1695
        virStorageReportError(obj->conn, VIR_ERR_NO_STORAGE_VOL,
                             _("no storage vol with matching name '%s'"),
                              obj->name);
1696
        goto cleanup;
1697 1698 1699
    }

    ret = strdup(vol->target.path);
1700
    if (ret == NULL)
1701
        virReportOOMError(obj->conn);
1702 1703

cleanup:
1704 1705
    if (pool)
        virStoragePoolObjUnlock(pool);
1706 1707 1708 1709
    return ret;
}

static virStorageDriver storageDriver = {
1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739
    .name = "storage",
    .open = storageOpen,
    .close = storageClose,
    .numOfPools = storageNumPools,
    .listPools = storageListPools,
    .numOfDefinedPools = storageNumDefinedPools,
    .listDefinedPools = storageListDefinedPools,
    .findPoolSources = storageFindPoolSources,
    .poolLookupByName = storagePoolLookupByName,
    .poolLookupByUUID = storagePoolLookupByUUID,
    .poolLookupByVolume = storagePoolLookupByVolume,
    .poolCreateXML = storagePoolCreate,
    .poolDefineXML = storagePoolDefine,
    .poolBuild = storagePoolBuild,
    .poolUndefine = storagePoolUndefine,
    .poolCreate = storagePoolStart,
    .poolDestroy = storagePoolDestroy,
    .poolDelete = storagePoolDelete,
    .poolRefresh = storagePoolRefresh,
    .poolGetInfo = storagePoolGetInfo,
    .poolGetXMLDesc = storagePoolDumpXML,
    .poolGetAutostart = storagePoolGetAutostart,
    .poolSetAutostart = storagePoolSetAutostart,
    .poolNumOfVolumes = storagePoolNumVolumes,
    .poolListVolumes = storagePoolListVolumes,

    .volLookupByName = storageVolumeLookupByName,
    .volLookupByKey = storageVolumeLookupByKey,
    .volLookupByPath = storageVolumeLookupByPath,
    .volCreateXML = storageVolumeCreateXML,
1740
    .volCreateXMLFrom = storageVolumeCreateXMLFrom,
1741 1742 1743 1744
    .volDelete = storageVolumeDelete,
    .volGetInfo = storageVolumeGetInfo,
    .volGetXMLDesc = storageVolumeGetXMLDesc,
    .volGetPath = storageVolumeGetPath,
1745 1746 1747 1748
};


static virStateDriver stateDriver = {
1749
    .name = "Storage",
1750 1751 1752 1753
    .initialize = storageDriverStartup,
    .cleanup = storageDriverShutdown,
    .reload = storageDriverReload,
    .active = storageDriverActive,
1754 1755 1756 1757 1758 1759 1760
};

int storageRegister(void) {
    virRegisterStorageDriver(&storageDriver);
    virRegisterStateDriver(&stateDriver);
    return 0;
}