storage_driver.c 56.6 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 131
storageDriverStartup(int privileged)
{
132 133
    char *base = NULL;

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
    }

    /* Configuration paths are either ~/.libvirt/storage/... (session) or
     * /etc/libvirt/storage/... (system).
     */
163 164
    if (virAsprintf(&driverState->configDir,
                    "%s/storage", base) == -1)
165 166
        goto out_of_memory;

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

171
    VIR_FREE(base);
172

173
    if (virStoragePoolLoadAllConfigs(&driverState->pools,
174
                                     driverState->configDir,
175 176
                                     driverState->autostartDir) < 0)
        goto error;
177 178
    storageDriverAutostart(driverState);

179
    storageDriverUnlock(driverState);
180 181
    return 0;

182
out_of_memory:
183
    virReportOOMError();
184 185 186 187
error:
    VIR_FREE(base);
    storageDriverUnlock(driverState);
    storageDriverShutdown();
188 189 190 191 192 193 194 195 196 197 198
    return -1;
}

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

202
    storageDriverLock(driverState);
203
    virStoragePoolLoadAllConfigs(&driverState->pools,
204 205
                                 driverState->configDir,
                                 driverState->autostartDir);
206
    storageDriverAutostart(driverState);
207
    storageDriverUnlock(driverState);
208 209 210 211 212 213 214 215 216 217 218 219 220

    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) {
221
    unsigned int i;
222
    int active = 0;
223 224 225 226

    if (!driverState)
        return 0;

227 228 229 230
    storageDriverLock(driverState);

    for (i = 0 ; i < driverState->pools.count ; i++) {
        virStoragePoolObjLock(driverState->pools.objs[i]);
231
        if (virStoragePoolObjIsActive(driverState->pools.objs[i]))
232 233 234
            active = 1;
        virStoragePoolObjUnlock(driverState->pools.objs[i]);
    }
235

236 237
    storageDriverUnlock(driverState);
    return active;
238 239 240 241 242 243 244 245 246 247 248 249
}

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

250
    storageDriverLock(driverState);
251 252

    /* free inactive pools */
253 254 255 256
    virStoragePoolObjListFree(&driverState->pools);

    VIR_FREE(driverState->configDir);
    VIR_FREE(driverState->autostartDir);
257
    storageDriverUnlock(driverState);
258
    virMutexDestroy(&driverState->lock);
259
    VIR_FREE(driverState);
260 261 262 263 264 265 266 267 268

    return 0;
}



static virStoragePoolPtr
storagePoolLookupByUUID(virConnectPtr conn,
                        const unsigned char *uuid) {
269 270 271
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
272

273
    storageDriverLock(driver);
274
    pool = virStoragePoolObjFindByUUID(&driver->pools, uuid);
275 276
    storageDriverUnlock(driver);

277
    if (!pool) {
278
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
279
                              "%s", _("no pool with matching uuid"));
280
        goto cleanup;
281 282 283
    }

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

cleanup:
286 287
    if (pool)
        virStoragePoolObjUnlock(pool);
288 289 290 291 292 293
    return ret;
}

static virStoragePoolPtr
storagePoolLookupByName(virConnectPtr conn,
                        const char *name) {
294 295 296
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
297

298
    storageDriverLock(driver);
299
    pool = virStoragePoolObjFindByName(&driver->pools, name);
300 301
    storageDriverUnlock(driver);

302
    if (!pool) {
303
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
304
                              _("no pool with matching name '%s'"), name);
305
        goto cleanup;
306 307 308
    }

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

cleanup:
311 312
    if (pool)
        virStoragePoolObjUnlock(pool);
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
    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) {
340
    virStorageDriverStatePtr driver = conn->storagePrivateData;
341 342
    unsigned int i, nactive = 0;

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

    return nactive;
353 354 355 356 357 358
}

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

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

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

static int
storageNumDefinedPools(virConnectPtr conn) {
388
    virStorageDriverStatePtr driver = conn->storagePrivateData;
389 390
    unsigned int i, nactive = 0;

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

    return nactive;
401 402 403 404 405 406
}

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

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

 cleanup:
427
    storageDriverUnlock(driver);
428
    for (i = 0 ; i < got ; i++) {
429
        VIR_FREE(names[i]);
430
    }
431
    memset(names, 0, nnames * sizeof(*names));
432 433 434
    return -1;
}

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

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

    backend = virStorageBackendForType(backend_type);
    if (backend == NULL)
456
        goto cleanup;
457

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

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

467 468
cleanup:
    return ret;
469 470 471
}


