storage_driver.c 68.8 KB
Newer Older
1 2 3
/*
 * storage_driver.c: core driver for storage APIs
 *
4
 * Copyright (C) 2006-2012 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17
 * 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
18
 * License along with this library.  If not, see
O
Osier Yang 已提交
19
 * <http://www.gnu.org/licenses/>.
20 21 22 23 24 25 26 27 28
 *
 * 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 "virerror.h"
40
#include "datatypes.h"
41 42 43
#include "driver.h"
#include "storage_driver.h"
#include "storage_conf.h"
44
#include "viralloc.h"
45
#include "storage_backend.h"
46
#include "virlog.h"
E
Eric Blake 已提交
47
#include "virfile.h"
48
#include "fdstream.h"
49
#include "configmake.h"
50
#include "virstring.h"
51

52 53
#define VIR_FROM_THIS VIR_FROM_STORAGE

54 55
static virStorageDriverStatePtr driverState;

56
static int storageStateCleanup(void);
57

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

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

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

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

83 84 85 86 87 88 89 90 91 92 93 94 95
        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)) {
96 97 98
            if (backend->startPool &&
                backend->startPool(NULL, pool) < 0) {
                virErrorPtr err = virGetLastError();
99
                VIR_ERROR(_("Failed to autostart storage pool '%s': %s"),
100
                          pool->def->name, err ? err->message :
101
                          _("no error message found"));
102
                virStoragePoolObjUnlock(pool);
103 104
                continue;
            }
105 106
            started = true;
        }
107

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

/**
 * virStorageStartup:
 *
 * Initialization function for the QEmu daemon
 */
static int
131 132 133
storageStateInitialize(bool privileged,
                       virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                       void *opaque ATTRIBUTE_UNUSED)
134
{
135 136
    char *base = NULL;

137
    if (VIR_ALLOC(driverState) < 0)
138 139
        return -1;

140 141 142 143
    if (virMutexInit(&driverState->lock) < 0) {
        VIR_FREE(driverState);
        return -1;
    }
144 145
    storageDriverLock(driverState);

146
    if (privileged) {
147 148
        if (VIR_STRDUP(base, SYSCONFDIR "/libvirt") < 0)
            goto error;
149
    } else {
150
        base = virGetUserConfigDirectory();
151
        if (!base)
152
            goto error;
153 154
    }

155
    /* Configuration paths are either $USER_CONFIG_HOME/libvirt/storage/... (session) or
156 157
     * /etc/libvirt/storage/... (system).
     */
158 159
    if (virAsprintf(&driverState->configDir,
                    "%s/storage", base) == -1)
160 161
        goto out_of_memory;

162 163
    if (virAsprintf(&driverState->autostartDir,
                    "%s/storage/autostart", base) == -1)
164 165
        goto out_of_memory;

166
    VIR_FREE(base);
167

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

174
    storageDriverUnlock(driverState);
175 176
    return 0;

177
out_of_memory:
178
    virReportOOMError();
179 180 181
error:
    VIR_FREE(base);
    storageDriverUnlock(driverState);
182
    storageStateCleanup();
183 184 185 186
    return -1;
}

/**
187
 * storageStateReload:
188 189 190 191 192
 *
 * Function to restart the storage driver, it will recheck the configuration
 * files and update its state
 */
static int
193
storageStateReload(void) {
194 195 196
    if (!driverState)
        return -1;

197
    storageDriverLock(driverState);
198
    virStoragePoolLoadAllConfigs(&driverState->pools,
199 200
                                 driverState->configDir,
                                 driverState->autostartDir);
201
    storageDriverAutostart(driverState);
202
    storageDriverUnlock(driverState);
203 204 205 206 207 208

    return 0;
}


/**
209
 * storageStateCleanup
210 211 212 213
 *
 * Shutdown the storage driver, it will stop all active storage pools
 */
static int
214
storageStateCleanup(void) {
215 216 217
    if (!driverState)
        return -1;

218
    storageDriverLock(driverState);
219 220

    /* free inactive pools */
221 222 223 224
    virStoragePoolObjListFree(&driverState->pools);

    VIR_FREE(driverState->configDir);
    VIR_FREE(driverState->autostartDir);
225
    storageDriverUnlock(driverState);
226
    virMutexDestroy(&driverState->lock);
227
    VIR_FREE(driverState);
228 229 230 231 232 233 234 235 236

    return 0;
}



static virStoragePoolPtr
storagePoolLookupByUUID(virConnectPtr conn,
                        const unsigned char *uuid) {
237 238 239
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
240

241
    storageDriverLock(driver);
242
    pool = virStoragePoolObjFindByUUID(&driver->pools, uuid);
243 244
    storageDriverUnlock(driver);

245
    if (!pool) {
246
        virReportError(VIR_ERR_NO_STORAGE_POOL,
247
                       _("no storage pool with matching uuid %s"), uuid);
248
        goto cleanup;
249 250
    }

251 252
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
253 254

cleanup:
255 256
    if (pool)
        virStoragePoolObjUnlock(pool);
257 258 259 260 261 262
    return ret;
}

static virStoragePoolPtr
storagePoolLookupByName(virConnectPtr conn,
                        const char *name) {
263 264 265
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
266

267
    storageDriverLock(driver);
268
    pool = virStoragePoolObjFindByName(&driver->pools, name);
269 270
    storageDriverUnlock(driver);

271
    if (!pool) {
272
        virReportError(VIR_ERR_NO_STORAGE_POOL,
273
                       _("no storage pool with matching name '%s'"), name);
274
        goto cleanup;
275 276
    }

277 278
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
279 280

cleanup:
281 282
    if (pool)
        virStoragePoolObjUnlock(pool);
283 284 285 286 287 288 289 290 291 292 293
    return ret;
}

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

static virDrvOpenStatus
storageOpen(virConnectPtr conn,
            virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
294 295 296 297
            unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

298 299 300 301 302 303 304 305 306 307 308 309 310 311
    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
312
storageConnectNumOfStoragePools(virConnectPtr conn) {
313
    virStorageDriverStatePtr driver = conn->storagePrivateData;
314 315
    unsigned int i, nactive = 0;

316
    storageDriverLock(driver);
317
    for (i = 0; i < driver->pools.count; i++) {
318
        virStoragePoolObjLock(driver->pools.objs[i]);
319 320
        if (virStoragePoolObjIsActive(driver->pools.objs[i]))
            nactive++;
321 322 323
        virStoragePoolObjUnlock(driver->pools.objs[i]);
    }
    storageDriverUnlock(driver);
324 325

    return nactive;
326 327 328
}

static int
329 330 331
storageConnectListStoragePools(virConnectPtr conn,
                               char **const names,
                               int nnames) {
332
    virStorageDriverStatePtr driver = conn->storagePrivateData;
333
    int got = 0, i;
334

335
    storageDriverLock(driver);
336
    for (i = 0; i < driver->pools.count && got < nnames; i++) {
337
        virStoragePoolObjLock(driver->pools.objs[i]);
338
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
339
            if (VIR_STRDUP(names[got], driver->pools.objs[i]->def->name) < 0) {
340
                virStoragePoolObjUnlock(driver->pools.objs[i]);
341 342 343 344
                goto cleanup;
            }
            got++;
        }
345
        virStoragePoolObjUnlock(driver->pools.objs[i]);
346
    }
347
    storageDriverUnlock(driver);
348 349 350
    return got;

 cleanup:
351
    storageDriverUnlock(driver);
352
    for (i = 0; i < got; i++)
353
        VIR_FREE(names[i]);
354
    memset(names, 0, nnames * sizeof(*names));
355 356 357 358
    return -1;
}

