storage_driver.c 56.9 KB
Newer Older
1 2 3
/*
 * storage_driver.c: core driver for storage APIs
 *
4
 * Copyright (C) 2006-2010 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>
29 30 31 32
#include <sys/stat.h>
#include <sys/param.h>
#include <fcntl.h>

R
Richard W.M. Jones 已提交
33
#if HAVE_PWD_H
34
# include <pwd.h>
R
Richard W.M. Jones 已提交
35
#endif
36 37 38
#include <errno.h>
#include <string.h>

39
#include "virterror_internal.h"
40
#include "datatypes.h"
41 42 43 44
#include "driver.h"
#include "util.h"
#include "storage_driver.h"
#include "storage_conf.h"
45
#include "memory.h"
46
#include "storage_backend.h"
47
#include "logging.h"
48
#include "files.h"
49
#include "configmake.h"
50

51 52
#define VIR_FROM_THIS VIR_FROM_STORAGE

53 54 55 56
static virStorageDriverStatePtr driverState;

static int storageDriverShutdown(void);

57 58
static void storageDriverLock(virStorageDriverStatePtr driver)
{
59
    virMutexLock(&driver->lock);
60 61 62
}
static void storageDriverUnlock(virStorageDriverStatePtr driver)
{
63
    virMutexUnlock(&driver->lock);
64
}
65 66 67

static void
storageDriverAutostart(virStorageDriverStatePtr driver) {
68
    unsigned int i;
69

70 71
    for (i = 0 ; i < driver->pools.count ; i++) {
        virStoragePoolObjPtr pool = driver->pools.objs[i];
72 73
        virStorageBackendPtr backend;
        bool started = false;
74

75
        virStoragePoolObjLock(pool);
76 77 78 79 80
        if ((backend = virStorageBackendForType(pool->def->type)) == NULL) {
            VIR_ERROR(_("Missing backend %d"), pool->def->type);
            virStoragePoolObjUnlock(pool);
            continue;
        }
81

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

        if (!started &&
            pool->autostart &&
            !virStoragePoolObjIsActive(pool)) {
95 96 97
            if (backend->startPool &&
                backend->startPool(NULL, pool) < 0) {
                virErrorPtr err = virGetLastError();
98
                VIR_ERROR(_("Failed to autostart storage pool '%s': %s"),
99
                          pool->def->name, err ? err->message :
100
                          _("no error message found"));
101
                virStoragePoolObjUnlock(pool);
102 103
                continue;
            }
104 105
            started = true;
        }
106

107
        if (started) {
108 109 110 111
            if (backend->refreshPool(NULL, pool) < 0) {
                virErrorPtr err = virGetLastError();
                if (backend->stopPool)
                    backend->stopPool(NULL, pool);
112
                VIR_ERROR(_("Failed to autostart storage pool '%s': %s"),
113
                          pool->def->name, err ? err->message :
114
                          _("no error message found"));
115
                virStoragePoolObjUnlock(pool);
116 117 118 119
                continue;
            }
            pool->active = 1;
        }
120
        virStoragePoolObjUnlock(pool);
121 122 123 124 125 126 127 128 129
    }
}

/**
 * virStorageStartup:
 *
 * Initialization function for the QEmu daemon
 */
static int
130
storageDriverStartup(int privileged) {
131 132 133
    char *base = NULL;
    char driverConf[PATH_MAX];

134
    if (VIR_ALLOC(driverState) < 0)
135 136
        return -1;

137 138 139 140
    if (virMutexInit(&driverState->lock) < 0) {
        VIR_FREE(driverState);
        return -1;
    }
141 142
    storageDriverLock(driverState);

143
    if (privileged) {
144
        if ((base = strdup (SYSCONFDIR "/libvirt")) == NULL)
145 146
            goto out_of_memory;
    } else {
147
        uid_t uid = geteuid();
148
        char *userdir = virGetUserDirectory(uid);
149 150 151

        if (!userdir)
            goto error;
152

153 154
        if (virAsprintf(&base, "%s/.libvirt", userdir) == -1) {
            VIR_FREE(userdir);
155 156
            goto out_of_memory;
        }
157
        VIR_FREE(userdir);
158 159 160 161 162 163 164 165 166 167
    }

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

168 169
    if (virAsprintf(&driverState->configDir,
                    "%s/storage", base) == -1)
170 171
        goto out_of_memory;

172 173
    if (virAsprintf(&driverState->autostartDir,
                    "%s/storage/autostart", base) == -1)
174 175
        goto out_of_memory;

176
    VIR_FREE(base);
177 178 179 180 181 182 183 184

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

185
    if (virStoragePoolLoadAllConfigs(&driverState->pools,
186
                                     driverState->configDir,
187 188
                                     driverState->autostartDir) < 0)
        goto error;
189 190
    storageDriverAutostart(driverState);

191
    storageDriverUnlock(driverState);
192 193
    return 0;

194
out_of_memory:
195
    virReportOOMError();
196 197 198 199
error:
    VIR_FREE(base);
    storageDriverUnlock(driverState);
    storageDriverShutdown();
200 201 202 203 204 205 206 207 208 209 210
    return -1;
}

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

214
    storageDriverLock(driverState);
215
    virStoragePoolLoadAllConfigs(&driverState->pools,
216 217
                                 driverState->configDir,
                                 driverState->autostartDir);
218
    storageDriverAutostart(driverState);
219
    storageDriverUnlock(driverState);
220 221 222 223 224 225 226 227 228 229 230 231 232

    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) {
233
    unsigned int i;
234
    int active = 0;
235 236 237 238

    if (!driverState)
        return 0;

239 240 241 242
    storageDriverLock(driverState);

    for (i = 0 ; i < driverState->pools.count ; i++) {
        virStoragePoolObjLock(driverState->pools.objs[i]);
243
        if (virStoragePoolObjIsActive(driverState->pools.objs[i]))
244 245 246
            active = 1;
        virStoragePoolObjUnlock(driverState->pools.objs[i]);
    }
247

248 249
    storageDriverUnlock(driverState);
    return active;
250 251 252 253 254 255 256 257 258 259 260 261
}

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

262
    storageDriverLock(driverState);
263 264

    /* free inactive pools */