472
static int storagePoolIsActive(virStoragePoolPtr pool)
473
{
474
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
475 476 477 478
    virStoragePoolObjPtr obj;
    int ret = -1;

    storageDriverLock(driver);
479
    obj = virStoragePoolObjFindByUUID(&driver->pools, pool->uuid);
480 481
    storageDriverUnlock(driver);
    if (!obj) {
482
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
483 484 485 486 487 488 489 490 491 492
        goto cleanup;
    }
    ret = virStoragePoolObjIsActive(obj);

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

493
static int storagePoolIsPersistent(virStoragePoolPtr pool)
494
{
495
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
496 497 498 499
    virStoragePoolObjPtr obj;
    int ret = -1;

    storageDriverLock(driver);
500
    obj = virStoragePoolObjFindByUUID(&driver->pools, pool->uuid);
501 502
    storageDriverUnlock(driver);
    if (!obj) {
503
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
504 505 506 507 508 509 510 511 512 513 514
        goto cleanup;
    }
    ret = obj->configFile ? 1 : 0;

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


515 516 517 518
static virStoragePoolPtr
storagePoolCreate(virConnectPtr conn,
                  const char *xml,
                  unsigned int flags ATTRIBUTE_UNUSED) {
519
    virStorageDriverStatePtr driver = conn->storagePrivateData;
520
    virStoragePoolDefPtr def;
521
    virStoragePoolObjPtr pool = NULL;
522
    virStoragePoolPtr ret = NULL;
523 524
    virStorageBackendPtr backend;

525
    storageDriverLock(driver);
526
    if (!(def = virStoragePoolDefParseString(xml)))
527
        goto cleanup;
528

529
    if (virStoragePoolObjIsDuplicate(&driver->pools, def, 1) < 0)
530
        goto cleanup;
531

532 533
    if ((backend = virStorageBackendForType(def->type)) == NULL)
        goto cleanup;
534

535
    if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
536 537
        goto cleanup;
    def = NULL;
538

539
    if (backend->startPool &&
540 541 542
        backend->startPool(conn, pool) < 0) {
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
543
        goto cleanup;
544
    }
545

546 547 548
    if (backend->refreshPool(conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(conn, pool);
549 550
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
551
        goto cleanup;
552 553 554 555 556
    }
    pool->active = 1;

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

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

static virStoragePoolPtr
storagePoolDefine(virConnectPtr conn,
                  const char *xml,
                  unsigned int flags ATTRIBUTE_UNUSED) {
569
    virStorageDriverStatePtr driver = conn->storagePrivateData;
570
    virStoragePoolDefPtr def;
571
    virStoragePoolObjPtr pool = NULL;
572
    virStoragePoolPtr ret = NULL;
573

574
    storageDriverLock(driver);
575
    if (!(def = virStoragePoolDefParseString(xml)))
576
        goto cleanup;
577

578 579 580
    if (virStoragePoolObjIsDuplicate(&driver->pools, def, 0) < 0)
        goto cleanup;

581
    if (virStorageBackendForType(def->type) == NULL)
582
        goto cleanup;
583

584
    if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
585
        goto cleanup;
586

587
    if (virStoragePoolObjSaveDef(driver, pool, def) < 0) {
588
        virStoragePoolObjRemove(&driver->pools, pool);
589
        def = NULL;
590
        goto cleanup;
591
    }
592
    def = NULL;
593 594

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

cleanup:
    virStoragePoolDefFree(def);
598 599 600
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
601 602 603 604 605
    return ret;
}

static int
storagePoolUndefine(virStoragePoolPtr obj) {
606 607 608
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
609

610
    storageDriverLock(driver);
611
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
612
    if (!pool) {
613
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
614
                              "%s", _("no storage pool with matching uuid"));
615
        goto cleanup;
616 617 618
    }

    if (virStoragePoolObjIsActive(pool)) {
619
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
620
                              "%s", _("pool is still active"));
621
        goto cleanup;
622 623
    }

624
    if (pool->asyncjobs > 0) {
625
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
626 627 628 629 630
                              _("pool '%s' has asynchronous jobs running."),
                              pool->def->name);
        goto cleanup;
    }

631
    if (virStoragePoolObjDeleteDef(pool) < 0)
632
        goto cleanup;
633

634 635
    if (unlink(pool->autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
        char ebuf[1024];
636
        VIR_ERROR(_("Failed to delete autostart link '%s': %s"),
637 638
                   pool->autostartLink, virStrerror(errno, ebuf, sizeof ebuf));
    }
639

640 641
    VIR_FREE(pool->configFile);
    VIR_FREE(pool->autostartLink);
642

643
    virStoragePoolObjRemove(&driver->pools, pool);
644
    pool = NULL;
645
    ret = 0;
646

647
cleanup:
648 649 650
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
651
    return ret;
652 653 654 655 656
}

static int
storagePoolStart(virStoragePoolPtr obj,
                 unsigned int flags ATTRIBUTE_UNUSED) {
657 658
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
659
    virStorageBackendPtr backend;
660
    int ret = -1;
661

662
    storageDriverLock(driver);
663
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
664 665
    storageDriverUnlock(driver);

666
    if (!pool) {
667
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
668
                              "%s", _("no storage pool with matching uuid"));
669
        goto cleanup;
670 671
    }

672 673
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
674 675

    if (virStoragePoolObjIsActive(pool)) {
676
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
677
                              "%s", _("pool already active"));
678
        goto cleanup;
679 680 681
    }
    if (backend->startPool &&
        backend->startPool(obj->conn, pool) < 0)
682 683
        goto cleanup;

684 685 686
    if (backend->refreshPool(obj->conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(obj->conn, pool);
687
        goto cleanup;
688 689 690
    }

    pool->active = 1;
691
    ret = 0;
692

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

static int
storagePoolBuild(virStoragePoolPtr obj,
                 unsigned int flags) {
702 703
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
704
    virStorageBackendPtr backend;
705
    int ret = -1;
706

707
    storageDriverLock(driver);
708
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
709 710
    storageDriverUnlock(driver);

711
    if (!pool) {
712
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
713
                              "%s", _("no storage pool with matching uuid"));
714
        goto cleanup;
715 716
    }

717 718
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
719 720

    if (virStoragePoolObjIsActive(pool)) {
721
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
722
                              "%s", _("storage pool is already active"));
723
        goto cleanup;
724 725 726 727
    }

    if (backend->buildPool &&
        backend->buildPool(obj->conn, pool, flags) < 0)
728 729
        goto cleanup;
    ret = 0;
730

731
cleanup:
732 733
    if (pool)
        virStoragePoolObjUnlock(pool);
734
    return ret;
735 736 737 738 739
}