static int
359
storageConnectNumOfDefinedStoragePools(virConnectPtr conn) {
360
    virStorageDriverStatePtr driver = conn->storagePrivateData;
361 362
    unsigned int i, nactive = 0;

363
    storageDriverLock(driver);
364
    for (i = 0; i < driver->pools.count; i++) {
365
        virStoragePoolObjLock(driver->pools.objs[i]);
366 367
        if (!virStoragePoolObjIsActive(driver->pools.objs[i]))
            nactive++;
368 369 370
        virStoragePoolObjUnlock(driver->pools.objs[i]);
    }
    storageDriverUnlock(driver);
371 372

    return nactive;
373 374 375
}

static int
376 377 378
storageConnectListDefinedStoragePools(virConnectPtr conn,
                                      char **const names,
                                      int nnames) {
379
    virStorageDriverStatePtr driver = conn->storagePrivateData;
380
    int got = 0, i;
381

382
    storageDriverLock(driver);
383
    for (i = 0; i < driver->pools.count && got < nnames; i++) {
384
        virStoragePoolObjLock(driver->pools.objs[i]);
385
        if (!virStoragePoolObjIsActive(driver->pools.objs[i])) {
386
            if (VIR_STRDUP(names[got], driver->pools.objs[i]->def->name) < 0) {
387
                virStoragePoolObjUnlock(driver->pools.objs[i]);
388 389 390 391
                goto cleanup;
            }
            got++;
        }
392
        virStoragePoolObjUnlock(driver->pools.objs[i]);
393
    }
394
    storageDriverUnlock(driver);
395 396 397
    return got;

 cleanup:
398
    storageDriverUnlock(driver);
399
    for (i = 0; i < got; i++) {
400
        VIR_FREE(names[i]);
401
    }
402
    memset(names, 0, nnames * sizeof(*names));
403 404 405
    return -1;
}

406 407
/* This method is required to be re-entrant / thread safe, so
   uses no driver lock */
408
static char *
409 410 411 412
storageConnectFindStoragePoolSources(virConnectPtr conn,
                                     const char *type,
                                     const char *srcSpec,
                                     unsigned int flags)
413 414 415
{
    int backend_type;
    virStorageBackendPtr backend;
416
    char *ret = NULL;
417

418
    backend_type = virStoragePoolTypeFromString(type);
419
    if (backend_type < 0) {
420 421
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
422
        goto cleanup;
423
    }
424 425 426

    backend = virStorageBackendForType(backend_type);
    if (backend == NULL)
427
        goto cleanup;
428

429
    if (!backend->findPoolSources) {
430 431 432
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source "
                         "discovery"), type);
433 434 435 436
        goto cleanup;
    }

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

438 439
cleanup:
    return ret;
440 441 442
}