265 266 267 268
    virStoragePoolObjListFree(&driverState->pools);

    VIR_FREE(driverState->configDir);
    VIR_FREE(driverState->autostartDir);
269
    storageDriverUnlock(driverState);
270
    virMutexDestroy(&driverState->lock);
271
    VIR_FREE(driverState);
272 273 274 275 276 277 278 279 280

    return 0;
}



static virStoragePoolPtr
storagePoolLookupByUUID(virConnectPtr conn,
                        const unsigned char *uuid) {
281 282 283
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
284

285
    storageDriverLock(driver);
286
    pool = virStoragePoolObjFindByUUID(&driver->pools, uuid);
287 288
    storageDriverUnlock(driver);

289
    if (!pool) {
290
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
291
                              "%s", _("no pool with matching uuid"));
292
        goto cleanup;
293 294 295
    }

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

cleanup:
298 299
    if (pool)
        virStoragePoolObjUnlock(pool);
300 301 302 303 304 305
    return ret;
}

static virStoragePoolPtr
storagePoolLookupByName(virConnectPtr conn,
                        const char *name) {
306 307 308
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
309

310
    storageDriverLock(driver);
311
    pool = virStoragePoolObjFindByName(&driver->pools, name);
312 313
    storageDriverUnlock(driver);

314
    if (!pool) {
315
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
316
                              _("no pool with matching name '%s'"), name);
317
        goto cleanup;
318 319 320
    }

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

cleanup:
323 324
    if (pool)
        virStoragePoolObjUnlock(pool);
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
    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) {
352
    virStorageDriverStatePtr driver = conn->storagePrivateData;
353 354
    unsigned int i, nactive = 0;

355 356 357
    storageDriverLock(driver);
    for (i = 0 ; i < driver->pools.count ; i++) {
        virStoragePoolObjLock(driver->pools.objs[i]);
358 359
        if (virStoragePoolObjIsActive(driver->pools.objs[i]))
            nactive++;
360 361 362
        virStoragePoolObjUnlock(driver->pools.objs[i]);
    }
    storageDriverUnlock(driver);
363 364

    return nactive;
365 366 367 368 369 370
}

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

374
    storageDriverLock(driver);
375
    for (i = 0 ; i < driver->pools.count && got < nnames ; i++) {
376
        virStoragePoolObjLock(driver->pools.objs[i]);
377 378
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
            if (!(names[got] = strdup(driver->pools.objs[i]->def->name))) {
379
                virStoragePoolObjUnlock(driver->pools.objs[i]);
380
                virReportOOMError();
381 382 383 384
                goto cleanup;
            }
            got++;
        }
385
        virStoragePoolObjUnlock(driver->pools.objs[i]);
386
    }
387
    storageDriverUnlock(driver);
388 389 390
    return got;

 cleanup:
391 392 393
    storageDriverUnlock(driver);
    for (i = 0 ; i < got ; i++)
        VIR_FREE(names[i]);
394
    memset(names, 0, nnames * sizeof(*names));
395 396 397 398 399
    return -1;
}

static int
storageNumDefinedPools(virConnectPtr conn) {
400
    virStorageDriverStatePtr driver = conn->storagePrivateData;
401 402
    unsigned int i, nactive = 0;

403 404 405
    storageDriverLock(driver);
    for (i = 0 ; i < driver->pools.count ; i++) {
        virStoragePoolObjLock(driver->pools.objs[i]);
406 407
        if (!virStoragePoolObjIsActive(driver->pools.objs[i]))
            nactive++;
408 409 410
        virStoragePoolObjUnlock(driver->pools.objs[i]);
    }
    storageDriverUnlock(driver);
411 412

    return nactive;
413 414 415 416 417 418
}

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

422
    storageDriverLock(driver);
423
    for (i = 0 ; i < driver->pools.count && got < nnames ; i++) {
424
        virStoragePoolObjLock(driver->pools.objs[i]);
425 426
        if (!virStoragePoolObjIsActive(driver->pools.objs[i])) {
            if (!(names[got] = strdup(driver->pools.objs[i]->def->name))) {
427
                virStoragePoolObjUnlock(driver->pools.objs[i]);
428
                virReportOOMError();
429 430 431 432
                goto cleanup;
            }
            got++;
        }
433
        virStoragePoolObjUnlock(driver->pools.objs[i]);
434
    }
435
    storageDriverUnlock(driver);
436 437 438
    return got;

 cleanup:
439
    storageDriverUnlock(driver);
440
    for (i = 0 ; i < got ; i++) {
441
        VIR_FREE(names[i]);
442
    }
443
    memset(names, 0, nnames * sizeof(*names));
444 445 446
    return -1;
}

447 448
/* This method is required to be re-entrant / thread safe, so
   uses no driver lock */
449 450 451 452 453 454 455 456
static char *
storageFindPoolSources(virConnectPtr conn,
                       const char *type,
                       const char *srcSpec,
                       unsigned int flags)
{
    int backend_type;
    virStorageBackendPtr backend;
457
    char *ret = NULL;
458

459
    backend_type = virStoragePoolTypeFromString(type);
460
    if (backend_type < 0) {
461
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
462
                              _("unknown storage pool type %s"), type);
463
        goto cleanup;
464
    }
465 466 467

    backend = virStorageBackendForType(backend_type);
    if (backend == NULL)
468
        goto cleanup;
469

470
    if (!backend->findPoolSources) {
471
        virStorageReportError(VIR_ERR_NO_SUPPORT,
472 473 474 475 476 477
                              _("pool type '%s' does not support source "
                                "discovery"), type);
        goto cleanup;
    }

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

479 480
cleanup:
    return ret;
481 482 483
}


484
static int storagePoolIsActive(virStoragePoolPtr pool)
485
{
486
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
487 488 489 490
    virStoragePoolObjPtr obj;
    int ret = -1;

    storageDriverLock(driver);
491
    obj = virStoragePoolObjFindByUUID(&driver->pools, pool->uuid);
492 493
    storageDriverUnlock(driver);
    if (!obj) {
494
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
495 496 497 498 499 500 501 502 503 504
        goto cleanup;
    }
    ret = virStoragePoolObjIsActive(obj);

cleanup:
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}