static int
storagePoolDestroy(virStoragePoolPtr obj) {
740 741
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
742
    virStorageBackendPtr backend;
743
    int ret = -1;
744

745
    storageDriverLock(driver);
746
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
747

748
    if (!pool) {
749
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
750
                              "%s", _("no storage pool with matching uuid"));
751
        goto cleanup;
752 753
    }

754 755
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
756 757

    if (!virStoragePoolObjIsActive(pool)) {
758
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
759
                              "%s", _("storage pool is not active"));
760
        goto cleanup;
761 762
    }

763
    if (pool->asyncjobs > 0) {
764
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
765 766 767 768 769
                              _("pool '%s' has asynchronous jobs running."),
                              pool->def->name);
        goto cleanup;
    }

770 771
    if (backend->stopPool &&
        backend->stopPool(obj->conn, pool) < 0)
772
        goto cleanup;
773 774 775 776 777

    virStoragePoolObjClearVols(pool);

    pool->active = 0;

778
    if (pool->configFile == NULL) {
779
        virStoragePoolObjRemove(&driver->pools, pool);
780 781
        pool = NULL;
    }
782
    ret = 0;
783

784
cleanup:
785 786 787
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
788
    return ret;
789 790 791 792 793 794
}


static int
storagePoolDelete(virStoragePoolPtr obj,
                  unsigned int flags) {
795 796
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
797
    virStorageBackendPtr backend;
798
    int ret = -1;
799

800
    storageDriverLock(driver);
801
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
802 803
    storageDriverUnlock(driver);

804
    if (!pool) {
805
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
806
                              "%s", _("no storage pool with matching uuid"));
807
        goto cleanup;
808 809
    }

810 811
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
812 813

    if (virStoragePoolObjIsActive(pool)) {
814
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
815
                              "%s", _("storage pool is still active"));
816
        goto cleanup;
817 818
    }

819
    if (pool->asyncjobs > 0) {
820
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
821 822 823 824 825
                              _("pool '%s' has asynchronous jobs running."),
                              pool->def->name);
        goto cleanup;
    }

826
    if (!backend->deletePool) {
827
        virStorageReportError(VIR_ERR_NO_SUPPORT,
828
                              "%s", _("pool does not support pool deletion"));
829
        goto cleanup;
830 831
    }
    if (backend->deletePool(obj->conn, pool, flags) < 0)
832 833
        goto cleanup;
    ret = 0;
834

835
cleanup:
836 837
    if (pool)
        virStoragePoolObjUnlock(pool);
838
    return ret;
839 840 841 842 843 844
}


static int
storagePoolRefresh(virStoragePoolPtr obj,
                   unsigned int flags ATTRIBUTE_UNUSED) {
845 846
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
847
    virStorageBackendPtr backend;
848
    int ret = -1;
849

850
    storageDriverLock(driver);
851
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
852

853
    if (!pool) {
854
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
855
                              "%s", _("no storage pool with matching uuid"));
856
        goto cleanup;
857 858
    }

859 860
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
861 862

    if (!virStoragePoolObjIsActive(pool)) {
863
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
864
                              "%s", _("storage pool is not active"));
865
        goto cleanup;
866 867
    }

868
    if (pool->asyncjobs > 0) {
869
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
870 871 872 873 874
                              _("pool '%s' has asynchronous jobs running."),
                              pool->def->name);
        goto cleanup;
    }