443
static int storagePoolIsActive(virStoragePoolPtr pool)
444
{
445
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
446 447 448 449
    virStoragePoolObjPtr obj;
    int ret = -1;

    storageDriverLock(driver);
450
    obj = virStoragePoolObjFindByUUID(&driver->pools, pool->uuid);
451 452
    storageDriverUnlock(driver);
    if (!obj) {
453
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
454 455 456 457 458 459 460 461 462 463
        goto cleanup;
    }
    ret = virStoragePoolObjIsActive(obj);

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

464
static int storagePoolIsPersistent(virStoragePoolPtr pool)
465
{
466
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
467 468 469 470
    virStoragePoolObjPtr obj;
    int ret = -1;

    storageDriverLock(driver);
471
    obj = virStoragePoolObjFindByUUID(&driver->pools, pool->uuid);
472 473
    storageDriverUnlock(driver);
    if (!obj) {
474
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
475 476 477 478 479 480 481 482 483 484 485
        goto cleanup;
    }
    ret = obj->configFile ? 1 : 0;

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


486
static virStoragePoolPtr
487 488 489
storagePoolCreateXML(virConnectPtr conn,
                     const char *xml,
                     unsigned int flags)
E
Eric Blake 已提交
490
{
491
    virStorageDriverStatePtr driver = conn->storagePrivateData;
492
    virStoragePoolDefPtr def;
493
    virStoragePoolObjPtr pool = NULL;
494
    virStoragePoolPtr ret = NULL;
495 496
    virStorageBackendPtr backend;

E
Eric Blake 已提交
497 498
    virCheckFlags(0, NULL);

499
    storageDriverLock(driver);
500
    if (!(def = virStoragePoolDefParseString(xml)))
501
        goto cleanup;
502

503
    if (virStoragePoolObjIsDuplicate(&driver->pools, def, 1) < 0)
504
        goto cleanup;
505

506 507 508
    if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
        goto cleanup;

509 510
    if ((backend = virStorageBackendForType(def->type)) == NULL)
        goto cleanup;
511

512
    if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
513 514
        goto cleanup;
    def = NULL;
515

516
    if (backend->startPool &&
517 518 519
        backend->startPool(conn, pool) < 0) {
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
520
        goto cleanup;
521
    }
522

523 524 525
    if (backend->refreshPool(conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(conn, pool);
526 527
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
528
        goto cleanup;
529
    }
530
    VIR_INFO("Creating storage pool '%s'", pool->def->name);
531 532
    pool->active = 1;

533 534
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
535

536 537
cleanup:
    virStoragePoolDefFree(def);
538
    if (pool)
539
        virStoragePoolObjUnlock(pool);
540
    storageDriverUnlock(driver);
541 542 543 544
    return ret;
}

static virStoragePoolPtr
545 546 547
storagePoolDefineXML(virConnectPtr conn,
                     const char *xml,
                     unsigned int flags)
E
Eric Blake 已提交
548
{
549
    virStorageDriverStatePtr driver = conn->storagePrivateData;
550
    virStoragePoolDefPtr def;
551
    virStoragePoolObjPtr pool = NULL;
552
    virStoragePoolPtr ret = NULL;
553

E
Eric Blake 已提交
554 555
    virCheckFlags(0, NULL);

556
    storageDriverLock(driver);
557
    if (!(def = virStoragePoolDefParseString(xml)))
558
        goto cleanup;
559

560 561 562
    if (virStoragePoolObjIsDuplicate(&driver->pools, def, 0) < 0)
        goto cleanup;

563 564 565
    if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
        goto cleanup;

566
    if (virStorageBackendForType(def->type) == NULL)
567
        goto cleanup;
568

569
    if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
570
        goto cleanup;
571

572
    if (virStoragePoolObjSaveDef(driver, pool, def) < 0) {
573
        virStoragePoolObjRemove(&driver->pools, pool);
574
        def = NULL;
575
        goto cleanup;
576
    }
577
    def = NULL;
578

579
    VIR_INFO("Defining storage pool '%s'", pool->def->name);
580 581
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
582 583 584

cleanup:
    virStoragePoolDefFree(def);
585 586 587
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
588 589 590 591 592
    return ret;
}

static int
storagePoolUndefine(virStoragePoolPtr obj) {
593 594 595
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
596

597
    storageDriverLock(driver);
598
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
599
    if (!pool) {
600
        virReportError(VIR_ERR_NO_STORAGE_POOL,
601
                       _("no storage pool with matching uuid %s"), obj->uuid);
602
        goto cleanup;
603 604 605
    }

    if (virStoragePoolObjIsActive(pool)) {
606
        virReportError(VIR_ERR_OPERATION_INVALID,
607 608
                       _("storage pool '%s' is still active"),
                       pool->def->name);
609
        goto cleanup;
610 611
    }

612
    if (pool->asyncjobs > 0) {
613 614 615
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
                       pool->def->name);
616 617 618
        goto cleanup;
    }

619
    if (virStoragePoolObjDeleteDef(pool) < 0)
620
        goto cleanup;
621

622 623
    if (unlink(pool->autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
        char ebuf[1024];
624
        VIR_ERROR(_("Failed to delete autostart link '%s': %s"),
625
                  pool->autostartLink, virStrerror(errno, ebuf, sizeof(ebuf)));
626
    }
627

628 629
    VIR_FREE(pool->configFile);
    VIR_FREE(pool->autostartLink);
630

631
    VIR_INFO("Undefining storage pool '%s'", pool->def->name);
632
    virStoragePoolObjRemove(&driver->pools, pool);
633
    pool = NULL;
634
    ret = 0;
635

636
cleanup:
637 638 639
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
640
    return ret;
641 642 643
}

static int
644 645
storagePoolCreate(virStoragePoolPtr obj,
                  unsigned int flags)
E
Eric Blake 已提交
646
{
647 648
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
649
    virStorageBackendPtr backend;
650
    int ret = -1;
651

E
Eric Blake 已提交
652 653
    virCheckFlags(0, -1);

654
    storageDriverLock(driver);
655
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
656 657
    storageDriverUnlock(driver);

658
    if (!pool) {
659
        virReportError(VIR_ERR_NO_STORAGE_POOL,
660
                       _("no storage pool with matching uuid %s"), obj->uuid);
661
        goto cleanup;
662 663
    }

664 665
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
666 667

    if (virStoragePoolObjIsActive(pool)) {
668
        virReportError(VIR_ERR_OPERATION_INVALID,
669 670
                       _("storage pool '%s' is already active"),
                       pool->def->name);
671
        goto cleanup;
672 673 674
    }
    if (backend->startPool &&
        backend->startPool(obj->conn, pool) < 0)
675 676
        goto cleanup;

677 678 679
    if (backend->refreshPool(obj->conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(obj->conn, pool);
680
        goto cleanup;
681 682
    }

683
    VIR_INFO("Starting up storage pool '%s'", pool->def->name);
684
    pool->active = 1;
685
    ret = 0;
686

687
cleanup:
688 689
    if (pool)
        virStoragePoolObjUnlock(pool);
690
    return ret;
691 692 693 694 695
}

static int
storagePoolBuild(virStoragePoolPtr obj,
                 unsigned int flags) {
696 697
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
698
    virStorageBackendPtr backend;
699
    int ret = -1;
700

701
    storageDriverLock(driver);
702
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
703 704
    storageDriverUnlock(driver);

705
    if (!pool) {
706
        virReportError(VIR_ERR_NO_STORAGE_POOL,
707
                       _("no storage pool with matching uuid %s"), obj->uuid);
708
        goto cleanup;
709 710
    }

711 712
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
713 714

    if (virStoragePoolObjIsActive(pool)) {
715
        virReportError(VIR_ERR_OPERATION_INVALID,
716 717
                       _("storage pool '%s' is already active"),
                       pool->def->name);
718
        goto cleanup;
719 720 721 722
    }

    if (backend->buildPool &&
        backend->buildPool(obj->conn, pool, flags) < 0)
723 724
        goto cleanup;
    ret = 0;
725

726
cleanup:
727 728
    if (pool)
        virStoragePoolObjUnlock(pool);
729
    return ret;
730 731 732 733 734
}


static int
storagePoolDestroy(virStoragePoolPtr obj) {
735 736
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
737
    virStorageBackendPtr backend;
738
    int ret = -1;
739

740
    storageDriverLock(driver);
741
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
742

743
    if (!pool) {
744
        virReportError(VIR_ERR_NO_STORAGE_POOL,
745
                       _("no storage pool with matching uuid %s"), obj->uuid);
746
        goto cleanup;
747 748
    }

749 750
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
751 752

    if (!virStoragePoolObjIsActive(pool)) {
753
        virReportError(VIR_ERR_OPERATION_INVALID,
754
                       _("storage pool '%s' is not active"), pool->def->name);
755
        goto cleanup;
756 757
    }

758
    if (pool->asyncjobs > 0) {
759 760 761
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
                       pool->def->name);
762 763 764
        goto cleanup;
    }

765 766
    if (backend->stopPool &&
        backend->stopPool(obj->conn, pool) < 0)
767
        goto cleanup;
768 769 770 771

    virStoragePoolObjClearVols(pool);

    pool->active = 0;
772
    VIR_INFO("Shutting down storage pool '%s'", pool->def->name);
773

774
    if (pool->configFile == NULL) {
775
        virStoragePoolObjRemove(&driver->pools, pool);
776
        pool = NULL;
777 778 779 780
    } else if (pool->newDef) {
        virStoragePoolDefFree(pool->def);
        pool->def = pool->newDef;
        pool->newDef = NULL;
781
    }
782
    ret = 0;
783

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

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

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

803
    if (!pool) {
804
        virReportError(VIR_ERR_NO_STORAGE_POOL,
805
                       _("no storage pool with matching uuid %s"), obj->uuid);
806
        goto cleanup;
807 808
    }

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

    if (virStoragePoolObjIsActive(pool)) {
813
        virReportError(VIR_ERR_OPERATION_INVALID,
814 815
                       _("storage pool '%s' is still active"),
                       pool->def->name);
816
        goto cleanup;
817 818
    }

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

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

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


static int
storagePoolRefresh(virStoragePoolPtr obj,
E
Eric Blake 已提交
845 846
                   unsigned int flags)
{
847 848
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
849
    virStorageBackendPtr backend;
850
    int ret = -1;
851

E
Eric Blake 已提交
852 853
    virCheckFlags(0, -1);

854
    storageDriverLock(driver);
855
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
856

857
    if (!pool) {
858
        virReportError(VIR_ERR_NO_STORAGE_POOL,
859
                       _("no storage pool with matching uuid %s"), obj->uuid);
860
        goto cleanup;
861 862
    }

863 864
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
865 866

    if (!virStoragePoolObjIsActive(pool)) {
867
        virReportError(VIR_ERR_OPERATION_INVALID,
868
                       _("storage pool '%s' is not active"), pool->def->name);
869
        goto cleanup;
870 871
    }

872
    if (pool->asyncjobs > 0) {
873 874 875
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
                       pool->def->name);
876 877 878
        goto cleanup;
    }

879
    virStoragePoolObjClearVols(pool);
880
    if (backend->refreshPool(obj->conn, pool) < 0) {
881 882 883 884 885
        if (backend->stopPool)
            backend->stopPool(obj->conn, pool);

        pool->active = 0;

886
        if (pool->configFile == NULL) {
887
            virStoragePoolObjRemove(&driver->pools, pool);
888 889
            pool = NULL;
        }
890
        goto cleanup;
891
    }
892
    ret = 0;
893

894
cleanup:
895 896
    if (pool)
        virStoragePoolObjUnlock(pool);
897
    storageDriverUnlock(driver);
898 899 900 901 902 903 904
    return ret;
}


static int
storagePoolGetInfo(virStoragePoolPtr obj,
                   virStoragePoolInfoPtr info) {
905 906 907
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
908

909
    storageDriverLock(driver);
910
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
911 912
    storageDriverUnlock(driver);

913
    if (!pool) {
914
        virReportError(VIR_ERR_NO_STORAGE_POOL,
915
                       _("no storage pool with matching uuid %s"), obj->uuid);
916
        goto cleanup;
917 918
    }

919
    if (virStorageBackendForType(pool->def->type) == NULL)
920
        goto cleanup;
921 922 923 924 925 926 927 928 929

    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;
930
    ret = 0;
931

932
cleanup:
933 934
    if (pool)
        virStoragePoolObjUnlock(pool);
935
    return ret;
936 937 938
}

static char *
939
storagePoolGetXMLDesc(virStoragePoolPtr obj,
E
Eric Blake 已提交
940 941
                      unsigned int flags)
{
942 943
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
944
    virStoragePoolDefPtr def;
945
    char *ret = NULL;
946

947
    virCheckFlags(VIR_STORAGE_XML_INACTIVE, NULL);
E
Eric Blake 已提交
948

949
    storageDriverLock(driver);
950
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
951 952
    storageDriverUnlock(driver);

953
    if (!pool) {
954
        virReportError(VIR_ERR_NO_STORAGE_POOL,
955
                       _("no storage pool with matching uuid %s"), obj->uuid);
956
        goto cleanup;
957 958
    }

959 960 961 962 963 964
    if ((flags & VIR_STORAGE_XML_INACTIVE) && pool->newDef)
        def = pool->newDef;
    else
        def = pool->def;

    ret = virStoragePoolDefFormat(def);
965 966

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

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

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

983
    if (!pool) {
984
        virReportError(VIR_ERR_NO_STORAGE_POOL,
985
                       _("no storage pool with matching uuid %s"), obj->uuid);
986
        goto cleanup;
987 988 989 990 991 992 993
    }

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

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

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

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

1012
    if (!pool) {
1013
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1014
                       _("no storage pool with matching uuid %s"), obj->uuid);
1015
        goto cleanup;
1016 1017 1018
    }

    if (!pool->configFile) {
1019 1020
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("pool has no config file"));
1021
        goto cleanup;
1022 1023 1024 1025
    }

    autostart = (autostart != 0);

1026 1027
    if (pool->autostart != autostart) {
        if (autostart) {
1028 1029
            if (virFileMakePath(driver->autostartDir) < 0) {
                virReportSystemError(errno,
1030 1031
                                     _("cannot create autostart directory %s"),
                                     driver->autostartDir);
1032 1033
                goto cleanup;
            }
1034

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

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


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

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

1072
    if (!pool) {
1073
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1074
                       _("no storage pool with matching uuid %s"), obj->uuid);
1075
        goto cleanup;
1076 1077 1078
    }

    if (!virStoragePoolObjIsActive(pool)) {
1079
        virReportError(VIR_ERR_OPERATION_INVALID,
1080
                       _("storage pool '%s' is not active"), pool->def->name);
1081
        goto cleanup;
1082
    }
1083
    ret = pool->volumes.count;
1084

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

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

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

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

1105
    if (!pool) {
1106
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1107
                       _("no storage pool with matching uuid %s"), obj->uuid);
1108
        goto cleanup;
1109 1110 1111
    }

    if (!virStoragePoolObjIsActive(pool)) {
1112
        virReportError(VIR_ERR_OPERATION_INVALID,
1113
                       _("storage pool '%s' is not active"), pool->def->name);
1114
        goto cleanup;
1115 1116
    }

1117
    for (i = 0; i < pool->volumes.count && n < maxnames; i++) {
1118
        if (VIR_STRDUP(names[n++], pool->volumes.objs[i]->name) < 0)
1119 1120 1121
            goto cleanup;
    }

1122
    virStoragePoolObjUnlock(pool);
1123
    return n;
1124 1125

 cleanup:
1126 1127
    if (pool)
        virStoragePoolObjUnlock(pool);
1128
    for (n = 0; n < maxnames; n++)
1129
        VIR_FREE(names[n]);
1130

1131
    memset(names, 0, maxnames * sizeof(*names));
1132 1133 1134
    return -1;
}

1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
static int
storagePoolListAllVolumes(virStoragePoolPtr pool,
                          virStorageVolPtr **vols,
                          unsigned int flags) {
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
    virStoragePoolObjPtr obj;
    int i;
    virStorageVolPtr *tmp_vols = NULL;
    virStorageVolPtr vol = NULL;
    int nvols = 0;
    int ret = -1;

    virCheckFlags(0, -1);

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

    if (!obj) {
1154 1155 1156
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching uuid %s"),
                       pool->uuid);
1157 1158 1159 1160
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(obj)) {
1161 1162
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), obj->def->name);
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176
        goto cleanup;
    }

     /* Just returns the volumes count */
    if (!vols) {
        ret = obj->volumes.count;
        goto cleanup;
    }

    if (VIR_ALLOC_N(tmp_vols, obj->volumes.count + 1) < 0) {
         virReportOOMError();
         goto cleanup;
    }