505
static int storagePoolIsPersistent(virStoragePoolPtr pool)
506
{
507
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
508 509 510 511
    virStoragePoolObjPtr obj;
    int ret = -1;

    storageDriverLock(driver);
512
    obj = virStoragePoolObjFindByUUID(&driver->pools, pool->uuid);
513 514
    storageDriverUnlock(driver);
    if (!obj) {
515
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
516 517 518 519 520 521 522 523 524 525 526
        goto cleanup;
    }
    ret = obj->configFile ? 1 : 0;

cleanup:
    if (obj)
        virStoragePoolObjUnlock(obj);
    return ret;
}


527 528 529 530
static virStoragePoolPtr
storagePoolCreate(virConnectPtr conn,
                  const char *xml,
                  unsigned int flags ATTRIBUTE_UNUSED) {
531
    virStorageDriverStatePtr driver = conn->storagePrivateData;
532
    virStoragePoolDefPtr def;
533
    virStoragePoolObjPtr pool = NULL;
534
    virStoragePoolPtr ret = NULL;
535 536
    virStorageBackendPtr backend;

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

541
    if (virStoragePoolObjIsDuplicate(&driver->pools, def, 1) < 0)
542
        goto cleanup;
543

544 545
    if ((backend = virStorageBackendForType(def->type)) == NULL)
        goto cleanup;
546

547
    if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
548 549
        goto cleanup;
    def = NULL;
550

551
    if (backend->startPool &&
552 553 554
        backend->startPool(conn, pool) < 0) {
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
555
        goto cleanup;
556
    }
557

558 559 560
    if (backend->refreshPool(conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(conn, pool);
561 562
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
563
        goto cleanup;
564 565 566 567 568
    }
    pool->active = 1;

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

569 570
cleanup:
    virStoragePoolDefFree(def);
571
    if (pool)
572
        virStoragePoolObjUnlock(pool);
573
    storageDriverUnlock(driver);
574 575 576 577 578 579 580
    return ret;
}

static virStoragePoolPtr
storagePoolDefine(virConnectPtr conn,
                  const char *xml,
                  unsigned int flags ATTRIBUTE_UNUSED) {
581
    virStorageDriverStatePtr driver = conn->storagePrivateData;
582
    virStoragePoolDefPtr def;
583
    virStoragePoolObjPtr pool = NULL;
584
    virStoragePoolPtr ret = NULL;
585

586
    storageDriverLock(driver);
587
    if (!(def = virStoragePoolDefParseString(xml)))
588
        goto cleanup;
589

590 591 592
    if (virStoragePoolObjIsDuplicate(&driver->pools, def, 0) < 0)
        goto cleanup;

593
    if (virStorageBackendForType(def->type) == NULL)
594
        goto cleanup;
595

596
    if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
597
        goto cleanup;
598

599
    if (virStoragePoolObjSaveDef(driver, pool, def) < 0) {
600
        virStoragePoolObjRemove(&driver->pools, pool);
601
        def = NULL;
602
        goto cleanup;
603
    }
604
    def = NULL;
605 606

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

cleanup:
    virStoragePoolDefFree(def);
610 611 612
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
613 614 615 616 617
    return ret;
}

static int
storagePoolUndefine(virStoragePoolPtr obj) {
618 619 620
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
621

622
    storageDriverLock(driver);
623
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
624
    if (!pool) {
625
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
626
                              "%s", _("no storage pool with matching uuid"));
627
        goto cleanup;
628 629 630
    }

    if (virStoragePoolObjIsActive(pool)) {
631
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
632
                              "%s", _("pool is still active"));
633
        goto cleanup;
634 635
    }

636
    if (pool->asyncjobs > 0) {
637
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
638 639 640 641 642
                              _("pool '%s' has asynchronous jobs running."),
                              pool->def->name);
        goto cleanup;
    }

643
    if (virStoragePoolObjDeleteDef(pool) < 0)
644
        goto cleanup;
645

646 647
    if (unlink(pool->autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
        char ebuf[1024];
648
        VIR_ERROR(_("Failed to delete autostart link '%s': %s"),
649 650
                   pool->autostartLink, virStrerror(errno, ebuf, sizeof ebuf));
    }
651

652 653
    VIR_FREE(pool->configFile);
    VIR_FREE(pool->autostartLink);
654

655
    virStoragePoolObjRemove(&driver->pools, pool);
656
    pool = NULL;
657
    ret = 0;
658

659
cleanup:
660 661 662
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
663
    return ret;
664 665 666 667 668
}

static int
storagePoolStart(virStoragePoolPtr obj,
                 unsigned int flags ATTRIBUTE_UNUSED) {
669 670
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
671
    virStorageBackendPtr backend;
672
    int ret = -1;
673

674
    storageDriverLock(driver);
675
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
676 677
    storageDriverUnlock(driver);

678
    if (!pool) {
679
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
680
                              "%s", _("no storage pool with matching uuid"));
681
        goto cleanup;
682 683
    }

684 685
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
686 687

    if (virStoragePoolObjIsActive(pool)) {
688
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
689
                              "%s", _("pool already active"));
690
        goto cleanup;
691 692 693
    }
    if (backend->startPool &&
        backend->startPool(obj->conn, pool) < 0)
694 695
        goto cleanup;

696 697 698
    if (backend->refreshPool(obj->conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(obj->conn, pool);
699
        goto cleanup;
700 701 702
    }

    pool->active = 1;
703
    ret = 0;
704

705
cleanup:
706 707
    if (pool)
        virStoragePoolObjUnlock(pool);
708
    return ret;
709 710 711 712 713
}

static int
storagePoolBuild(virStoragePoolPtr obj,
                 unsigned int flags) {
714 715
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
716
    virStorageBackendPtr backend;
717
    int ret = -1;
718

719
    storageDriverLock(driver);
720
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
721 722
    storageDriverUnlock(driver);

723
    if (!pool) {
724
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
725
                              "%s", _("no storage pool with matching uuid"));
726
        goto cleanup;
727 728
    }

729 730
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
731 732

    if (virStoragePoolObjIsActive(pool)) {
733
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
734
                              "%s", _("storage pool is already active"));
735
        goto cleanup;
736 737 738 739
    }

    if (backend->buildPool &&
        backend->buildPool(obj->conn, pool, flags) < 0)