875
    virStoragePoolObjClearVols(pool);
876
    if (backend->refreshPool(obj->conn, pool) < 0) {
877 878 879 880 881
        if (backend->stopPool)
            backend->stopPool(obj->conn, pool);

        pool->active = 0;

882
        if (pool->configFile == NULL) {
883
            virStoragePoolObjRemove(&driver->pools, pool);
884 885
            pool = NULL;
        }
886
        goto cleanup;
887
    }
888
    ret = 0;
889

890
cleanup:
891 892
    if (pool)
        virStoragePoolObjUnlock(pool);
893
    storageDriverUnlock(driver);
894 895 896 897 898 899 900
    return ret;
}


static int
storagePoolGetInfo(virStoragePoolPtr obj,
                   virStoragePoolInfoPtr info) {
901 902 903
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
904

905
    storageDriverLock(driver);
906
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
907 908
    storageDriverUnlock(driver);

909
    if (!pool) {
910
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
911
                              "%s", _("no storage pool with matching uuid"));
912
        goto cleanup;
913 914
    }

915
    if (virStorageBackendForType(pool->def->type) == NULL)
916
        goto cleanup;
917 918 919 920 921 922 923 924 925

    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;
926
    ret = 0;
927

928
cleanup:
929 930
    if (pool)
        virStoragePoolObjUnlock(pool);
931
    return ret;
932 933 934 935 936
}

static char *
storagePoolDumpXML(virStoragePoolPtr obj,
                   unsigned int flags ATTRIBUTE_UNUSED) {
937 938 939
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    char *ret = NULL;
940

941
    storageDriverLock(driver);
942
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
943 944
    storageDriverUnlock(driver);

945
    if (!pool) {
946
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
947
                              "%s", _("no storage pool with matching uuid"));
948
        goto cleanup;
949 950
    }

951
    ret = virStoragePoolDefFormat(pool->def);
952 953

cleanup:
954 955
    if (pool)
        virStoragePoolObjUnlock(pool);
956
    return ret;
957 958 959 960 961
}

static int
storagePoolGetAutostart(virStoragePoolPtr obj,
                        int *autostart) {
962 963 964
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
965

966
    storageDriverLock(driver);
967
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
968 969
    storageDriverUnlock(driver);

970
    if (!pool) {
971
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
972
                              "%s", _("no pool with matching uuid"));
973
        goto cleanup;
974 975 976 977 978 979 980
    }

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

983
cleanup:
984 985
    if (pool)
        virStoragePoolObjUnlock(pool);
986
    return ret;
987 988 989 990 991
}

static int
storagePoolSetAutostart(virStoragePoolPtr obj,
                        int autostart) {
992 993 994
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
995

996
    storageDriverLock(driver);
997
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
998

999
    if (!pool) {
1000
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1001
                              "%s", _("no pool with matching uuid"));
1002
        goto cleanup;
1003 1004 1005
    }

    if (!pool->configFile) {
1006
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1007
                              "%s", _("pool has no config file"));
1008
        goto cleanup;
1009 1010 1011 1012
    }

    autostart = (autostart != 0);

1013 1014 1015
    if (pool->autostart != autostart) {
        if (autostart) {
            int err;
1016

1017
            if ((err = virFileMakePath(driver->autostartDir))) {
1018
                virReportSystemError(err,
1019 1020
                                     _("cannot create autostart directory %s"),
                                     driver->autostartDir);
1021 1022
                goto cleanup;
            }
1023

1024
            if (symlink(pool->configFile, pool->autostartLink) < 0) {
1025
                virReportSystemError(errno,
1026 1027
                                     _("Failed to create symlink '%s' to '%s'"),
                                     pool->autostartLink, pool->configFile);
1028 1029 1030 1031 1032
                goto cleanup;
            }
        } else {
            if (unlink(pool->autostartLink) < 0 &&
                errno != ENOENT && errno != ENOTDIR) {
1033
                virReportSystemError(errno,
1034 1035
                                     _("Failed to delete symlink '%s'"),
                                     pool->autostartLink);
1036 1037
                goto cleanup;
            }
1038
        }
1039
        pool->autostart = autostart;
1040
    }
1041
    ret = 0;
1042

1043
cleanup:
1044 1045
    if (pool)
        virStoragePoolObjUnlock(pool);
1046
    storageDriverUnlock(driver);
1047
    return ret;
1048 1049 1050 1051 1052
}


static int
storagePoolNumVolumes(virStoragePoolPtr obj) {
1053 1054 1055
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
1056

1057
    storageDriverLock(driver);
1058
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1059 1060
    storageDriverUnlock(driver);

1061
    if (!pool) {
1062
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1063
                              "%s", _("no storage pool with matching uuid"));
1064
        goto cleanup;
1065 1066 1067
    }

    if (!virStoragePoolObjIsActive(pool)) {
1068
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
1069
                              "%s", _("storage pool is not active"));