1177
    for (i = 0; i < obj->volumes.count; i++) {
1178 1179
        if (!(vol = virGetStorageVol(pool->conn, obj->def->name,
                                     obj->volumes.objs[i]->name,
1180 1181
                                     obj->volumes.objs[i]->key,
                                     NULL, NULL)))
1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195
            goto cleanup;
        tmp_vols[nvols++] = vol;
    }

    *vols = tmp_vols;
    tmp_vols = NULL;
    ret = nvols;

 cleanup:
    if (tmp_vols) {
        for (i = 0; i < nvols; i++) {
            if (tmp_vols[i])
                virStorageVolFree(tmp_vols[i]);
        }
1196
        VIR_FREE(tmp_vols);
1197 1198 1199 1200 1201 1202 1203
    }

    if (obj)
        virStoragePoolObjUnlock(obj);

    return ret;
}
1204 1205

static virStorageVolPtr
1206 1207
storageVolLookupByName(virStoragePoolPtr obj,
                       const char *name) {
1208 1209
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1210
    virStorageVolDefPtr vol;
1211
    virStorageVolPtr ret = NULL;
1212

1213
    storageDriverLock(driver);
1214
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1215 1216
    storageDriverUnlock(driver);

1217
    if (!pool) {
1218
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1219
                       _("no storage pool with matching uuid %s"), obj->uuid);
1220
        goto cleanup;
1221 1222 1223
    }

    if (!virStoragePoolObjIsActive(pool)) {
1224
        virReportError(VIR_ERR_OPERATION_INVALID,
1225
                       _("storage pool '%s' is not active"), pool->def->name);
1226
        goto cleanup;
1227 1228 1229 1230 1231
    }

    vol = virStorageVolDefFindByName(pool, name);

    if (!vol) {
1232 1233 1234
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       name);
1235
        goto cleanup;
1236 1237
    }

1238 1239
    ret = virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key,
                           NULL, NULL);
1240 1241

cleanup:
1242 1243
    if (pool)
        virStoragePoolObjUnlock(pool);
1244
    return ret;
1245 1246 1247 1248
}