740 741
        goto cleanup;
    ret = 0;
742

743
cleanup:
744 745
    if (pool)
        virStoragePoolObjUnlock(pool);
746
    return ret;
747 748 749 750 751
}


static int
storagePoolDestroy(virStoragePoolPtr obj) {
752 753
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
754
    virStorageBackendPtr backend;
755
    int ret = -1;
756

757
    storageDriverLock(driver);
758
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
759

760
    if (!pool) {
761
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
762
                              "%s", _("no storage pool with matching uuid"));
763
        goto cleanup;
764 765
    }

766 767
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
768 769

    if (!virStoragePoolObjIsActive(pool)) {
770
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
771
                              "%s", _("storage pool is not active"));
772
        goto cleanup;
773 774
    }

775
    if (pool->asyncjobs > 0) {
776
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
777 778 779 780 781
                              _("pool '%s' has asynchronous jobs running."),
                              pool->def->name);
        goto cleanup;
    }

782 783
    if (backend->stopPool &&
        backend->stopPool(obj->conn, pool) < 0)
784
        goto cleanup;
785 786 787 788 789

    virStoragePoolObjClearVols(pool);

    pool->active = 0;

790
    if (pool->configFile == NULL) {
791
        virStoragePoolObjRemove(&driver->pools, pool);
792 793
        pool = NULL;
    }
794
    ret = 0;
795

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


static int
storagePoolDelete(virStoragePoolPtr obj,
                  unsigned int flags) {
807 808
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
809
    virStorageBackendPtr backend;
810
    int ret = -1;
811

812
    storageDriverLock(driver);
813
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
814 815
    storageDriverUnlock(driver);

816
    if (!pool) {
817
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
818
                              "%s", _("no storage pool with matching uuid"));
819
        goto cleanup;
820 821
    }

822 823
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
824 825

    if (virStoragePoolObjIsActive(pool)) {
826
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
827
                              "%s", _("storage pool is still active"));
828
        goto cleanup;
829 830
    }

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

838
    if (!backend->deletePool) {
839
        virStorageReportError(VIR_ERR_NO_SUPPORT,
840
                              "%s", _("pool does not support pool deletion"));
841
        goto cleanup;
842 843
    }
    if (backend->deletePool(obj->conn, pool, flags) < 0)
844 845
        goto cleanup;
    ret = 0;
846

847
cleanup:
848 849
    if (pool)
        virStoragePoolObjUnlock(pool);
850
    return ret;
851 852 853 854 855 856
}


static int
storagePoolRefresh(virStoragePoolPtr obj,
                   unsigned int flags ATTRIBUTE_UNUSED) {
857 858
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
859
    virStorageBackendPtr backend;
860
    int ret = -1;
861

862
    storageDriverLock(driver);
863
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
864

865
    if (!pool) {
866
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
867
                              "%s", _("no storage pool with matching uuid"));
868
        goto cleanup;
869 870
    }

871 872
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
873 874

    if (!virStoragePoolObjIsActive(pool)) {
875
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
876
                              "%s", _("storage pool is not active"));
877
        goto cleanup;
878 879
    }

880
    if (pool->asyncjobs > 0) {
881
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
882 883 884 885 886
                              _("pool '%s' has asynchronous jobs running."),
                              pool->def->name);
        goto cleanup;
    }

887
    virStoragePoolObjClearVols(pool);
888
    if (backend->refreshPool(obj->conn, pool) < 0) {
889 890 891 892 893
        if (backend->stopPool)
            backend->stopPool(obj->conn, pool);

        pool->active = 0;

894
        if (pool->configFile == NULL) {
895
            virStoragePoolObjRemove(&driver->pools, pool);
896 897
            pool = NULL;
        }
898
        goto cleanup;
899
    }
900
    ret = 0;
901

902
cleanup:
903 904
    if (pool)
        virStoragePoolObjUnlock(pool);
905
    storageDriverUnlock(driver);
906 907 908 909 910 911 912
    return ret;
}


static int
storagePoolGetInfo(virStoragePoolPtr obj,
                   virStoragePoolInfoPtr info) {
913 914 915
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
916

917
    storageDriverLock(driver);
918
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
919 920
    storageDriverUnlock(driver);

921
    if (!pool) {
922
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
923
                              "%s", _("no storage pool with matching uuid"));
924
        goto cleanup;
925 926
    }

927
    if (virStorageBackendForType(pool->def->type) == NULL)
928
        goto cleanup;
929 930 931 932 933 934 935 936 937

    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;
938
    ret = 0;
939

940
cleanup:
941 942
    if (pool)
        virStoragePoolObjUnlock(pool);
943
    return ret;
944 945 946 947 948
}

static char *
storagePoolDumpXML(virStoragePoolPtr obj,
                   unsigned int flags ATTRIBUTE_UNUSED) {
949 950 951
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    char *ret = NULL;
952

953
    storageDriverLock(driver);
954
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
955 956
    storageDriverUnlock(driver);

957
    if (!pool) {
958
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
959
                              "%s", _("no storage pool with matching uuid"));
960
        goto cleanup;
961 962
    }

963
    ret = virStoragePoolDefFormat(pool->def);
964 965

cleanup:
966 967
    if (pool)
        virStoragePoolObjUnlock(pool);
968
    return ret;
969 970 971 972 973
}

static int
storagePoolGetAutostart(virStoragePoolPtr obj,
                        int *autostart) {
974 975 976
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
977

978
    storageDriverLock(driver);
979
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
980 981
    storageDriverUnlock(driver);

982
    if (!pool) {
983
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
984
                              "%s", _("no pool with matching uuid"));
985
        goto cleanup;
986 987 988 989 990 991 992
    }

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

995
cleanup:
996 997
    if (pool)
        virStoragePoolObjUnlock(pool);
998
    return ret;
999 1000 1001 1002 1003
}

static int
storagePoolSetAutostart(virStoragePoolPtr obj,
                        int autostart) {
1004 1005 1006
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
1007

1008
    storageDriverLock(driver);
1009
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1010

1011
    if (!pool) {
1012
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1013
                              "%s", _("no pool with matching uuid"));
1014
        goto cleanup;
1015 1016 1017
    }

    if (!pool->configFile) {
1018
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1019
                              "%s", _("pool has no config file"));