1070
        goto cleanup;
1071
    }
1072
    ret = pool->volumes.count;
1073

1074
cleanup:
1075 1076
    if (pool)
        virStoragePoolObjUnlock(pool);
1077
    return ret;
1078 1079 1080 1081 1082 1083
}

static int
storagePoolListVolumes(virStoragePoolPtr obj,
                       char **const names,
                       int maxnames) {
1084 1085
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1086
    int i, n = 0;
1087

1088 1089
    memset(names, 0, maxnames * sizeof(*names));

1090
    storageDriverLock(driver);
1091
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1092 1093
    storageDriverUnlock(driver);

1094
    if (!pool) {
1095
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1096
                              "%s", _("no storage pool with matching uuid"));
1097
        goto cleanup;
1098 1099 1100
    }

    if (!virStoragePoolObjIsActive(pool)) {
1101
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
1102
                              "%s", _("storage pool is not active"));
1103
        goto cleanup;
1104 1105
    }

1106 1107
    for (i = 0 ; i < pool->volumes.count && n < maxnames ; i++) {
        if ((names[n++] = strdup(pool->volumes.objs[i]->name)) == NULL) {
1108
            virReportOOMError();
1109 1110 1111 1112
            goto cleanup;
        }
    }

1113
    virStoragePoolObjUnlock(pool);
1114
    return n;
1115 1116

 cleanup:
1117 1118
    if (pool)
        virStoragePoolObjUnlock(pool);
1119
    for (n = 0 ; n < maxnames ; n++)
1120
        VIR_FREE(names[n]);
1121

1122
    memset(names, 0, maxnames * sizeof(*names));
1123 1124 1125 1126 1127 1128 1129
    return -1;
}


static virStorageVolPtr
storageVolumeLookupByName(virStoragePoolPtr obj,
                          const char *name) {
1130 1131
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1132
    virStorageVolDefPtr vol;
1133
    virStorageVolPtr ret = NULL;
1134

1135
    storageDriverLock(driver);
1136
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1137 1138
    storageDriverUnlock(driver);

1139
    if (!pool) {
1140
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1141
                              "%s", _("no storage pool with matching uuid"));
1142
        goto cleanup;
1143 1144 1145
    }

    if (!virStoragePoolObjIsActive(pool)) {
1146
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
1147
                              "%s", _("storage pool is not active"));
1148
        goto cleanup;
1149 1150 1151 1152 1153
    }

    vol = virStorageVolDefFindByName(pool, name);

    if (!vol) {
1154 1155
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
                              _("no storage vol with matching name '%s'"),
1156
                              name);
1157
        goto cleanup;
1158 1159
    }

1160 1161 1162
    ret = virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key);

cleanup:
1163 1164
    if (pool)
        virStoragePoolObjUnlock(pool);
1165
    return ret;
1166 1167 1168 1169 1170 1171
}


static virStorageVolPtr
storageVolumeLookupByKey(virConnectPtr conn,
                         const char *key) {
1172
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1173
    unsigned int i;
1174
    virStorageVolPtr ret = NULL;
1175

1176 1177 1178
    storageDriverLock(driver);
    for (i = 0 ; i < driver->pools.count && !ret ; i++) {
        virStoragePoolObjLock(driver->pools.objs[i]);
1179 1180 1181
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
            virStorageVolDefPtr vol =
                virStorageVolDefFindByKey(driver->pools.objs[i], key);
1182

1183
            if (vol)
1184
                ret = virGetStorageVol(conn,
1185 1186 1187
                                       driver->pools.objs[i]->def->name,
                                       vol->name,
                                       vol->key);
1188
        }
1189
        virStoragePoolObjUnlock(driver->pools.objs[i]);
1190
    }
1191
    storageDriverUnlock(driver);
1192

1193
    if (!ret)
1194
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
1195 1196 1197
                              "%s", _("no storage vol with matching key"));

    return ret;
1198 1199 1200 1201 1202
}

static virStorageVolPtr
storageVolumeLookupByPath(virConnectPtr conn,
                          const char *path) {
1203
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1204
    unsigned int i;
1205
    virStorageVolPtr ret = NULL;
1206 1207 1208 1209 1210
    char *cleanpath;

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

1212 1213 1214
    storageDriverLock(driver);
    for (i = 0 ; i < driver->pools.count && !ret ; i++) {
        virStoragePoolObjLock(driver->pools.objs[i]);
1215
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
1216
            virStorageVolDefPtr vol;
1217 1218
            const char *stable_path;

1219
            stable_path = virStorageBackendStablePath(driver->pools.objs[i],
1220
                                                      cleanpath);
1221 1222 1223 1224 1225
            /*
             * virStorageBackendStablePath already does
             * virStorageReportError if it fails; we just need to keep
             * propagating the return code
             */
1226 1227
            if (stable_path == NULL) {
                virStoragePoolObjUnlock(driver->pools.objs[i]);
1228
                goto cleanup;
1229
            }
1230 1231 1232 1233

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

1235
            if (vol)
1236 1237 1238 1239
                ret = virGetStorageVol(conn,
                                       driver->pools.objs[i]->def->name,
                                       vol->name,
                                       vol->key);
1240
        }
1241
        virStoragePoolObjUnlock(driver->pools.objs[i]);
1242 1243
    }