static virStorageVolPtr
1249 1250
storageVolLookupByKey(virConnectPtr conn,
                      const char *key) {
1251
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1252
    unsigned int i;
1253
    virStorageVolPtr ret = NULL;
1254

1255
    storageDriverLock(driver);
1256
    for (i = 0; i < driver->pools.count && !ret; i++) {
1257
        virStoragePoolObjLock(driver->pools.objs[i]);
1258 1259 1260
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
            virStorageVolDefPtr vol =
                virStorageVolDefFindByKey(driver->pools.objs[i], key);
1261

1262
            if (vol)
1263
                ret = virGetStorageVol(conn,
1264 1265
                                       driver->pools.objs[i]->def->name,
                                       vol->name,
1266 1267
                                       vol->key,
                                       NULL, NULL);
1268
        }
1269
        virStoragePoolObjUnlock(driver->pools.objs[i]);
1270
    }
1271
    storageDriverUnlock(driver);
1272

1273
    if (!ret)
1274
        virReportError(VIR_ERR_NO_STORAGE_VOL,
1275
                       _("no storage vol with matching key %s"), key);
1276 1277

    return ret;
1278 1279 1280
}

static virStorageVolPtr
1281 1282
storageVolLookupByPath(virConnectPtr conn,
                       const char *path) {
1283
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1284
    unsigned int i;
1285
    virStorageVolPtr ret = NULL;
1286 1287 1288 1289 1290
    char *cleanpath;

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

1292
    storageDriverLock(driver);
1293
    for (i = 0; i < driver->pools.count && !ret; i++) {
1294
        virStoragePoolObjLock(driver->pools.objs[i]);
1295
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
1296
            virStorageVolDefPtr vol;
1297 1298
            const char *stable_path;

1299
            stable_path = virStorageBackendStablePath(driver->pools.objs[i],
1300 1301
                                                      cleanpath,
                                                      false);
1302
            if (stable_path == NULL) {
1303 1304 1305 1306 1307
                /* Don't break the whole lookup process if it fails on
                 * getting the stable path for some of the pools.
                 */
                VIR_WARN("Failed to get stable path for pool '%s'",
                         driver->pools.objs[i]->def->name);
1308
                virStoragePoolObjUnlock(driver->pools.objs[i]);
1309
                continue;
1310
            }
1311 1312 1313 1314

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

1316
            if (vol)
1317 1318 1319
                ret = virGetStorageVol(conn,
                                       driver->pools.objs[i]->def->name,
                                       vol->name,
1320 1321
                                       vol->key,
                                       NULL, NULL);
1322
        }
1323
        virStoragePoolObjUnlock(driver->pools.objs[i]);
1324 1325
    }

1326
    if (!ret)
1327
        virReportError(VIR_ERR_NO_STORAGE_VOL,
1328
                       _("no storage vol with matching path %s"), path);
1329

1330
    VIR_FREE(cleanpath);
1331
    storageDriverUnlock(driver);
1332
    return ret;
1333 1334
}

1335
static int storageVolDelete(virStorageVolPtr obj, unsigned int flags);
1336

1337
static virStorageVolPtr
1338 1339 1340
storageVolCreateXML(virStoragePoolPtr obj,
                    const char *xmldesc,
                    unsigned int flags)
E
Eric Blake 已提交
1341
{
1342 1343
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1344
    virStorageBackendPtr backend;
1345 1346
    virStorageVolDefPtr voldef = NULL;
    virStorageVolPtr ret = NULL, volobj = NULL;
1347

1348
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
E
Eric Blake 已提交
1349

1350
    storageDriverLock(driver);
1351
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1352 1353
    storageDriverUnlock(driver);

1354
    if (!pool) {
1355
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1356
                       _("no storage pool with matching uuid %s"), obj->uuid);
1357
        goto cleanup;
1358 1359 1360
    }

    if (!virStoragePoolObjIsActive(pool)) {
1361
        virReportError(VIR_ERR_OPERATION_INVALID,
1362
                       _("storage pool '%s' is not active"), pool->def->name);
1363
        goto cleanup;
1364 1365 1366
    }

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

1369
    voldef = virStorageVolDefParseString(pool->def, xmldesc);
1370
    if (voldef == NULL)
1371
        goto cleanup;
1372

1373
    if (virStorageVolDefFindByName(pool, voldef->name)) {
1374
        virReportError(VIR_ERR_NO_STORAGE_VOL,
1375
                       _("storage vol '%s' already exists"), voldef->name);
1376
        goto cleanup;
1377 1378
    }

1379 1380
    if (VIR_REALLOC_N(pool->volumes.objs,
                      pool->volumes.count+1) < 0) {
1381
        virReportOOMError();
1382
        goto cleanup;
1383 1384
    }

1385
    if (!backend->createVol) {
1386 1387 1388
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("storage pool does not support volume "
                               "creation"));
1389
        goto cleanup;
1390 1391
    }

1392
    if (backend->createVol(obj->conn, pool, voldef) < 0) {
1393
        goto cleanup;
1394 1395
    }

1396 1397
    pool->volumes.objs[pool->volumes.count++] = voldef;
    volobj = virGetStorageVol(obj->conn, pool->def->name, voldef->name,
1398
                              voldef->key, NULL, NULL);
1399 1400 1401 1402
    if (!volobj) {
        pool->volumes.count--;
        goto cleanup;
    }
1403

1404
    if (backend->buildVol) {
1405 1406 1407 1408
        int buildret;
        virStorageVolDefPtr buildvoldef = NULL;

        if (VIR_ALLOC(buildvoldef) < 0) {
1409
            virReportOOMError();
1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424
            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);

1425
        buildret = backend->buildVol(obj->conn, pool, buildvoldef, flags);
1426

1427
        storageDriverLock(driver);
1428
        virStoragePoolObjLock(pool);
1429 1430
        storageDriverUnlock(driver);

1431 1432 1433 1434 1435 1436 1437 1438
        voldef->building = 0;
        pool->asyncjobs--;

        voldef = NULL;
        VIR_FREE(buildvoldef);

        if (buildret < 0) {
            virStoragePoolObjUnlock(pool);
1439
            storageVolDelete(volobj, 0);
1440 1441 1442 1443 1444 1445
            pool = NULL;
            goto cleanup;
        }

    }

1446
    VIR_INFO("Creating volume '%s' in storage pool '%s'",
1447
             volobj->name, pool->def->name);
1448 1449 1450
    ret = volobj;
    volobj = NULL;
    voldef = NULL;
1451

1452
cleanup:
1453
    virObjectUnref(volobj);
1454
    virStorageVolDefFree(voldef);
1455 1456
    if (pool)
        virStoragePoolObjUnlock(pool);
1457
    return ret;
1458 1459
}

1460
static virStorageVolPtr
1461 1462 1463 1464
storageVolCreateXMLFrom(virStoragePoolPtr obj,
                        const char *xmldesc,
                        virStorageVolPtr vobj,
                        unsigned int flags)
E
Eric Blake 已提交
1465
{
1466 1467 1468 1469 1470
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool, origpool = NULL;
    virStorageBackendPtr backend;
    virStorageVolDefPtr origvol = NULL, newvol = NULL;
    virStorageVolPtr ret = NULL, volobj = NULL;
1471
    int buildret;
1472

1473
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
E
Eric Blake 已提交
1474

1475 1476
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1477
    if (pool && STRNEQ(obj->name, vobj->pool)) {
1478
        virStoragePoolObjUnlock(pool);
1479
        origpool = virStoragePoolObjFindByName(&driver->pools, vobj->pool);
1480
        virStoragePoolObjLock(pool);
1481
    }
1482 1483
    storageDriverUnlock(driver);
    if (!pool) {
1484
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1485
                       _("no storage pool with matching uuid %s"), obj->uuid);
1486 1487 1488
        goto cleanup;
    }