1020
        goto cleanup;
1021 1022 1023 1024
    }

    autostart = (autostart != 0);

1025 1026 1027
    if (pool->autostart != autostart) {
        if (autostart) {
            int err;
1028

1029
            if ((err = virFileMakePath(driver->autostartDir))) {
1030
                virReportSystemError(err,
1031 1032
                                     _("cannot create autostart directory %s"),
                                     driver->autostartDir);
1033 1034
                goto cleanup;
            }
1035

1036
            if (symlink(pool->configFile, pool->autostartLink) < 0) {
1037
                virReportSystemError(errno,
1038 1039
                                     _("Failed to create symlink '%s' to '%s'"),
                                     pool->autostartLink, pool->configFile);
1040 1041 1042 1043 1044
                goto cleanup;
            }
        } else {
            if (unlink(pool->autostartLink) < 0 &&
                errno != ENOENT && errno != ENOTDIR) {
1045
                virReportSystemError(errno,
1046 1047
                                     _("Failed to delete symlink '%s'"),
                                     pool->autostartLink);
1048 1049
                goto cleanup;
            }
1050
        }
1051
        pool->autostart = autostart;
1052
    }
1053
    ret = 0;
1054

1055
cleanup:
1056 1057
    if (pool)
        virStoragePoolObjUnlock(pool);
1058
    storageDriverUnlock(driver);
1059
    return ret;
1060 1061 1062 1063 1064
}


static int
storagePoolNumVolumes(virStoragePoolPtr obj) {
1065 1066 1067
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
1068

1069
    storageDriverLock(driver);
1070
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1071 1072
    storageDriverUnlock(driver);

1073
    if (!pool) {
1074
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1075
                              "%s", _("no storage pool with matching uuid"));
1076
        goto cleanup;
1077 1078 1079
    }

    if (!virStoragePoolObjIsActive(pool)) {
1080
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
1081
                              "%s", _("storage pool is not active"));
1082
        goto cleanup;
1083
    }
1084
    ret = pool->volumes.count;
1085

1086
cleanup:
1087 1088
    if (pool)
        virStoragePoolObjUnlock(pool);
1089
    return ret;
1090 1091 1092 1093 1094 1095
}

static int
storagePoolListVolumes(virStoragePoolPtr obj,
                       char **const names,
                       int maxnames) {
1096 1097
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1098
    int i, n = 0;
1099

1100 1101
    memset(names, 0, maxnames * sizeof(*names));

1102
    storageDriverLock(driver);
1103
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1104 1105
    storageDriverUnlock(driver);

1106
    if (!pool) {
1107
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1108
                              "%s", _("no storage pool with matching uuid"));
1109
        goto cleanup;
1110 1111 1112
    }

    if (!virStoragePoolObjIsActive(pool)) {
1113
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
1114
                              "%s", _("storage pool is not active"));
1115
        goto cleanup;
1116 1117
    }

1118 1119
    for (i = 0 ; i < pool->volumes.count && n < maxnames ; i++) {
        if ((names[n++] = strdup(pool->volumes.objs[i]->name)) == NULL) {
1120
            virReportOOMError();
1121 1122 1123 1124
            goto cleanup;
        }
    }

1125
    virStoragePoolObjUnlock(pool);
1126
    return n;
1127 1128

 cleanup:
1129 1130
    if (pool)
        virStoragePoolObjUnlock(pool);
1131
    for (n = 0 ; n < maxnames ; n++)
1132
        VIR_FREE(names[n]);
1133

1134
    memset(names, 0, maxnames * sizeof(*names));
1135 1136 1137 1138 1139 1140 1141
    return -1;
}


static virStorageVolPtr
storageVolumeLookupByName(virStoragePoolPtr obj,
                          const char *name) {
1142 1143
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1144
    virStorageVolDefPtr vol;
1145
    virStorageVolPtr ret = NULL;
1146

1147
    storageDriverLock(driver);
1148
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1149 1150
    storageDriverUnlock(driver);

1151
    if (!pool) {
1152
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1153
                              "%s", _("no storage pool with matching uuid"));
1154
        goto cleanup;
1155 1156 1157
    }

    if (!virStoragePoolObjIsActive(pool)) {
1158
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
1159
                              "%s", _("storage pool is not active"));
1160
        goto cleanup;
1161 1162 1163 1164 1165
    }

    vol = virStorageVolDefFindByName(pool, name);

    if (!vol) {
1166 1167
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
                              _("no storage vol with matching name '%s'"),
1168
                              name);
1169
        goto cleanup;
1170 1171
    }

1172 1173 1174
    ret = virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key);

cleanup:
1175 1176
    if (pool)
        virStoragePoolObjUnlock(pool);
1177
    return ret;
1178 1179 1180 1181 1182 1183
}


static virStorageVolPtr
storageVolumeLookupByKey(virConnectPtr conn,
                         const char *key) {
1184
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1185
    unsigned int i;
1186
    virStorageVolPtr ret = NULL;
1187

1188 1189 1190
    storageDriverLock(driver);
    for (i = 0 ; i < driver->pools.count && !ret ; i++) {
        virStoragePoolObjLock(driver->pools.objs[i]);
1191 1192 1193
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
            virStorageVolDefPtr vol =
                virStorageVolDefFindByKey(driver->pools.objs[i], key);
1194

1195
            if (vol)
1196
                ret = virGetStorageVol(conn,
1197 1198 1199
                                       driver->pools.objs[i]->def->name,
                                       vol->name,
                                       vol->key);
1200
        }
1201
        virStoragePoolObjUnlock(driver->pools.objs[i]);
1202
    }
1203
    storageDriverUnlock(driver);
1204

1205
    if (!ret)
1206
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
1207 1208 1209
                              "%s", _("no storage vol with matching key"));

    return ret;
1210 1211 1212 1213 1214
}