1244
    if (!ret)
1245
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
1246 1247 1248
                              "%s", _("no storage vol with matching path"));

cleanup:
1249
    VIR_FREE(cleanpath);
1250
    storageDriverUnlock(driver);
1251
    return ret;
1252 1253
}

1254 1255
static int storageVolumeDelete(virStorageVolPtr obj, unsigned int flags);

1256 1257 1258 1259
static virStorageVolPtr
storageVolumeCreateXML(virStoragePoolPtr obj,
                       const char *xmldesc,
                       unsigned int flags ATTRIBUTE_UNUSED) {
1260 1261
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1262
    virStorageBackendPtr backend;
1263 1264
    virStorageVolDefPtr voldef = NULL;
    virStorageVolPtr ret = NULL, volobj = NULL;
1265

1266
    storageDriverLock(driver);
1267
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1268 1269
    storageDriverUnlock(driver);

1270
    if (!pool) {
1271
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1272
                              "%s", _("no storage pool with matching uuid"));
1273
        goto cleanup;
1274 1275 1276
    }

    if (!virStoragePoolObjIsActive(pool)) {
1277
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
1278
                              "%s", _("storage pool is not active"));
1279
        goto cleanup;
1280 1281 1282
    }

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

1285
    voldef = virStorageVolDefParseString(pool->def, xmldesc);
1286
    if (voldef == NULL)
1287
        goto cleanup;
1288

1289
    if (virStorageVolDefFindByName(pool, voldef->name)) {
1290
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
J
Jim Meyering 已提交
1291
                              "%s", _("storage vol already exists"));
1292
        goto cleanup;
1293 1294
    }

1295 1296
    if (VIR_REALLOC_N(pool->volumes.objs,
                      pool->volumes.count+1) < 0) {
1297
        virReportOOMError();
1298
        goto cleanup;
1299 1300
    }

1301
    if (!backend->createVol) {
1302
        virStorageReportError(VIR_ERR_NO_SUPPORT,
1303 1304
                              "%s", _("storage pool does not support volume "
                                      "creation"));
1305
        goto cleanup;
1306 1307
    }

1308
    if (backend->createVol(obj->conn, pool, voldef) < 0) {
1309
        goto cleanup;
1310 1311
    }

1312 1313 1314
    pool->volumes.objs[pool->volumes.count++] = voldef;
    volobj = virGetStorageVol(obj->conn, pool->def->name, voldef->name,
                              voldef->key);
1315

1316 1317 1318 1319 1320
    if (volobj && backend->buildVol) {
        int buildret;
        virStorageVolDefPtr buildvoldef = NULL;

        if (VIR_ALLOC(buildvoldef) < 0) {
1321
            virReportOOMError();
1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336
            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);

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

1339
        storageDriverLock(driver);
1340
        virStoragePoolObjLock(pool);
1341 1342
        storageDriverUnlock(driver);

1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360
        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;
1361

1362
cleanup:
1363 1364 1365
    if (volobj)
        virUnrefStorageVol(volobj);
    virStorageVolDefFree(voldef);
1366 1367
    if (pool)
        virStoragePoolObjUnlock(pool);
1368
    return ret;
1369 1370
}

1371 1372 1373 1374 1375 1376 1377 1378 1379 1380
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;
1381
    int buildret;
1382 1383 1384

    storageDriverLock(driver);
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1385
    if (pool && STRNEQ(obj->name, vobj->pool)) {
1386
        virStoragePoolObjUnlock(pool);
1387
        origpool = virStoragePoolObjFindByName(&driver->pools, vobj->pool);
1388
        virStoragePoolObjLock(pool);
1389
    }
1390 1391
    storageDriverUnlock(driver);
    if (!pool) {
1392
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
1393 1394 1395 1396
                              "%s", _("no storage pool with matching uuid"));
        goto cleanup;
    }

1397
    if (STRNEQ(obj->name, vobj->pool) && !origpool) {
1398 1399
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
                              _("no storage pool with matching name '%s'"),
1400
                              vobj->pool);
1401 1402 1403 1404
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1405
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
1406 1407 1408 1409
                              "%s", _("storage pool is not active"));
        goto cleanup;
    }

1410
    if (origpool && !virStoragePoolObjIsActive(origpool)) {
1411
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
1412 1413 1414 1415 1416 1417 1418
                              "%s", _("storage pool is not active"));
        goto cleanup;
    }

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

1419
    origvol = virStorageVolDefFindByName(origpool ? origpool : pool, vobj->name);