1489
    if (STRNEQ(obj->name, vobj->pool) && !origpool) {
1490 1491 1492
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       vobj->pool);
1493 1494 1495 1496
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1497
        virReportError(VIR_ERR_OPERATION_INVALID,
1498
                       _("storage pool '%s' is not active"), pool->def->name);
1499 1500 1501
        goto cleanup;
    }

1502
    if (origpool && !virStoragePoolObjIsActive(origpool)) {
1503
        virReportError(VIR_ERR_OPERATION_INVALID,
1504 1505
                       _("storage pool '%s' is not active"),
                       origpool->def->name);
1506 1507 1508 1509 1510 1511
        goto cleanup;
    }

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

1512
    origvol = virStorageVolDefFindByName(origpool ? origpool : pool, vobj->name);
1513
    if (!origvol) {
1514 1515 1516
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vobj->name);
1517 1518 1519
        goto cleanup;
    }

1520
    newvol = virStorageVolDefParseString(pool->def, xmldesc);
1521 1522 1523 1524
    if (newvol == NULL)
        goto cleanup;

    if (virStorageVolDefFindByName(pool, newvol->name)) {
1525 1526 1527
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("storage volume name '%s' already in use."),
                       newvol->name);
1528 1529 1530 1531 1532 1533 1534
        goto cleanup;
    }

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

1535 1536 1537 1538 1539
    /* 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;

1540
    if (!backend->buildVolFrom) {
1541 1542
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("storage pool does not support volume creation from an existing volume"));
1543 1544 1545 1546
        goto cleanup;
    }

    if (origvol->building) {
1547 1548 1549
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       origvol->name);
1550 1551 1552 1553 1554 1555 1556 1557 1558
        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) {
1559
        virReportOOMError();
1560 1561 1562 1563 1564 1565 1566 1567 1568 1569
        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,
1570
                              newvol->key, NULL, NULL);
1571 1572 1573 1574 1575 1576 1577

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

1578
    if (origpool) {
1579 1580 1581 1582
        origpool->asyncjobs++;
        virStoragePoolObjUnlock(origpool);
    }

1583
    buildret = backend->buildVolFrom(obj->conn, pool, newvol, origvol, flags);
1584 1585 1586

    storageDriverLock(driver);
    virStoragePoolObjLock(pool);
1587
    if (origpool)
1588 1589 1590 1591 1592 1593 1594 1595
        virStoragePoolObjLock(origpool);
    storageDriverUnlock(driver);

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

1596
    if (origpool) {
1597 1598 1599 1600 1601 1602 1603
        origpool->asyncjobs--;
        virStoragePoolObjUnlock(origpool);
        origpool = NULL;
    }

    if (buildret < 0) {
        virStoragePoolObjUnlock(pool);
1604
        storageVolDelete(volobj, 0);
1605 1606 1607 1608
        pool = NULL;
        goto cleanup;
    }

1609
    VIR_INFO("Creating volume '%s' in storage pool '%s'",
1610
             volobj->name, pool->def->name);
1611 1612 1613 1614
    ret = volobj;
    volobj = NULL;

cleanup:
1615
    virObjectUnref(volobj);
1616 1617 1618
    virStorageVolDefFree(newvol);
    if (pool)
        virStoragePoolObjUnlock(pool);
1619
    if (origpool)
1620 1621 1622 1623
        virStoragePoolObjUnlock(origpool);
    return ret;
}

1624

1625
static int
1626 1627 1628 1629 1630
storageVolDownload(virStorageVolPtr obj,
                   virStreamPtr stream,
                   unsigned long long offset,
                   unsigned long long length,
                   unsigned int flags)
1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

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

    if (!pool) {
1644
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1645 1646
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1647 1648 1649 1650
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1651
        virReportError(VIR_ERR_OPERATION_INVALID,
1652
                       _("storage pool '%s' is not active"), pool->def->name);
1653 1654 1655 1656 1657 1658
        goto out;
    }

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

    if (vol == NULL) {
1659 1660 1661
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1662 1663 1664 1665
        goto out;
    }

    if (vol->building) {
1666 1667 1668
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1669 1670 1671 1672 1673 1674
        goto out;
    }

    if (virFDStreamOpenFile(stream,
                            vol->target.path,
                            offset, length,
E
Eric Blake 已提交
1675
                            O_RDONLY) < 0)
1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688
        goto out;

    ret = 0;

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}


static int
1689 1690 1691 1692 1693
storageVolUpload(virStorageVolPtr obj,
                 virStreamPtr stream,
                 unsigned long long offset,
                 unsigned long long length,
                 unsigned int flags)
1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

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

    if (!pool) {
1707
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1708 1709
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1710 1711 1712 1713
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1714
        virReportError(VIR_ERR_OPERATION_INVALID,
1715
                       _("storage pool '%s' is not active"), pool->def->name);
1716 1717 1718 1719 1720 1721
        goto out;
    }

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

    if (vol == NULL) {
1722 1723 1724
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1725 1726 1727 1728
        goto out;
    }

    if (vol->building) {
1729 1730 1731
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1732 1733 1734 1735 1736 1737 1738 1739
        goto out;
    }

    /* Not using O_CREAT because the file is required to
     * already exist at this point */
    if (virFDStreamOpenFile(stream,
                            vol->target.path,
                            offset, length,
E
Eric Blake 已提交
1740
                            O_WRONLY) < 0)
1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751
        goto out;

    ret = 0;

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}

1752
static int
1753 1754 1755
storageVolResize(virStorageVolPtr obj,
                 unsigned long long capacity,
                 unsigned int flags)
1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStorageBackendPtr backend;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    unsigned long long abs_capacity;
    int ret = -1;

    virCheckFlags(VIR_STORAGE_VOL_RESIZE_DELTA, -1);

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

    if (!pool) {
1771 1772 1773
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1774 1775 1776 1777
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1778 1779
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->def->name);
1780 1781 1782 1783 1784 1785 1786 1787 1788
        goto out;
    }

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

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

    if (vol == NULL) {
1789 1790 1791
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1792 1793 1794 1795
        goto out;
    }

    if (vol->building) {
1796 1797 1798
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1799 1800
        goto out;
    }
1801

1802 1803 1804 1805 1806 1807 1808 1809
    if (flags & VIR_STORAGE_VOL_RESIZE_DELTA) {
        abs_capacity = vol->capacity + capacity;
        flags &= ~VIR_STORAGE_VOL_RESIZE_DELTA;
    } else {
        abs_capacity = capacity;
    }

    if (abs_capacity < vol->allocation) {
1810
        virReportError(VIR_ERR_INVALID_ARG, "%s",
1811 1812
                       _("can't shrink capacity below "
                         "existing allocation"));
1813 1814 1815
        goto out;
    }

1816
    if (abs_capacity > vol->capacity + pool->def->available) {
1817
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
1818
                       _("Not enough space left on storage pool"));
1819 1820 1821 1822
        goto out;
    }

    if (!backend->resizeVol) {
1823
        virReportError(VIR_ERR_NO_SUPPORT, "%s",
1824 1825
                       _("storage pool does not support changing of "
                         "volume capacity"));
1826 1827 1828 1829 1830 1831
        goto out;
    }

    if (backend->resizeVol(obj->conn, pool, vol, abs_capacity, flags) < 0)
        goto out;

O
Osier Yang 已提交
1832 1833
    vol->capacity = abs_capacity;
    ret = 0;