static virStorageVolPtr
storageVolumeLookupByPath(virConnectPtr conn,
                          const char *path) {
1215
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1216
    unsigned int i;
1217
    virStorageVolPtr ret = NULL;
1218 1219 1220 1221 1222
    char *cleanpath;

    cleanpath = virFileSanitizePath(path);
    if (!cleanpath)
        return NULL;
1223

1224 1225 1226
    storageDriverLock(driver);
    for (i = 0 ; i < driver->pools.count && !ret ; i++) {
        virStoragePoolObjLock(driver->pools.objs[i]);
1227
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
1228
            virStorageVolDefPtr vol;
1229 1230
            const char *stable_path;

1231
            stable_path = virStorageBackendStablePath(driver->pools.objs[i],
1232
                                                      cleanpath);
1233 1234 1235 1236 1237
            /*
             * virStorageBackendStablePath already does
             * virStorageReportError if it fails; we just need to keep
             * propagating the return code
             */
1238 1239
            if (stable_path == NULL) {
                virStoragePoolObjUnlock(driver->pools.objs[i]);
1240
                goto cleanup;
1241
            }
1242 1243 1244 1245

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

1247
            if (vol)
1248 1249 1250 1251
                ret = virGetStorageVol(conn,
                                       driver->pools.objs[i]->def->name,
                                       vol->name,
                                       vol->key);
1252
        }
1253
        virStoragePoolObjUnlock(driver->pools.objs[i]);
1254 1255
    }

1256
    if (!ret)
1257
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
1258 1259 1260
                              "%s", _("no storage vol with matching path"));

cleanup:
1261
    VIR_FREE(cleanpath);
1262
    storageDriverUnlock(driver);
1263
    return ret;
1264 1265
}

1266 1267
static int storageVolumeDelete(virStorageVolPtr obj, unsigned int flags);

1268 1269 1270 1271
static virStorageVolPtr
storageVolumeCreateXML(virStoragePoolPtr obj,
                       const char *xmldesc,
                       unsigned int flags ATTRIBUTE_UNUSED) {
1272 1273
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1274
    virStorageBackendPtr backend;
1275 1276
    virStorageVolDefPtr voldef = NULL;
    virStorageVolPtr ret = NULL, volobj = NULL;
1277

1278
    storageDriverLock(driver);
1279
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1280 1281
    storageDriverUnlock(driver);

1282
    if (!pool) {
1283
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1284
                              "%s", _("no storage pool with matching uuid"));
1285
        goto cleanup;
1286 1287 1288
    }

    if (!virStoragePoolObjIsActive(pool)) {
1289
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
1290
                              "%s", _("storage pool is not active"));
1291
        goto cleanup;
1292 1293 1294
    }

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

1297
    voldef = virStorageVolDefParseString(pool->def, xmldesc);
1298
    if (voldef == NULL)
1299
        goto cleanup;
1300

1301
    if (virStorageVolDefFindByName(pool, voldef->name)) {
1302
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
J
Jim Meyering 已提交
1303
                              "%s", _("storage vol already exists"));
1304
        goto cleanup;
1305 1306
    }

1307 1308
    if (VIR_REALLOC_N(pool->volumes.objs,
                      pool->volumes.count+1) < 0) {
1309
        virReportOOMError();
1310
        goto cleanup;
1311 1312
    }

1313
    if (!backend->createVol) {
1314
        virStorageReportError(VIR_ERR_NO_SUPPORT,
1315 1316
                              "%s", _("storage pool does not support volume "
                                      "creation"));
1317
        goto cleanup;
1318 1319
    }

1320
    if (backend->createVol(obj->conn, pool, voldef) < 0) {
1321
        goto cleanup;
1322 1323
    }

1324 1325 1326
    pool->volumes.objs[pool->volumes.count++] = voldef;
    volobj = virGetStorageVol(obj->conn, pool->def->name, voldef->name,
                              voldef->key);
1327

1328 1329 1330 1331 1332
    if (volobj && backend->buildVol) {
        int buildret;
        virStorageVolDefPtr buildvoldef = NULL;

        if (VIR_ALLOC(buildvoldef) < 0) {
1333
            virReportOOMError();
1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348
            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);

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

1351
        storageDriverLock(driver);
1352
        virStoragePoolObjLock(pool);
1353 1354
        storageDriverUnlock(driver);

1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372
        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;
1373

1374
cleanup:
1375 1376 1377
    if (volobj)
        virUnrefStorageVol(volobj);
    virStorageVolDefFree(voldef);
1378 1379
    if (pool)
        virStoragePoolObjUnlock(pool);
1380
    return ret;
1381 1382
}

1383 1384 1385 1386 1387 1388 1389 1390 1391 1392
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;
1393
    int buildret;
1394 1395 1396

    storageDriverLock(driver);
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1397
    if (pool && STRNEQ(obj->name, vobj->pool)) {
1398
        virStoragePoolObjUnlock(pool);
1399
        origpool = virStoragePoolObjFindByName(&driver->pools, vobj->pool);
1400
        virStoragePoolObjLock(pool);
1401
    }
1402 1403
    storageDriverUnlock(driver);
    if (!pool) {
1404
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
1405 1406 1407 1408
                              "%s", _("no storage pool with matching uuid"));
        goto cleanup;
    }

1409
    if (STRNEQ(obj->name, vobj->pool) && !origpool) {
1410 1411
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
                              _("no storage pool with matching name '%s'"),
1412
                              vobj->pool);
1413 1414 1415 1416
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1417
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
1418 1419 1420 1421
                              "%s", _("storage pool is not active"));
        goto cleanup;
    }

1422
    if (origpool && !virStoragePoolObjIsActive(origpool)) {
1423
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
1424 1425 1426 1427 1428 1429 1430
                              "%s", _("storage pool is not active"));
        goto cleanup;
    }

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

1431
    origvol = virStorageVolDefFindByName(origpool ? origpool : pool, vobj->name);
1432
    if (!origvol) {
1433 1434
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
                              _("no storage vol with matching name '%s'"),
1435
                              vobj->name);
1436 1437 1438
        goto cleanup;
    }

1439
    newvol = virStorageVolDefParseString(pool->def, xmldesc);