1420
    if (!origvol) {
1421 1422
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
                              _("no storage vol with matching name '%s'"),
1423
                              vobj->name);
1424 1425 1426
        goto cleanup;
    }

1427
    newvol = virStorageVolDefParseString(pool->def, xmldesc);
1428 1429 1430 1431
    if (newvol == NULL)
        goto cleanup;

    if (virStorageVolDefFindByName(pool, newvol->name)) {
1432
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
1433 1434 1435 1436 1437 1438 1439 1440 1441
                              _("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;

1442 1443 1444 1445 1446
    /* 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;

1447
    if (!backend->buildVolFrom) {
1448
        virStorageReportError(VIR_ERR_NO_SUPPORT,
1449 1450 1451 1452 1453
                              "%s", _("storage pool does not support volume creation from an existing volume"));
        goto cleanup;
    }

    if (origvol->building) {
1454
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465
                              _("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) {
1466
        virReportOOMError();
1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484
        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);

1485
    if (origpool) {
1486 1487 1488 1489
        origpool->asyncjobs++;
        virStoragePoolObjUnlock(origpool);
    }

1490
    buildret = backend->buildVolFrom(obj->conn, pool, newvol, origvol, flags);
1491 1492 1493

    storageDriverLock(driver);
    virStoragePoolObjLock(pool);
1494
    if (origpool)
1495 1496 1497 1498 1499 1500 1501 1502
        virStoragePoolObjLock(origpool);
    storageDriverUnlock(driver);

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

1503
    if (origpool) {
1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524
        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);
1525
    if (origpool)
1526 1527 1528 1529
        virStoragePoolObjUnlock(origpool);
    return ret;
}

1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564

/* 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 "
1565
                               "path '%s' to %ju bytes"),
E
Eric Blake 已提交
1566
                             vol->target.path, (uintmax_t)size);
1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587
    }

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",
E
Eric Blake 已提交
1588
              (uintmax_t)extent_start, (uintmax_t)extent_length);
1589 1590 1591 1592 1593

    if ((ret = lseek(fd, extent_start, SEEK_SET)) < 0) {
        virReportSystemError(errno,
                             _("Failed to seek to position %ju in volume "
                               "with path '%s'"),
E
Eric Blake 已提交
1594
                             (uintmax_t)extent_start, vol->target.path);
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
        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);

1672
    VIR_FORCE_CLOSE(fd);
1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686

    return ret;
}


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

1687
    virCheckFlags(0, -1);
1688 1689 1690 1691 1692 1693

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

    if (!pool) {
1694
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
1695 1696 1697 1698 1699
                              "%s", _("no storage pool with matching uuid"));
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1700
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
1701 1702 1703 1704 1705 1706 1707 1708 1709 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
                              "%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;

}

1736 1737 1738
static int
storageVolumeDelete(virStorageVolPtr obj,
                    unsigned int flags) {
1739 1740
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1741
    virStorageBackendPtr backend;
1742
    virStorageVolDefPtr vol = NULL;
1743
    unsigned int i;
1744
    int ret = -1;
1745

1746
    storageDriverLock(driver);
1747
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
1748 1749
    storageDriverUnlock(driver);

1750
    if (!pool) {
1751
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1752
                              "%s", _("no storage pool with matching uuid"));
1753
        goto cleanup;
1754 1755 1756
    }

    if (!virStoragePoolObjIsActive(pool)) {
1757
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
1758
                              "%s", _("storage pool is not active"));
1759
        goto cleanup;
1760 1761 1762
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
1763
        goto cleanup;
1764 1765 1766 1767

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

    if (!vol) {
1768
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
1769 1770
                             _("no storage vol with matching name '%s'"),
                              obj->name);
1771
        goto cleanup;
1772 1773
    }

1774
    if (vol->building) {
1775
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
1776 1777 1778 1779 1780
                              _("volume '%s' is still being allocated."),
                              vol->name);
        goto cleanup;
    }

1781
    if (!backend->deleteVol) {
1782
        virStorageReportError(VIR_ERR_NO_SUPPORT,
J
Jim Meyering 已提交
1783
                              "%s", _("storage pool does not support vol deletion"));
1784

1785
        goto cleanup;
1786 1787
    }

1788 1789 1790
    if (backend->deleteVol(obj->conn, pool, vol, flags) < 0)
        goto cleanup;

1791 1792 1793
    for (i = 0 ; i < pool->volumes.count ; i++) {
        if (pool->volumes.objs[i] == vol) {
            virStorageVolDefFree(vol);
1794
            vol = NULL;
1795 1796 1797 1798 1799 1800 1801 1802 1803 1804

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

1805 1806 1807
            break;
        }
    }
1808
    ret = 0;
1809

1810
cleanup:
1811 1812
    if (pool)
        virStoragePoolObjUnlock(pool);
1813
    return ret;
1814 1815 1816 1817 1818
}

static int
storageVolumeGetInfo(virStorageVolPtr obj,
                     virStorageVolInfoPtr info) {
1819 1820
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1821 1822
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
1823
    int ret = -1;
1824

1825
    storageDriverLock(driver);
1826
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
1827 1828
    storageDriverUnlock(driver);

1829
    if (!pool) {
1830
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1831
                              "%s", _("no storage pool with matching uuid"));
1832
        goto cleanup;
1833 1834 1835
    }

    if (!virStoragePoolObjIsActive(pool)) {
1836
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
1837
                              "%s", _("storage pool is not active"));
1838
        goto cleanup;
1839 1840 1841 1842 1843
    }

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

    if (!vol) {
1844 1845
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
                              _("no storage vol with matching name '%s'"),
1846
                              obj->name);
1847
        goto cleanup;
1848 1849 1850
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
1851
        goto cleanup;
1852 1853 1854

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

    memset(info, 0, sizeof(*info));
1858
    info->type = vol->type;
1859 1860
    info->capacity = vol->capacity;
    info->allocation = vol->allocation;
1861
    ret = 0;
1862

1863
cleanup:
1864 1865
    if (pool)
        virStoragePoolObjUnlock(pool);
1866
    return ret;
1867 1868 1869 1870 1871
}

static char *
storageVolumeGetXMLDesc(virStorageVolPtr obj,
                        unsigned int flags ATTRIBUTE_UNUSED) {
1872 1873
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1874 1875
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
1876
    char *ret = NULL;
1877

1878
    storageDriverLock(driver);
1879
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
1880 1881
    storageDriverUnlock(driver);

1882
    if (!pool) {
1883
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1884
                              "%s", _("no storage pool with matching uuid"));
1885
        goto cleanup;
1886 1887 1888
    }

    if (!virStoragePoolObjIsActive(pool)) {
1889
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
1890
                              "%s", _("storage pool is not active"));
1891
        goto cleanup;
1892 1893 1894 1895 1896
    }

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

    if (!vol) {
1897
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
1898 1899
                             _("no storage vol with matching name '%s'"),
                              obj->name);
1900
        goto cleanup;
1901 1902 1903
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
1904
        goto cleanup;
1905 1906 1907 1908

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

1910
    ret = virStorageVolDefFormat(pool->def, vol);
1911 1912

cleanup:
1913 1914 1915
    if (pool)
        virStoragePoolObjUnlock(pool);

1916
    return ret;
1917 1918 1919 1920
}

static char *
storageVolumeGetPath(virStorageVolPtr obj) {
1921
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
1922
    virStoragePoolObjPtr pool;
1923
    virStorageVolDefPtr vol;
1924
    char *ret = NULL;
1925

1926 1927 1928
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
    storageDriverUnlock(driver);
1929
    if (!pool) {
1930
        virStorageReportError(VIR_ERR_NO_STORAGE_POOL,
J
Jim Meyering 已提交
1931
                              "%s", _("no storage pool with matching uuid"));
1932
        goto cleanup;
1933 1934 1935
    }

    if (!virStoragePoolObjIsActive(pool)) {
1936
        virStorageReportError(VIR_ERR_OPERATION_INVALID,
J
Jim Meyering 已提交
1937
                              "%s", _("storage pool is not active"));
1938
        goto cleanup;
1939 1940 1941 1942 1943
    }

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

    if (!vol) {
1944 1945
        virStorageReportError(VIR_ERR_NO_STORAGE_VOL,
                              _("no storage vol with matching name '%s'"),
1946
                              obj->name);
1947
        goto cleanup;
1948 1949 1950
    }

    ret = strdup(vol->target.path);
1951
    if (ret == NULL)
1952
        virReportOOMError();
1953 1954

cleanup:
1955 1956
    if (pool)
        virStoragePoolObjUnlock(pool);
1957 1958 1959 1960
    return ret;
}

static virStorageDriver storageDriver = {
1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990
    .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,
1991
    .volCreateXMLFrom = storageVolumeCreateXMLFrom,
1992 1993
    .volDownload = NULL,
    .volUpload = NULL,
1994
    .volDelete = storageVolumeDelete,
1995
    .volWipe = storageVolumeWipe,
1996 1997 1998
    .volGetInfo = storageVolumeGetInfo,
    .volGetXMLDesc = storageVolumeGetXMLDesc,
    .volGetPath = storageVolumeGetPath,
1999 2000 2001

    .poolIsActive = storagePoolIsActive,
    .poolIsPersistent = storagePoolIsPersistent,
2002 2003 2004 2005
};


static virStateDriver stateDriver = {
2006
    .name = "Storage",
2007 2008 2009 2010
    .initialize = storageDriverStartup,
    .cleanup = storageDriverShutdown,
    .reload = storageDriverReload,
    .active = storageDriverActive,
2011 2012 2013 2014 2015 2016 2017
};

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