1834 1835 1836 1837 1838 1839 1840

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
1841

1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856
/* 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
1857 1858 1859
storageVolZeroSparseFile(virStorageVolDefPtr vol,
                         off_t size,
                         int fd)
1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875
{
    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 "
1876
                               "path '%s' to %ju bytes"),
E
Eric Blake 已提交
1877
                             vol->target.path, (uintmax_t)size);
1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898
    }

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 已提交
1899
              (uintmax_t)extent_start, (uintmax_t)extent_length);
1900 1901 1902 1903 1904

    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 已提交
1905
                             (uintmax_t)extent_start, vol->target.path);
1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926
        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;
    }

1927 1928 1929 1930 1931 1932 1933 1934
    if (fdatasync(fd) < 0) {
        ret = -errno;
        virReportSystemError(errno,
                             _("cannot sync data to volume with path '%s'"),
                             vol->target.path);
        goto out;
    }

1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945
    VIR_DEBUG("Wrote %zu bytes to volume with path '%s'",
              *bytes_wiped, vol->target.path);

    ret = 0;

out:
    return ret;
}


static int
1946 1947
storageVolWipeInternal(virStorageVolDefPtr def,
                       unsigned int algorithm)
1948 1949 1950 1951 1952
{
    int ret = -1, fd = -1;
    struct stat st;
    char *writebuf = NULL;
    size_t bytes_wiped = 0;
1953
    virCommandPtr cmd = NULL;
1954

1955 1956
    VIR_DEBUG("Wiping volume with path '%s' and algorithm %u",
              def->target.path, algorithm);
1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972

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

1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988
    if (algorithm != VIR_STORAGE_VOL_WIPE_ALG_ZERO) {
        const char *alg_char ATTRIBUTE_UNUSED = NULL;
        switch (algorithm) {
        case VIR_STORAGE_VOL_WIPE_ALG_NNSA:
            alg_char = "nnsa";
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_DOD:
            alg_char = "dod";
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_BSI:
            alg_char = "bsi";
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_GUTMANN:
            alg_char = "gutmann";
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_SCHNEIER:
A
Alex Jia 已提交
1989
            alg_char = "schneier";
1990 1991 1992 1993 1994
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7:
            alg_char = "pfitzner7";
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33:
M
Michal Privoznik 已提交
1995
            alg_char = "pfitzner33";
1996 1997 1998 1999 2000
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_RANDOM:
            alg_char = "random";
            break;
        default:
2001 2002 2003
            virReportError(VIR_ERR_INVALID_ARG,
                           _("unsupported algorithm %d"),
                           algorithm);
2004 2005 2006 2007
        }
        cmd = virCommandNew(SCRUB);
        virCommandAddArgList(cmd, "-f", "-p", alg_char,
                             def->target.path, NULL);
2008

2009
        if (virCommandRun(cmd, NULL) < 0)
2010 2011
            goto out;

2012 2013 2014 2015
        ret = 0;
        goto out;
    } else {
        if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) {
2016
            ret = storageVolZeroSparseFile(def, st.st_size, fd);
2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031
        } 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);
        }
2032 2033 2034
    }

out:
2035
    virCommandFree(cmd);
2036
    VIR_FREE(writebuf);
2037
    VIR_FORCE_CLOSE(fd);
2038 2039 2040 2041 2042
    return ret;
}


static int
2043 2044 2045
storageVolWipePattern(virStorageVolPtr obj,
                      unsigned int algorithm,
                      unsigned int flags)
2046 2047 2048 2049 2050 2051
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    int ret = -1;

2052
    virCheckFlags(0, -1);
2053

2054
    if (algorithm >= VIR_STORAGE_VOL_WIPE_ALG_LAST) {
2055 2056 2057
        virReportError(VIR_ERR_INVALID_ARG,
                       _("wiping algorithm %d not supported"),
                       algorithm);
2058 2059 2060
        return -1;
    }

2061 2062 2063 2064 2065
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
    storageDriverUnlock(driver);

    if (!pool) {
2066
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2067 2068
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2069 2070 2071 2072
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
2073
        virReportError(VIR_ERR_OPERATION_INVALID,
2074
                       _("storage pool '%s' is not active"), pool->def->name);
2075 2076 2077 2078 2079 2080
        goto out;
    }

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

    if (vol == NULL) {
2081 2082 2083
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2084 2085 2086 2087
        goto out;
    }

    if (vol->building) {
2088 2089 2090
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
2091 2092 2093
        goto out;
    }

2094
    if (storageVolWipeInternal(vol, algorithm) == -1) {
2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108
        goto out;
    }

    ret = 0;

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

    return ret;

}

2109
static int
2110 2111
storageVolWipe(virStorageVolPtr obj,
               unsigned int flags)
2112
{
2113
    return storageVolWipePattern(obj, VIR_STORAGE_VOL_WIPE_ALG_ZERO, flags);
2114 2115
}

2116
static int
2117 2118
storageVolDelete(virStorageVolPtr obj,
                 unsigned int flags) {
2119 2120
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2121
    virStorageBackendPtr backend;
2122
    virStorageVolDefPtr vol = NULL;
2123
    unsigned int i;
2124
    int ret = -1;
2125

2126
    storageDriverLock(driver);
2127
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2128 2129
    storageDriverUnlock(driver);

2130
    if (!pool) {
2131
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2132 2133
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2134
        goto cleanup;
2135 2136 2137
    }

    if (!virStoragePoolObjIsActive(pool)) {
2138
        virReportError(VIR_ERR_OPERATION_INVALID,
2139
                       _("storage pool '%s' is not active"), pool->def->name);
2140
        goto cleanup;
2141 2142 2143
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2144
        goto cleanup;
2145 2146 2147 2148

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

    if (!vol) {
2149 2150 2151
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2152
        goto cleanup;
2153 2154
    }

2155
    if (vol->building) {
2156 2157 2158
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
2159 2160 2161
        goto cleanup;
    }

2162
    if (!backend->deleteVol) {
2163 2164
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("storage pool does not support vol deletion"));
2165

2166
        goto cleanup;
2167 2168
    }

2169 2170 2171
    if (backend->deleteVol(obj->conn, pool, vol, flags) < 0)
        goto cleanup;

2172
    for (i = 0; i < pool->volumes.count; i++) {
2173
        if (pool->volumes.objs[i] == vol) {
2174
            VIR_INFO("Deleting volume '%s' from storage pool '%s'",
2175
                     vol->name, pool->def->name);
2176
            virStorageVolDefFree(vol);
2177
            vol = NULL;
2178 2179 2180 2181 2182 2183 2184 2185 2186 2187

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

2188 2189 2190
            break;
        }
    }
2191
    ret = 0;
2192

2193
cleanup:
2194 2195
    if (pool)
        virStoragePoolObjUnlock(pool);
2196
    return ret;
2197 2198 2199
}

static int
2200 2201
storageVolGetInfo(virStorageVolPtr obj,
                  virStorageVolInfoPtr info) {
2202 2203
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2204 2205
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
2206
    int ret = -1;
2207

2208
    storageDriverLock(driver);
2209
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2210 2211
    storageDriverUnlock(driver);

2212
    if (!pool) {
2213
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2214 2215
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2216
        goto cleanup;
2217 2218 2219
    }

    if (!virStoragePoolObjIsActive(pool)) {
2220
        virReportError(VIR_ERR_OPERATION_INVALID,
2221
                       _("storage pool '%s' is not active"), pool->def->name);
2222
        goto cleanup;
2223 2224 2225 2226 2227
    }

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

    if (!vol) {
2228 2229 2230
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2231
        goto cleanup;
2232 2233 2234
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2235
        goto cleanup;
2236 2237 2238

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

    memset(info, 0, sizeof(*info));
2242
    info->type = vol->type;
2243 2244
    info->capacity = vol->capacity;
    info->allocation = vol->allocation;
2245
    ret = 0;
2246

2247
cleanup:
2248 2249
    if (pool)
        virStoragePoolObjUnlock(pool);
2250
    return ret;
2251 2252 2253
}

static char *
2254 2255
storageVolGetXMLDesc(virStorageVolPtr obj,
                     unsigned int flags)
E
Eric Blake 已提交
2256
{
2257 2258
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2259 2260
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
2261
    char *ret = NULL;
2262

E
Eric Blake 已提交
2263 2264
    virCheckFlags(0, NULL);

2265
    storageDriverLock(driver);
2266
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2267 2268
    storageDriverUnlock(driver);

2269
    if (!pool) {
2270
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2271 2272
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2273
        goto cleanup;
2274 2275 2276
    }

    if (!virStoragePoolObjIsActive(pool)) {
2277
        virReportError(VIR_ERR_OPERATION_INVALID,
2278
                       _("storage pool '%s' is not active"), pool->def->name);
2279
        goto cleanup;
2280 2281 2282 2283 2284
    }

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

    if (!vol) {
2285 2286 2287
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2288
        goto cleanup;
2289 2290 2291
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2292
        goto cleanup;
2293 2294 2295 2296

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

2298
    ret = virStorageVolDefFormat(pool->def, vol);
2299 2300

cleanup:
2301 2302 2303
    if (pool)
        virStoragePoolObjUnlock(pool);

2304
    return ret;
2305 2306 2307
}

static char *
2308
storageVolGetPath(virStorageVolPtr obj) {
2309
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
2310
    virStoragePoolObjPtr pool;
2311
    virStorageVolDefPtr vol;
2312
    char *ret = NULL;
2313

2314 2315 2316
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
    storageDriverUnlock(driver);
2317
    if (!pool) {
2318
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2319 2320
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2321
        goto cleanup;
2322 2323 2324
    }

    if (!virStoragePoolObjIsActive(pool)) {
2325
        virReportError(VIR_ERR_OPERATION_INVALID,
2326
                       _("storage pool '%s' is not active"), pool->def->name);
2327
        goto cleanup;
2328 2329 2330 2331 2332
    }

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

    if (!vol) {
2333 2334 2335
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2336
        goto cleanup;
2337 2338
    }

2339
    ignore_value(VIR_STRDUP(ret, vol->target.path));
2340 2341

cleanup:
2342 2343
    if (pool)
        virStoragePoolObjUnlock(pool);
2344 2345 2346
    return ret;
}

2347
static int
2348 2349 2350
storageConnectListAllStoragePools(virConnectPtr conn,
                                  virStoragePoolPtr **pools,
                                  unsigned int flags)
2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363
{
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

    storageDriverLock(driver);
    ret = virStoragePoolList(conn, driver->pools, pools, flags);
    storageDriverUnlock(driver);

    return ret;
}

2364
static virStorageDriver storageDriver = {
2365
    .name = "storage",
2366 2367
    .storageOpen = storageOpen, /* 0.4.0 */
    .storageClose = storageClose, /* 0.4.0 */