1440 1441 1442 1443
    if (newvol == NULL)
        goto cleanup;

    if (virStorageVolDefFindByName(pool, newvol->name)) {
1444
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
1445 1446 1447 1448 1449 1450 1451 1452 1453
                              _("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;

1454 1455 1456 1457 1458
    /* 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;

1459
    if (!backend->buildVolFrom) {
1460
        virStorageReportError(VIR_ERR_NO_SUPPORT,
1461 1462 1463 1464 1465
                              "%s", _("storage pool does not support volume creation from an existing volume"));
        goto cleanup;
    }

    if (origvol->building) {
1466
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477
                              _("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) {
1478
        virReportOOMError();
1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496
        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);

1497
    if (origpool) {
1498 1499 1500 1501
        origpool->asyncjobs++;
        virStoragePoolObjUnlock(origpool);
    }

1502
    buildret = backend->buildVolFrom(obj->conn, pool, newvol, origvol, flags);
1503 1504 1505

    storageDriverLock(driver);
    virStoragePoolObjLock(pool);
1506
    if (origpool)
1507 1508 1509 1510 1511 1512 1513 1514
        virStoragePoolObjLock(origpool);
    storageDriverUnlock(driver);

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

1515
    if (origpool) {
1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536
        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);
1537
    if (origpool)
1538 1539 1540 1541
        virStoragePoolObjUnlock(origpool);
    return ret;
}

1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576

/* If the volume we're wiping is already a sparse file, we simply
 * truncate and extend it to its original size, filling it with
 * zeroes.  This behavior is guaranteed by POSIX:
 *
 * http://www.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html
 *
 * If fildes refers to a regular file, the ftruncate() function shall
 * cause the size of the file to be truncated to length. If the size
 * of the file previously exceeded length, the extra data shall no
 * longer be available to reads on the file. If the file previously
 * was smaller than this size, ftruncate() shall increase the size of
 * the file. If the file size is increased, the extended area shall
 * appear as if it were zero-filled.
 */
static int
storageVolumeZeroSparseFile(virStorageVolDefPtr vol,
                            off_t size,
                            int fd)
{
    int ret = -1;

    ret = ftruncate(fd, 0);
    if (ret == -1) {
        virReportSystemError(errno,
                             _("Failed to truncate volume with "
                               "path '%s' to 0 bytes"),
                             vol->target.path);
        goto out;
    }

    ret = ftruncate(fd, size);
    if (ret == -1) {
        virReportSystemError(errno,
                             _("Failed to truncate volume with "
1577
                               "path '%s' to %ju bytes"),
1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683
                             vol->target.path, (intmax_t)size);
    }

out:
    return ret;
}


static int
storageWipeExtent(virStorageVolDefPtr vol,
                  int fd,
                  off_t extent_start,
                  off_t extent_length,
                  char *writebuf,
                  size_t writebuf_length,
                  size_t *bytes_wiped)
{
    int ret = -1, written = 0;
    off_t remaining = 0;
    size_t write_size = 0;

    VIR_DEBUG("extent logical start: %ju len: %ju",
              (intmax_t)extent_start, (intmax_t)extent_length);

    if ((ret = lseek(fd, extent_start, SEEK_SET)) < 0) {
        virReportSystemError(errno,
                             _("Failed to seek to position %ju in volume "
                               "with path '%s'"),
                             (intmax_t)extent_start, vol->target.path);
        goto out;
    }

    remaining = extent_length;
    while (remaining > 0) {

        write_size = (writebuf_length < remaining) ? writebuf_length : remaining;
        written = safewrite(fd, writebuf, write_size);
        if (written < 0) {
            virReportSystemError(errno,
                                 _("Failed to write %zu bytes to "
                                   "storage volume with path '%s'"),
                                 write_size, vol->target.path);

            goto out;
        }

        *bytes_wiped += written;
        remaining -= written;
    }

    VIR_DEBUG("Wrote %zu bytes to volume with path '%s'",
              *bytes_wiped, vol->target.path);

    ret = 0;

out:
    return ret;
}


static int
storageVolumeWipeInternal(virStorageVolDefPtr def)
{
    int ret = -1, fd = -1;
    struct stat st;
    char *writebuf = NULL;
    size_t bytes_wiped = 0;

    VIR_DEBUG("Wiping volume with path '%s'", def->target.path);

    fd = open(def->target.path, O_RDWR);
    if (fd == -1) {
        virReportSystemError(errno,
                             _("Failed to open storage volume with path '%s'"),
                             def->target.path);
        goto out;
    }

    if (fstat(fd, &st) == -1) {
        virReportSystemError(errno,
                             _("Failed to stat storage volume with path '%s'"),
                             def->target.path);
        goto out;
    }

    if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) {
        ret = storageVolumeZeroSparseFile(def, st.st_size, fd);
    } else {

        if (VIR_ALLOC_N(writebuf, st.st_blksize) != 0) {
            virReportOOMError();
            goto out;
        }

        ret = storageWipeExtent(def,
                                fd,
                                0,
                                def->allocation,
                                writebuf,
                                st.st_blksize,
                                &bytes_wiped);
    }

out:
    VIR_FREE(writebuf);

1684
    VIR_FORCE_CLOSE(fd);
1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698

    return ret;
}


static int
storageVolumeWipe(virStorageVolPtr obj,
                  unsigned int flags)
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    int ret = -1;

1699
    virCheckFlags(0, -1);
1700 1701 1702 1703 1704 1705

    storageDriverLock(driver);
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
    storageDriverUnlock(driver);

    if (!pool) {
1706
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
1707 1708 1709 1710 1711
                              "%s", _("no storage pool with matching uuid"));
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1712
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
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 1740 1741 1742 1743 1744 1745 1746 1747
                              "%s", _("storage pool is not active"));
        goto out;
    }

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

    if (vol == NULL) {
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
                             _("no storage vol with matching name '%s'"),
                              obj->name);
        goto out;
    }

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

    if (storageVolumeWipeInternal(vol) == -1) {
        goto out;
    }

    ret = 0;

out:
    if (pool) {
        virStoragePoolObjUnlock(pool);
    }

    return ret;

}

1748 1749 1750
static int
storageVolumeDelete(virStorageVolPtr obj,
                    unsigned int flags) {
1751 1752
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1753
    virStorageBackendPtr backend;
1754
    virStorageVolDefPtr vol = NULL;
1755
    unsigned int i;
1756
    int ret = -1;
1757

1758
    storageDriverLock(driver);
1759
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
1760 1761
    storageDriverUnlock(driver);

1762
    if (!pool) {
1763
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1764
                              "%s", _("no storage pool with matching uuid"));
1765
        goto cleanup;
1766 1767 1768
    }

    if (!virStoragePoolObjIsActive(pool)) {
1769
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
1770
                              "%s", _("storage pool is not active"));
1771
        goto cleanup;
1772 1773 1774
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
1775
        goto cleanup;
1776 1777 1778 1779

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

    if (!vol) {
1780
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
1781 1782
                             _("no storage vol with matching name '%s'"),
                              obj->name);
1783
        goto cleanup;
1784 1785
    }

1786
    if (vol->building) {
1787
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
1788 1789 1790 1791 1792
                              _("volume '%s' is still being allocated."),
                              vol->name);
        goto cleanup;
    }

1793
    if (!backend->deleteVol) {
1794
        virStorageReportError(VIR_ERR_NO_SUPPORT,
J
Jim Meyering 已提交
1795
                              "%s", _("storage pool does not support vol deletion"));
1796

1797
        goto cleanup;
1798 1799
    }

1800 1801 1802
    if (backend->deleteVol(obj->conn, pool, vol, flags) < 0)
        goto cleanup;

1803 1804 1805
    for (i = 0 ; i < pool->volumes.count ; i++) {
        if (pool->volumes.objs[i] == vol) {
            virStorageVolDefFree(vol);
1806
            vol = NULL;
1807 1808 1809 1810 1811 1812 1813 1814 1815 1816

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

1817 1818 1819
            break;
        }
    }
1820
    ret = 0;
1821

1822
cleanup:
1823 1824
    if (pool)
        virStoragePoolObjUnlock(pool);
1825
    return ret;
1826 1827 1828 1829 1830
}

static int
storageVolumeGetInfo(virStorageVolPtr obj,
                     virStorageVolInfoPtr info) {
1831 1832
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1833 1834
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
1835
    int ret = -1;
1836

1837
    storageDriverLock(driver);
1838
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
1839 1840
    storageDriverUnlock(driver);

1841
    if (!pool) {
1842
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1843
                              "%s", _("no storage pool with matching uuid"));
1844
        goto cleanup;
1845 1846 1847
    }

    if (!virStoragePoolObjIsActive(pool)) {
1848
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
1849
                              "%s", _("storage pool is not active"));
1850
        goto cleanup;
1851 1852 1853 1854 1855
    }

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

    if (!vol) {
1856 1857
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
                              _("no storage vol with matching name '%s'"),
1858
                              obj->name);
1859
        goto cleanup;
1860 1861 1862
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
1863
        goto cleanup;
1864 1865 1866

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

    memset(info, 0, sizeof(*info));
1870
    info->type = vol->type;
1871 1872
    info->capacity = vol->capacity;
    info->allocation = vol->allocation;
1873
    ret = 0;
1874

1875
cleanup:
1876 1877
    if (pool)
        virStoragePoolObjUnlock(pool);
1878
    return ret;
1879 1880 1881 1882 1883
}

static char *
storageVolumeGetXMLDesc(virStorageVolPtr obj,
                        unsigned int flags ATTRIBUTE_UNUSED) {
1884 1885
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1886 1887
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
1888
    char *ret = NULL;
1889

1890
    storageDriverLock(driver);
1891
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
1892 1893
    storageDriverUnlock(driver);

1894
    if (!pool) {
1895
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1896
                              "%s", _("no storage pool with matching uuid"));
1897
        goto cleanup;
1898 1899 1900
    }

    if (!virStoragePoolObjIsActive(pool)) {
1901
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
1902
                              "%s", _("storage pool is not active"));
1903
        goto cleanup;
1904 1905 1906 1907 1908
    }

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

    if (!vol) {
1909
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
1910 1911
                             _("no storage vol with matching name '%s'"),
                              obj->name);
1912
        goto cleanup;
1913 1914 1915
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
1916
        goto cleanup;
1917 1918 1919 1920

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

1922
    ret = virStorageVolDefFormat(pool->def, vol);
1923 1924

cleanup:
1925 1926 1927
    if (pool)
        virStoragePoolObjUnlock(pool);

1928
    return ret;
1929 1930 1931 1932
}

static char *
storageVolumeGetPath(virStorageVolPtr obj) {
1933
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
1934
    virStoragePoolObjPtr pool;
1935
    virStorageVolDefPtr vol;
1936
    char *ret = NULL;
1937

1938 1939 1940
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
    storageDriverUnlock(driver);
1941
    if (!pool) {
1942
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1943
                              "%s", _("no storage pool with matching uuid"));
1944
        goto cleanup;
1945 1946 1947
    }

    if (!virStoragePoolObjIsActive(pool)) {
1948
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
1949
                              "%s", _("storage pool is not active"));
1950
        goto cleanup;
1951 1952 1953 1954 1955
    }

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

    if (!vol) {
1956 1957
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
                              _("no storage vol with matching name '%s'"),
1958
                              obj->name);
1959
        goto cleanup;
1960 1961 1962
    }

    ret = strdup(vol->target.path);
1963
    if (ret == NULL)
1964
        virReportOOMError();
1965 1966

cleanup:
1967 1968
    if (pool)
        virStoragePoolObjUnlock(pool);
1969 1970 1971 1972
    return ret;
}

static virStorageDriver storageDriver = {
1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002
    .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,
2003
    .volCreateXMLFrom = storageVolumeCreateXMLFrom,
2004
    .volDelete = storageVolumeDelete,
2005
    .volWipe = storageVolumeWipe,
2006 2007 2008
    .volGetInfo = storageVolumeGetInfo,
    .volGetXMLDesc = storageVolumeGetXMLDesc,
    .volGetPath = storageVolumeGetPath,
2009 2010 2011

    .poolIsActive = storagePoolIsActive,
    .poolIsPersistent = storagePoolIsPersistent,
2012 2013 2014 2015
};


static virStateDriver stateDriver = {
2016
    .name = "Storage",
2017 2018 2019 2020
    .initialize = storageDriverStartup,
    .cleanup = storageDriverShutdown,
    .reload = storageDriverReload,
    .active = storageDriverActive,
2021 2022 2023 2024 2025 2026 2027
};

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