2368 2369 2370 2371 2372 2373
    .connectNumOfStoragePools = storageConnectNumOfStoragePools, /* 0.4.0 */
    .connectListStoragePools = storageConnectListStoragePools, /* 0.4.0 */
    .connectNumOfDefinedStoragePools = storageConnectNumOfDefinedStoragePools, /* 0.4.0 */
    .connectListDefinedStoragePools = storageConnectListDefinedStoragePools, /* 0.4.0 */
    .connectListAllStoragePools = storageConnectListAllStoragePools, /* 0.10.2 */
    .connectFindStoragePoolSources = storageConnectFindStoragePoolSources, /* 0.4.0 */
2374 2375 2376
    .storagePoolLookupByName = storagePoolLookupByName, /* 0.4.0 */
    .storagePoolLookupByUUID = storagePoolLookupByUUID, /* 0.4.0 */
    .storagePoolLookupByVolume = storagePoolLookupByVolume, /* 0.4.0 */
2377 2378
    .storagePoolCreateXML = storagePoolCreateXML, /* 0.4.0 */
    .storagePoolDefineXML = storagePoolDefineXML, /* 0.4.0 */
2379 2380
    .storagePoolBuild = storagePoolBuild, /* 0.4.0 */
    .storagePoolUndefine = storagePoolUndefine, /* 0.4.0 */
2381
    .storagePoolCreate = storagePoolCreate, /* 0.4.0 */
2382 2383 2384 2385 2386 2387 2388
    .storagePoolDestroy = storagePoolDestroy, /* 0.4.0 */
    .storagePoolDelete = storagePoolDelete, /* 0.4.0 */
    .storagePoolRefresh = storagePoolRefresh, /* 0.4.0 */
    .storagePoolGetInfo = storagePoolGetInfo, /* 0.4.0 */
    .storagePoolGetXMLDesc = storagePoolGetXMLDesc, /* 0.4.0 */
    .storagePoolGetAutostart = storagePoolGetAutostart, /* 0.4.0 */
    .storagePoolSetAutostart = storagePoolSetAutostart, /* 0.4.0 */
2389
    .storagePoolNumOfVolumes = storagePoolNumOfVolumes, /* 0.4.0 */
2390 2391 2392
    .storagePoolListVolumes = storagePoolListVolumes, /* 0.4.0 */
    .storagePoolListAllVolumes = storagePoolListAllVolumes, /* 0.10.2 */

2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406
    .storageVolLookupByName = storageVolLookupByName, /* 0.4.0 */
    .storageVolLookupByKey = storageVolLookupByKey, /* 0.4.0 */
    .storageVolLookupByPath = storageVolLookupByPath, /* 0.4.0 */
    .storageVolCreateXML = storageVolCreateXML, /* 0.4.0 */
    .storageVolCreateXMLFrom = storageVolCreateXMLFrom, /* 0.6.4 */
    .storageVolDownload = storageVolDownload, /* 0.9.0 */
    .storageVolUpload = storageVolUpload, /* 0.9.0 */
    .storageVolDelete = storageVolDelete, /* 0.4.0 */
    .storageVolWipe = storageVolWipe, /* 0.8.0 */
    .storageVolWipePattern = storageVolWipePattern, /* 0.9.10 */
    .storageVolGetInfo = storageVolGetInfo, /* 0.4.0 */
    .storageVolGetXMLDesc = storageVolGetXMLDesc, /* 0.4.0 */
    .storageVolGetPath = storageVolGetPath, /* 0.4.0 */
    .storageVolResize = storageVolResize, /* 0.9.10 */
2407 2408 2409

    .storagePoolIsActive = storagePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = storagePoolIsPersistent, /* 0.7.3 */
2410 2411 2412 2413
};


static virStateDriver stateDriver = {
2414
    .name = "Storage",
2415 2416 2417
    .stateInitialize = storageStateInitialize,
    .stateCleanup = storageStateCleanup,
    .stateReload = storageStateReload,
2418 2419 2420 2421 2422 2423 2424
};

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