storage_driver.c 74.5 KB
Newer Older
1 2 3
/*
 * storage_driver.c: core driver for storage APIs
 *
4
 * Copyright (C) 2006-2013 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
#include "viraccessapicheck.h"
52

53 54
#define VIR_FROM_THIS VIR_FROM_STORAGE

55 56
static virStorageDriverStatePtr driverState;

57
static int storageStateCleanup(void);
58

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

static void
storageDriverAutostart(virStorageDriverStatePtr driver) {
70
    size_t i;
71 72 73 74 75 76 77 78
    virConnectPtr conn = NULL;

    /* XXX Remove hardcoding of QEMU URI */
    if (driverState->privileged)
        conn = virConnectOpen("qemu:///system");
    else
        conn = virConnectOpen("qemu:///session");
    /* Ignoring NULL conn - let backends decide */
79

80
    for (i = 0; i < driver->pools.count; i++) {
81
        virStoragePoolObjPtr pool = driver->pools.objs[i];
82 83
        virStorageBackendPtr backend;
        bool started = false;
84

85
        virStoragePoolObjLock(pool);
86 87 88 89 90
        if ((backend = virStorageBackendForType(pool->def->type)) == NULL) {
            VIR_ERROR(_("Missing backend %d"), pool->def->type);
            virStoragePoolObjUnlock(pool);
            continue;
        }
91

92
        if (backend->checkPool &&
93
            backend->checkPool(conn, pool, &started) < 0) {
94 95 96 97 98 99 100 101 102 103 104
            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)) {
105
            if (backend->startPool &&
106
                backend->startPool(conn, pool) < 0) {
107
                virErrorPtr err = virGetLastError();
108
                VIR_ERROR(_("Failed to autostart storage pool '%s': %s"),
109
                          pool->def->name, err ? err->message :
110
                          _("no error message found"));
111
                virStoragePoolObjUnlock(pool);
112 113
                continue;
            }
114 115
            started = true;
        }
116

117
        if (started) {
118
            if (backend->refreshPool(conn, pool) < 0) {
119 120
                virErrorPtr err = virGetLastError();
                if (backend->stopPool)
121
                    backend->stopPool(conn, pool);
122
                VIR_ERROR(_("Failed to autostart storage pool '%s': %s"),
123
                          pool->def->name, err ? err->message :
124
                          _("no error message found"));
125
                virStoragePoolObjUnlock(pool);
126 127 128 129
                continue;
            }
            pool->active = 1;
        }
130
        virStoragePoolObjUnlock(pool);
131
    }
132 133 134

    if (conn)
        virConnectClose(conn);
135 136 137 138 139 140 141 142
}

/**
 * virStorageStartup:
 *
 * Initialization function for the QEmu daemon
 */
static int
143 144 145
storageStateInitialize(bool privileged,
                       virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                       void *opaque ATTRIBUTE_UNUSED)
146
{
147 148
    char *base = NULL;

149
    if (VIR_ALLOC(driverState) < 0)
150 151
        return -1;

152 153 154 155
    if (virMutexInit(&driverState->lock) < 0) {
        VIR_FREE(driverState);
        return -1;
    }
156 157
    storageDriverLock(driverState);

158
    if (privileged) {
159 160
        if (VIR_STRDUP(base, SYSCONFDIR "/libvirt") < 0)
            goto error;
161
    } else {
162
        base = virGetUserConfigDirectory();
163
        if (!base)
164
            goto error;
165
    }
166
    driverState->privileged = privileged;
167

168
    /* Configuration paths are either $USER_CONFIG_HOME/libvirt/storage/... (session) or
169 170
     * /etc/libvirt/storage/... (system).
     */
171 172
    if (virAsprintf(&driverState->configDir,
                    "%s/storage", base) == -1)
173
        goto error;
174

175 176
    if (virAsprintf(&driverState->autostartDir,
                    "%s/storage/autostart", base) == -1)
177
        goto error;
178

179
    VIR_FREE(base);
180

181
    if (virStoragePoolLoadAllConfigs(&driverState->pools,
182
                                     driverState->configDir,
183 184
                                     driverState->autostartDir) < 0)
        goto error;
185 186
    storageDriverAutostart(driverState);

187
    storageDriverUnlock(driverState);
188 189
    return 0;

190 191 192
error:
    VIR_FREE(base);
    storageDriverUnlock(driverState);
193
    storageStateCleanup();
194 195 196 197
    return -1;
}

/**
198
 * storageStateReload:
199 200 201 202 203
 *
 * Function to restart the storage driver, it will recheck the configuration
 * files and update its state
 */
static int
204
storageStateReload(void) {
205 206 207
    if (!driverState)
        return -1;

208
    storageDriverLock(driverState);
209
    virStoragePoolLoadAllConfigs(&driverState->pools,
210 211
                                 driverState->configDir,
                                 driverState->autostartDir);
212
    storageDriverAutostart(driverState);
213
    storageDriverUnlock(driverState);
214 215 216 217 218 219

    return 0;
}


/**
220
 * storageStateCleanup
221 222 223 224
 *
 * Shutdown the storage driver, it will stop all active storage pools
 */
static int
225
storageStateCleanup(void) {
226 227 228
    if (!driverState)
        return -1;

229
    storageDriverLock(driverState);
230 231

    /* free inactive pools */
232 233 234 235
    virStoragePoolObjListFree(&driverState->pools);

    VIR_FREE(driverState->configDir);
    VIR_FREE(driverState->autostartDir);
236
    storageDriverUnlock(driverState);
237
    virMutexDestroy(&driverState->lock);
238
    VIR_FREE(driverState);
239 240 241 242 243 244 245 246 247

    return 0;
}



static virStoragePoolPtr
storagePoolLookupByUUID(virConnectPtr conn,
                        const unsigned char *uuid) {
248 249 250
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
251

252
    storageDriverLock(driver);
253
    pool = virStoragePoolObjFindByUUID(&driver->pools, uuid);
254 255
    storageDriverUnlock(driver);

256
    if (!pool) {
257
        virReportError(VIR_ERR_NO_STORAGE_POOL,
258
                       _("no storage pool with matching uuid %s"), uuid);
259
        goto cleanup;
260 261
    }

262 263 264
    if (virStoragePoolLookupByUUIDEnsureACL(conn, pool->def) < 0)
        goto cleanup;

265 266
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
267 268

cleanup:
269 270
    if (pool)
        virStoragePoolObjUnlock(pool);
271 272 273 274 275 276
    return ret;
}

static virStoragePoolPtr
storagePoolLookupByName(virConnectPtr conn,
                        const char *name) {
277 278 279
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
280

281
    storageDriverLock(driver);
282
    pool = virStoragePoolObjFindByName(&driver->pools, name);
283 284
    storageDriverUnlock(driver);

285
    if (!pool) {
286
        virReportError(VIR_ERR_NO_STORAGE_POOL,
287
                       _("no storage pool with matching name '%s'"), name);
288
        goto cleanup;
289 290
    }

291 292 293
    if (virStoragePoolLookupByNameEnsureACL(conn, pool->def) < 0)
        goto cleanup;

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

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

static virStoragePoolPtr
storagePoolLookupByVolume(virStorageVolPtr vol) {
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
    virStorageDriverStatePtr driver = vol->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;

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

    if (!pool) {
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"), vol->pool);
        goto cleanup;
    }

    if (virStoragePoolLookupByVolumeEnsureACL(vol->conn, pool->def) < 0)
        goto cleanup;

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

cleanup:
    if (pool)
        virStoragePoolObjUnlock(pool);
    return ret;
329 330 331 332 333
}

static virDrvOpenStatus
storageOpen(virConnectPtr conn,
            virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
334 335 336 337
            unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

338 339 340 341 342 343 344 345 346 347 348 349 350 351
    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
352
storageConnectNumOfStoragePools(virConnectPtr conn) {
353
    virStorageDriverStatePtr driver = conn->storagePrivateData;
354 355
    size_t i;
    int nactive = 0;
356

357 358 359
    if (virConnectNumOfStoragePoolsEnsureACL(conn) < 0)
        return -1;

360
    storageDriverLock(driver);
361
    for (i = 0; i < driver->pools.count; i++) {
362 363 364 365
        virStoragePoolObjPtr obj = driver->pools.objs[i];
        virStoragePoolObjLock(obj);
        if (virConnectNumOfStoragePoolsCheckACL(conn, obj->def) &&
            virStoragePoolObjIsActive(obj))
366
            nactive++;
367
        virStoragePoolObjUnlock(obj);
368 369
    }
    storageDriverUnlock(driver);
370 371

    return nactive;
372 373 374
}

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

382 383 384
    if (virConnectListStoragePoolsEnsureACL(conn) < 0)
        return -1;

385
    storageDriverLock(driver);
386
    for (i = 0; i < driver->pools.count && got < nnames; i++) {
387 388 389 390 391 392
        virStoragePoolObjPtr obj = driver->pools.objs[i];
        virStoragePoolObjLock(obj);
        if (virConnectListStoragePoolsCheckACL(conn, obj->def) &&
            virStoragePoolObjIsActive(obj)) {
            if (VIR_STRDUP(names[got], obj->def->name) < 0) {
                virStoragePoolObjUnlock(obj);
393 394 395 396
                goto cleanup;
            }
            got++;
        }
397
        virStoragePoolObjUnlock(obj);
398
    }
399
    storageDriverUnlock(driver);
400 401 402
    return got;

 cleanup:
403
    storageDriverUnlock(driver);
404
    for (i = 0; i < got; i++)
405
        VIR_FREE(names[i]);
406
    memset(names, 0, nnames * sizeof(*names));
407 408 409 410
    return -1;
}

static int
411
storageConnectNumOfDefinedStoragePools(virConnectPtr conn) {
412
    virStorageDriverStatePtr driver = conn->storagePrivateData;
413 414
    size_t i;
    int nactive = 0;
415

416 417 418
    if (virConnectNumOfDefinedStoragePoolsEnsureACL(conn) < 0)
        return -1;

419
    storageDriverLock(driver);
420
    for (i = 0; i < driver->pools.count; i++) {
421 422 423 424
        virStoragePoolObjPtr obj = driver->pools.objs[i];
        virStoragePoolObjLock(obj);
        if (virConnectNumOfDefinedStoragePoolsCheckACL(conn, obj->def) &&
            !virStoragePoolObjIsActive(obj))
425
            nactive++;
426
        virStoragePoolObjUnlock(obj);
427 428
    }
    storageDriverUnlock(driver);
429 430

    return nactive;
431 432 433
}

static int
434 435 436
storageConnectListDefinedStoragePools(virConnectPtr conn,
                                      char **const names,
                                      int nnames) {
437
    virStorageDriverStatePtr driver = conn->storagePrivateData;
438 439
    int got = 0;
    size_t i;
440

441 442 443
    if (virConnectListDefinedStoragePoolsEnsureACL(conn) < 0)
        return -1;

444
    storageDriverLock(driver);
445
    for (i = 0; i < driver->pools.count && got < nnames; i++) {
446 447 448 449 450 451
        virStoragePoolObjPtr obj = driver->pools.objs[i];
        virStoragePoolObjLock(obj);
        if (virConnectListDefinedStoragePoolsCheckACL(conn, obj->def) &&
            !virStoragePoolObjIsActive(obj)) {
            if (VIR_STRDUP(names[got], obj->def->name) < 0) {
                virStoragePoolObjUnlock(obj);
452 453 454 455
                goto cleanup;
            }
            got++;
        }
456
        virStoragePoolObjUnlock(obj);
457
    }
458
    storageDriverUnlock(driver);
459 460 461
    return got;

 cleanup:
462
    storageDriverUnlock(driver);
463
    for (i = 0; i < got; i++) {
464
        VIR_FREE(names[i]);
465
    }
466
    memset(names, 0, nnames * sizeof(*names));
467 468 469
    return -1;
}

470 471
/* This method is required to be re-entrant / thread safe, so
   uses no driver lock */
472
static char *
473 474 475 476
storageConnectFindStoragePoolSources(virConnectPtr conn,
                                     const char *type,
                                     const char *srcSpec,
                                     unsigned int flags)
477 478 479
{
    int backend_type;
    virStorageBackendPtr backend;
480
    char *ret = NULL;
481

482 483 484
    if (virConnectFindStoragePoolSourcesEnsureACL(conn) < 0)
        return NULL;

485
    backend_type = virStoragePoolTypeFromString(type);
486
    if (backend_type < 0) {
487 488
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
489
        goto cleanup;
490
    }
491 492 493

    backend = virStorageBackendForType(backend_type);
    if (backend == NULL)
494
        goto cleanup;
495

496
    if (!backend->findPoolSources) {
497 498 499
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source "
                         "discovery"), type);
500 501 502 503
        goto cleanup;
    }

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

505 506
cleanup:
    return ret;
507 508 509
}


510
static int storagePoolIsActive(virStoragePoolPtr pool)
511
{
512
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
513 514 515 516
    virStoragePoolObjPtr obj;
    int ret = -1;

    storageDriverLock(driver);
517
    obj = virStoragePoolObjFindByUUID(&driver->pools, pool->uuid);
518 519
    storageDriverUnlock(driver);
    if (!obj) {
520
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
521 522
        goto cleanup;
    }
523 524 525 526

    if (virStoragePoolIsActiveEnsureACL(pool->conn, obj->def) < 0)
        goto cleanup;

527 528 529 530 531 532 533 534
    ret = virStoragePoolObjIsActive(obj);

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

535
static int storagePoolIsPersistent(virStoragePoolPtr pool)
536
{
537
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
538 539 540 541
    virStoragePoolObjPtr obj;
    int ret = -1;

    storageDriverLock(driver);
542
    obj = virStoragePoolObjFindByUUID(&driver->pools, pool->uuid);
543 544
    storageDriverUnlock(driver);
    if (!obj) {
545
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
546 547
        goto cleanup;
    }
548 549 550 551

    if (virStoragePoolIsPersistentEnsureACL(pool->conn, obj->def) < 0)
        goto cleanup;

552 553 554 555 556 557 558 559 560
    ret = obj->configFile ? 1 : 0;

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


561
static virStoragePoolPtr
562 563 564
storagePoolCreateXML(virConnectPtr conn,
                     const char *xml,
                     unsigned int flags)
E
Eric Blake 已提交
565
{
566
    virStorageDriverStatePtr driver = conn->storagePrivateData;
567
    virStoragePoolDefPtr def;
568
    virStoragePoolObjPtr pool = NULL;
569
    virStoragePoolPtr ret = NULL;
570 571
    virStorageBackendPtr backend;

E
Eric Blake 已提交
572 573
    virCheckFlags(0, NULL);

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

578 579 580
    if (virStoragePoolCreateXMLEnsureACL(conn, def) < 0)
        goto cleanup;

581
    if (virStoragePoolObjIsDuplicate(&driver->pools, def, 1) < 0)
582
        goto cleanup;
583

584 585 586
    if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
        goto cleanup;

587 588
    if ((backend = virStorageBackendForType(def->type)) == NULL)
        goto cleanup;
589

590
    if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
591 592
        goto cleanup;
    def = NULL;
593

594
    if (backend->startPool &&
595 596 597
        backend->startPool(conn, pool) < 0) {
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
598
        goto cleanup;
599
    }
600

601 602 603
    if (backend->refreshPool(conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(conn, pool);
604 605
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
606
        goto cleanup;
607
    }
608
    VIR_INFO("Creating storage pool '%s'", pool->def->name);
609 610
    pool->active = 1;

611 612
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
613

614 615
cleanup:
    virStoragePoolDefFree(def);
616
    if (pool)
617
        virStoragePoolObjUnlock(pool);
618
    storageDriverUnlock(driver);
619 620 621 622
    return ret;
}

static virStoragePoolPtr
623 624 625
storagePoolDefineXML(virConnectPtr conn,
                     const char *xml,
                     unsigned int flags)
E
Eric Blake 已提交
626
{
627
    virStorageDriverStatePtr driver = conn->storagePrivateData;
628
    virStoragePoolDefPtr def;
629
    virStoragePoolObjPtr pool = NULL;
630
    virStoragePoolPtr ret = NULL;
631

E
Eric Blake 已提交
632 633
    virCheckFlags(0, NULL);

634
    storageDriverLock(driver);
635
    if (!(def = virStoragePoolDefParseString(xml)))
636
        goto cleanup;
637

638 639 640
    if (virStoragePoolDefineXMLEnsureACL(conn, def) < 0)
        goto cleanup;

641 642 643
    if (virStoragePoolObjIsDuplicate(&driver->pools, def, 0) < 0)
        goto cleanup;

644 645 646
    if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
        goto cleanup;

647
    if (virStorageBackendForType(def->type) == NULL)
648
        goto cleanup;
649

650
    if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
651
        goto cleanup;
652

653
    if (virStoragePoolObjSaveDef(driver, pool, def) < 0) {
654
        virStoragePoolObjRemove(&driver->pools, pool);
655
        def = NULL;
656
        goto cleanup;
657
    }
658
    def = NULL;
659

660
    VIR_INFO("Defining storage pool '%s'", pool->def->name);
661 662
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
663 664 665

cleanup:
    virStoragePoolDefFree(def);
666 667 668
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
669 670 671 672 673
    return ret;
}

static int
storagePoolUndefine(virStoragePoolPtr obj) {
674 675 676
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
677

678
    storageDriverLock(driver);
679
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
680
    if (!pool) {
681
        virReportError(VIR_ERR_NO_STORAGE_POOL,
682
                       _("no storage pool with matching uuid %s"), obj->uuid);
683
        goto cleanup;
684 685
    }

686 687 688
    if (virStoragePoolUndefineEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

689
    if (virStoragePoolObjIsActive(pool)) {
690
        virReportError(VIR_ERR_OPERATION_INVALID,
691 692
                       _("storage pool '%s' is still active"),
                       pool->def->name);
693
        goto cleanup;
694 695
    }

696
    if (pool->asyncjobs > 0) {
697 698 699
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
                       pool->def->name);
700 701 702
        goto cleanup;
    }

703
    if (virStoragePoolObjDeleteDef(pool) < 0)
704
        goto cleanup;
705

706 707
    if (unlink(pool->autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
        char ebuf[1024];
708
        VIR_ERROR(_("Failed to delete autostart link '%s': %s"),
709
                  pool->autostartLink, virStrerror(errno, ebuf, sizeof(ebuf)));
710
    }
711

712 713
    VIR_FREE(pool->configFile);
    VIR_FREE(pool->autostartLink);
714

715
    VIR_INFO("Undefining storage pool '%s'", pool->def->name);
716
    virStoragePoolObjRemove(&driver->pools, pool);
717
    pool = NULL;
718
    ret = 0;
719

720
cleanup:
721 722 723
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
724
    return ret;
725 726 727
}

static int
728 729
storagePoolCreate(virStoragePoolPtr obj,
                  unsigned int flags)
E
Eric Blake 已提交
730
{
731 732
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
733
    virStorageBackendPtr backend;
734
    int ret = -1;
735

E
Eric Blake 已提交
736 737
    virCheckFlags(0, -1);

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

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

748 749 750
    if (virStoragePoolCreateEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

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

    if (virStoragePoolObjIsActive(pool)) {
755
        virReportError(VIR_ERR_OPERATION_INVALID,
756 757
                       _("storage pool '%s' is already active"),
                       pool->def->name);
758
        goto cleanup;
759 760 761
    }
    if (backend->startPool &&
        backend->startPool(obj->conn, pool) < 0)
762 763
        goto cleanup;

764 765 766
    if (backend->refreshPool(obj->conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(obj->conn, pool);
767
        goto cleanup;
768 769
    }

770
    VIR_INFO("Starting up storage pool '%s'", pool->def->name);
771
    pool->active = 1;
772
    ret = 0;
773

774
cleanup:
775 776
    if (pool)
        virStoragePoolObjUnlock(pool);
777
    return ret;
778 779 780 781 782
}

static int
storagePoolBuild(virStoragePoolPtr obj,
                 unsigned int flags) {
783 784
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
785
    virStorageBackendPtr backend;
786
    int ret = -1;
787

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

792
    if (!pool) {
793
        virReportError(VIR_ERR_NO_STORAGE_POOL,
794
                       _("no storage pool with matching uuid %s"), obj->uuid);
795
        goto cleanup;
796 797
    }

798 799 800
    if (virStoragePoolBuildEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

801 802
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
803 804

    if (virStoragePoolObjIsActive(pool)) {
805
        virReportError(VIR_ERR_OPERATION_INVALID,
806 807
                       _("storage pool '%s' is already active"),
                       pool->def->name);
808
        goto cleanup;
809 810 811 812
    }

    if (backend->buildPool &&
        backend->buildPool(obj->conn, pool, flags) < 0)
813 814
        goto cleanup;
    ret = 0;
815

816
cleanup:
817 818
    if (pool)
        virStoragePoolObjUnlock(pool);
819
    return ret;
820 821 822 823 824
}


static int
storagePoolDestroy(virStoragePoolPtr obj) {
825 826
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
827
    virStorageBackendPtr backend;
828
    int ret = -1;
829

830
    storageDriverLock(driver);
831
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
832

833
    if (!pool) {
834
        virReportError(VIR_ERR_NO_STORAGE_POOL,
835
                       _("no storage pool with matching uuid %s"), obj->uuid);
836
        goto cleanup;
837 838
    }

839 840 841
    if (virStoragePoolDestroyEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

842 843
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
844 845

    if (!virStoragePoolObjIsActive(pool)) {
846
        virReportError(VIR_ERR_OPERATION_INVALID,
847
                       _("storage pool '%s' is not active"), pool->def->name);
848
        goto cleanup;
849 850
    }

851
    if (pool->asyncjobs > 0) {
852 853 854
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
                       pool->def->name);
855 856 857
        goto cleanup;
    }

858 859
    if (backend->stopPool &&
        backend->stopPool(obj->conn, pool) < 0)
860
        goto cleanup;
861 862 863 864

    virStoragePoolObjClearVols(pool);

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

867
    if (pool->configFile == NULL) {
868
        virStoragePoolObjRemove(&driver->pools, pool);
869
        pool = NULL;
870 871 872 873
    } else if (pool->newDef) {
        virStoragePoolDefFree(pool->def);
        pool->def = pool->newDef;
        pool->newDef = NULL;
874
    }
875
    ret = 0;
876

877
cleanup:
878 879 880
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
881
    return ret;
882 883 884 885 886
}

static int
storagePoolDelete(virStoragePoolPtr obj,
                  unsigned int flags) {
887 888
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
889
    virStorageBackendPtr backend;
890
    int ret = -1;
891

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

896
    if (!pool) {
897
        virReportError(VIR_ERR_NO_STORAGE_POOL,
898
                       _("no storage pool with matching uuid %s"), obj->uuid);
899
        goto cleanup;
900 901
    }

902 903 904
    if (virStoragePoolDeleteEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

905 906
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
907 908

    if (virStoragePoolObjIsActive(pool)) {
909
        virReportError(VIR_ERR_OPERATION_INVALID,
910 911
                       _("storage pool '%s' is still active"),
                       pool->def->name);
912
        goto cleanup;
913 914
    }

915
    if (pool->asyncjobs > 0) {
916 917
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
918 919 920 921
                              pool->def->name);
        goto cleanup;
    }

922
    if (!backend->deletePool) {
923 924
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("pool does not support pool deletion"));
925
        goto cleanup;
926 927
    }
    if (backend->deletePool(obj->conn, pool, flags) < 0)
928
        goto cleanup;
929
    VIR_INFO("Deleting storage pool '%s'", pool->def->name);
930
    ret = 0;
931

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


static int
storagePoolRefresh(virStoragePoolPtr obj,
E
Eric Blake 已提交
941 942
                   unsigned int flags)
{
943 944
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
945
    virStorageBackendPtr backend;
946
    int ret = -1;
947

E
Eric Blake 已提交
948 949
    virCheckFlags(0, -1);

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

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
    if (virStoragePoolRefreshEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

962 963
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
964 965

    if (!virStoragePoolObjIsActive(pool)) {
966
        virReportError(VIR_ERR_OPERATION_INVALID,
967
                       _("storage pool '%s' is not active"), pool->def->name);
968
        goto cleanup;
969 970
    }

971
    if (pool->asyncjobs > 0) {
972 973 974
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
                       pool->def->name);
975 976 977
        goto cleanup;
    }

978
    virStoragePoolObjClearVols(pool);
979
    if (backend->refreshPool(obj->conn, pool) < 0) {
980 981 982 983 984
        if (backend->stopPool)
            backend->stopPool(obj->conn, pool);

        pool->active = 0;

985
        if (pool->configFile == NULL) {
986
            virStoragePoolObjRemove(&driver->pools, pool);
987 988
            pool = NULL;
        }
989
        goto cleanup;
990
    }
991
    ret = 0;
992

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


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

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

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 1019 1020
    if (virStoragePoolGetInfoEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1021
    if (virStorageBackendForType(pool->def->type) == NULL)
1022
        goto cleanup;
1023 1024 1025 1026 1027 1028 1029 1030 1031

    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;
1032
    ret = 0;
1033

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

static char *
1041
storagePoolGetXMLDesc(virStoragePoolPtr obj,
E
Eric Blake 已提交
1042 1043
                      unsigned int flags)
{
1044 1045
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1046
    virStoragePoolDefPtr def;
1047
    char *ret = NULL;
1048

1049
    virCheckFlags(VIR_STORAGE_XML_INACTIVE, NULL);
E
Eric Blake 已提交
1050

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

1055
    if (!pool) {
1056
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1057
                       _("no storage pool with matching uuid %s"), obj->uuid);
1058
        goto cleanup;
1059 1060
    }

1061 1062 1063
    if (virStoragePoolGetXMLDescEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1064 1065 1066 1067 1068 1069
    if ((flags & VIR_STORAGE_XML_INACTIVE) && pool->newDef)
        def = pool->newDef;
    else
        def = pool->def;

    ret = virStoragePoolDefFormat(def);
1070 1071

cleanup:
1072 1073
    if (pool)
        virStoragePoolObjUnlock(pool);
1074
    return ret;
1075 1076 1077 1078 1079
}

static int
storagePoolGetAutostart(virStoragePoolPtr obj,
                        int *autostart) {
1080 1081 1082
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
1083

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

1088
    if (!pool) {
1089
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1090
                       _("no storage pool with matching uuid %s"), obj->uuid);
1091
        goto cleanup;
1092 1093
    }

1094 1095 1096
    if (virStoragePoolGetAutostartEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1097 1098 1099 1100 1101
    if (!pool->configFile) {
        *autostart = 0;
    } else {
        *autostart = pool->autostart;
    }
1102
    ret = 0;
1103

1104
cleanup:
1105 1106
    if (pool)
        virStoragePoolObjUnlock(pool);
1107
    return ret;
1108 1109 1110 1111 1112
}

static int
storagePoolSetAutostart(virStoragePoolPtr obj,
                        int autostart) {
1113 1114 1115
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
1116

1117
    storageDriverLock(driver);
1118
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1119

1120
    if (!pool) {
1121
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1122
                       _("no storage pool with matching uuid %s"), obj->uuid);
1123
        goto cleanup;
1124 1125
    }

1126 1127 1128
    if (virStoragePoolSetAutostartEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1129
    if (!pool->configFile) {
1130 1131
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("pool has no config file"));
1132
        goto cleanup;
1133 1134 1135 1136
    }

    autostart = (autostart != 0);

1137 1138
    if (pool->autostart != autostart) {
        if (autostart) {
1139 1140
            if (virFileMakePath(driver->autostartDir) < 0) {
                virReportSystemError(errno,
1141 1142
                                     _("cannot create autostart directory %s"),
                                     driver->autostartDir);
1143 1144
                goto cleanup;
            }
1145

1146
            if (symlink(pool->configFile, pool->autostartLink) < 0) {
1147
                virReportSystemError(errno,
1148 1149
                                     _("Failed to create symlink '%s' to '%s'"),
                                     pool->autostartLink, pool->configFile);
1150 1151 1152 1153 1154
                goto cleanup;
            }
        } else {
            if (unlink(pool->autostartLink) < 0 &&
                errno != ENOENT && errno != ENOTDIR) {
1155
                virReportSystemError(errno,
1156 1157
                                     _("Failed to delete symlink '%s'"),
                                     pool->autostartLink);
1158 1159
                goto cleanup;
            }
1160
        }
1161
        pool->autostart = autostart;
1162
    }
1163
    ret = 0;
1164

1165
cleanup:
1166 1167
    if (pool)
        virStoragePoolObjUnlock(pool);
1168
    storageDriverUnlock(driver);
1169
    return ret;
1170 1171 1172 1173
}


static int
1174
storagePoolNumOfVolumes(virStoragePoolPtr obj) {
1175 1176
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1177 1178
    int ret = -1;
    size_t i;
1179

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

1184
    if (!pool) {
1185
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1186
                       _("no storage pool with matching uuid %s"), obj->uuid);
1187
        goto cleanup;
1188 1189
    }

1190 1191 1192
    if (virStoragePoolNumOfVolumesEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1193
    if (!virStoragePoolObjIsActive(pool)) {
1194
        virReportError(VIR_ERR_OPERATION_INVALID,
1195
                       _("storage pool '%s' is not active"), pool->def->name);
1196
        goto cleanup;
1197
    }
1198 1199 1200 1201 1202 1203
    ret = 0;
    for (i = 0; i < pool->volumes.count; i++) {
        if (virStoragePoolNumOfVolumesCheckACL(obj->conn, pool->def,
                                               pool->volumes.objs[i]))
            ret++;
    }
1204

1205
cleanup:
1206 1207
    if (pool)
        virStoragePoolObjUnlock(pool);
1208
    return ret;
1209 1210 1211 1212 1213 1214
}

static int
storagePoolListVolumes(virStoragePoolPtr obj,
                       char **const names,
                       int maxnames) {
1215 1216
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1217 1218
    size_t i;
    int n = 0;
1219

1220 1221
    memset(names, 0, maxnames * sizeof(*names));

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

1226
    if (!pool) {
1227
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1228
                       _("no storage pool with matching uuid %s"), obj->uuid);
1229
        goto cleanup;
1230 1231
    }

1232 1233 1234
    if (virStoragePoolListVolumesEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1235
    if (!virStoragePoolObjIsActive(pool)) {
1236
        virReportError(VIR_ERR_OPERATION_INVALID,
1237
                       _("storage pool '%s' is not active"), pool->def->name);
1238
        goto cleanup;
1239 1240
    }

1241
    for (i = 0; i < pool->volumes.count && n < maxnames; i++) {
1242 1243 1244
        if (!virStoragePoolListVolumesCheckACL(obj->conn, pool->def,
                                               pool->volumes.objs[i]))
            continue;
1245
        if (VIR_STRDUP(names[n++], pool->volumes.objs[i]->name) < 0)
1246 1247 1248
            goto cleanup;
    }

1249
    virStoragePoolObjUnlock(pool);
1250
    return n;
1251 1252

 cleanup:
1253 1254
    if (pool)
        virStoragePoolObjUnlock(pool);
1255
    for (n = 0; n < maxnames; n++)
1256
        VIR_FREE(names[n]);
1257

1258
    memset(names, 0, maxnames * sizeof(*names));
1259 1260 1261
    return -1;
}

1262 1263 1264 1265 1266 1267
static int
storagePoolListAllVolumes(virStoragePoolPtr pool,
                          virStorageVolPtr **vols,
                          unsigned int flags) {
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
    virStoragePoolObjPtr obj;
1268
    size_t i;
1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280
    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) {
1281 1282 1283
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching uuid %s"),
                       pool->uuid);
1284 1285 1286
        goto cleanup;
    }

1287 1288 1289
    if (virStoragePoolListAllVolumesEnsureACL(pool->conn, obj->def) < 0)
        goto cleanup;

1290
    if (!virStoragePoolObjIsActive(obj)) {
1291 1292
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), obj->def->name);
1293 1294 1295 1296 1297 1298 1299 1300 1301
        goto cleanup;
    }

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

1302
    if (VIR_ALLOC_N(tmp_vols, obj->volumes.count + 1) < 0)
1303
        goto cleanup;
1304

1305
    for (i = 0; i < obj->volumes.count; i++) {
1306 1307 1308
        if (!virStoragePoolListAllVolumesCheckACL(pool->conn, obj->def,
                                                  obj->volumes.objs[i]))
            continue;
1309 1310
        if (!(vol = virGetStorageVol(pool->conn, obj->def->name,
                                     obj->volumes.objs[i]->name,
1311 1312
                                     obj->volumes.objs[i]->key,
                                     NULL, NULL)))
1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326
            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]);
        }
1327
        VIR_FREE(tmp_vols);
1328 1329 1330 1331 1332 1333 1334
    }

    if (obj)
        virStoragePoolObjUnlock(obj);

    return ret;
}
1335 1336

static virStorageVolPtr
1337 1338
storageVolLookupByName(virStoragePoolPtr obj,
                       const char *name) {
1339 1340
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1341
    virStorageVolDefPtr vol;
1342
    virStorageVolPtr ret = NULL;
1343

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

1348
    if (!pool) {
1349
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1350
                       _("no storage pool with matching uuid %s"), obj->uuid);
1351
        goto cleanup;
1352 1353 1354
    }

    if (!virStoragePoolObjIsActive(pool)) {
1355
        virReportError(VIR_ERR_OPERATION_INVALID,
1356
                       _("storage pool '%s' is not active"), pool->def->name);
1357
        goto cleanup;
1358 1359 1360 1361 1362
    }

    vol = virStorageVolDefFindByName(pool, name);

    if (!vol) {
1363 1364 1365
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       name);
1366
        goto cleanup;
1367 1368
    }

1369 1370 1371
    if (virStorageVolLookupByNameEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

1372 1373
    ret = virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key,
                           NULL, NULL);
1374 1375

cleanup:
1376 1377
    if (pool)
        virStoragePoolObjUnlock(pool);
1378
    return ret;
1379 1380 1381 1382
}


static virStorageVolPtr
1383 1384
storageVolLookupByKey(virConnectPtr conn,
                      const char *key) {
1385
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1386
    size_t i;
1387
    virStorageVolPtr ret = NULL;
1388

1389
    storageDriverLock(driver);
1390
    for (i = 0; i < driver->pools.count && !ret; i++) {
1391
        virStoragePoolObjLock(driver->pools.objs[i]);
1392 1393 1394
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
            virStorageVolDefPtr vol =
                virStorageVolDefFindByKey(driver->pools.objs[i], key);
1395

1396
            if (vol) {
1397 1398
                if (virStorageVolLookupByKeyEnsureACL(conn, driver->pools.objs[i]->def, vol) < 0) {
                    virStoragePoolObjUnlock(driver->pools.objs[i]);
1399
                    goto cleanup;
1400
                }
1401

1402
                ret = virGetStorageVol(conn,
1403 1404
                                       driver->pools.objs[i]->def->name,
                                       vol->name,
1405 1406
                                       vol->key,
                                       NULL, NULL);
1407
            }
1408
        }
1409
        virStoragePoolObjUnlock(driver->pools.objs[i]);
1410 1411
    }

1412
    if (!ret)
1413
        virReportError(VIR_ERR_NO_STORAGE_VOL,
1414
                       _("no storage vol with matching key %s"), key);
1415

1416 1417
cleanup:
    storageDriverUnlock(driver);
1418
    return ret;
1419 1420 1421
}

static virStorageVolPtr
1422 1423
storageVolLookupByPath(virConnectPtr conn,
                       const char *path) {
1424
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1425
    size_t i;
1426
    virStorageVolPtr ret = NULL;
1427 1428 1429 1430 1431
    char *cleanpath;

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

1433
    storageDriverLock(driver);
1434
    for (i = 0; i < driver->pools.count && !ret; i++) {
1435
        virStoragePoolObjLock(driver->pools.objs[i]);
1436
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
1437
            virStorageVolDefPtr vol;
1438 1439
            const char *stable_path;

1440
            stable_path = virStorageBackendStablePath(driver->pools.objs[i],
1441 1442
                                                      cleanpath,
                                                      false);
1443
            if (stable_path == NULL) {
1444 1445 1446 1447 1448
                /* 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);
1449
                virStoragePoolObjUnlock(driver->pools.objs[i]);
1450
                continue;
1451
            }
1452 1453 1454 1455

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

1457
            if (vol) {
1458 1459
                if (virStorageVolLookupByPathEnsureACL(conn, driver->pools.objs[i]->def, vol) < 0) {
                    virStoragePoolObjUnlock(driver->pools.objs[i]);
1460
                    goto cleanup;
1461
                }
1462

1463 1464 1465
                ret = virGetStorageVol(conn,
                                       driver->pools.objs[i]->def->name,
                                       vol->name,
1466 1467
                                       vol->key,
                                       NULL, NULL);
1468
            }
1469
        }
1470
        virStoragePoolObjUnlock(driver->pools.objs[i]);
1471 1472
    }

1473
    if (!ret)
1474
        virReportError(VIR_ERR_NO_STORAGE_VOL,
1475
                       _("no storage vol with matching path %s"), path);
1476

1477
cleanup:
1478
    VIR_FREE(cleanpath);
1479
    storageDriverUnlock(driver);
1480
    return ret;
1481 1482
}

1483
static int storageVolDelete(virStorageVolPtr obj, unsigned int flags);
1484

1485
static virStorageVolPtr
1486 1487 1488
storageVolCreateXML(virStoragePoolPtr obj,
                    const char *xmldesc,
                    unsigned int flags)
E
Eric Blake 已提交
1489
{
1490 1491
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1492
    virStorageBackendPtr backend;
1493 1494
    virStorageVolDefPtr voldef = NULL;
    virStorageVolPtr ret = NULL, volobj = NULL;
1495

1496
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
E
Eric Blake 已提交
1497

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

1502
    if (!pool) {
1503
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1504
                       _("no storage pool with matching uuid %s"), obj->uuid);
1505
        goto cleanup;
1506 1507 1508
    }

    if (!virStoragePoolObjIsActive(pool)) {
1509
        virReportError(VIR_ERR_OPERATION_INVALID,
1510
                       _("storage pool '%s' is not active"), pool->def->name);
1511
        goto cleanup;
1512 1513 1514
    }

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

1517
    voldef = virStorageVolDefParseString(pool->def, xmldesc);
1518
    if (voldef == NULL)
1519
        goto cleanup;
1520

1521 1522 1523
    if (virStorageVolCreateXMLEnsureACL(obj->conn, pool->def, voldef) < 0)
        goto cleanup;

1524
    if (virStorageVolDefFindByName(pool, voldef->name)) {
1525
        virReportError(VIR_ERR_NO_STORAGE_VOL,
1526
                       _("storage vol '%s' already exists"), voldef->name);
1527
        goto cleanup;
1528 1529
    }

1530
    if (VIR_REALLOC_N(pool->volumes.objs,
1531
                      pool->volumes.count+1) < 0)
1532
        goto cleanup;
1533

1534
    if (!backend->createVol) {
1535 1536 1537
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("storage pool does not support volume "
                               "creation"));
1538
        goto cleanup;
1539 1540
    }

1541
    if (backend->createVol(obj->conn, pool, voldef) < 0) {
1542
        goto cleanup;
1543 1544
    }

1545 1546
    pool->volumes.objs[pool->volumes.count++] = voldef;
    volobj = virGetStorageVol(obj->conn, pool->def->name, voldef->name,
1547
                              voldef->key, NULL, NULL);
1548 1549 1550 1551
    if (!volobj) {
        pool->volumes.count--;
        goto cleanup;
    }
1552

1553
    if (backend->buildVol) {
1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572
        int buildret;
        virStorageVolDefPtr buildvoldef = NULL;

        if (VIR_ALLOC(buildvoldef) < 0) {
            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);

1573
        buildret = backend->buildVol(obj->conn, pool, buildvoldef, flags);
1574

1575
        storageDriverLock(driver);
1576
        virStoragePoolObjLock(pool);
1577 1578
        storageDriverUnlock(driver);

1579 1580 1581 1582 1583 1584 1585 1586
        voldef->building = 0;
        pool->asyncjobs--;

        voldef = NULL;
        VIR_FREE(buildvoldef);

        if (buildret < 0) {
            virStoragePoolObjUnlock(pool);
1587
            storageVolDelete(volobj, 0);
1588 1589 1590 1591 1592 1593
            pool = NULL;
            goto cleanup;
        }

    }

1594
    VIR_INFO("Creating volume '%s' in storage pool '%s'",
1595
             volobj->name, pool->def->name);
1596 1597 1598
    ret = volobj;
    volobj = NULL;
    voldef = NULL;
1599

1600
cleanup:
1601
    virObjectUnref(volobj);
1602
    virStorageVolDefFree(voldef);
1603 1604
    if (pool)
        virStoragePoolObjUnlock(pool);
1605
    return ret;
1606 1607
}

1608
static virStorageVolPtr
1609 1610 1611 1612
storageVolCreateXMLFrom(virStoragePoolPtr obj,
                        const char *xmldesc,
                        virStorageVolPtr vobj,
                        unsigned int flags)
E
Eric Blake 已提交
1613
{
1614 1615 1616 1617 1618
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool, origpool = NULL;
    virStorageBackendPtr backend;
    virStorageVolDefPtr origvol = NULL, newvol = NULL;
    virStorageVolPtr ret = NULL, volobj = NULL;
1619
    int buildret;
1620

1621
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
E
Eric Blake 已提交
1622

1623 1624
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1625
    if (pool && STRNEQ(obj->name, vobj->pool)) {
1626
        virStoragePoolObjUnlock(pool);
1627
        origpool = virStoragePoolObjFindByName(&driver->pools, vobj->pool);
1628
        virStoragePoolObjLock(pool);
1629
    }
1630 1631
    storageDriverUnlock(driver);
    if (!pool) {
1632
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1633
                       _("no storage pool with matching uuid %s"), obj->uuid);
1634 1635 1636
        goto cleanup;
    }

1637
    if (STRNEQ(obj->name, vobj->pool) && !origpool) {
1638 1639 1640
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       vobj->pool);
1641 1642 1643 1644
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1645
        virReportError(VIR_ERR_OPERATION_INVALID,
1646
                       _("storage pool '%s' is not active"), pool->def->name);
1647 1648 1649
        goto cleanup;
    }

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

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

1660
    origvol = virStorageVolDefFindByName(origpool ? origpool : pool, vobj->name);
1661
    if (!origvol) {
1662 1663 1664
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vobj->name);
1665 1666 1667
        goto cleanup;
    }

1668
    newvol = virStorageVolDefParseString(pool->def, xmldesc);
1669 1670 1671
    if (newvol == NULL)
        goto cleanup;

1672 1673 1674
    if (virStorageVolCreateXMLFromEnsureACL(obj->conn, pool->def, newvol) < 0)
        goto cleanup;

1675
    if (virStorageVolDefFindByName(pool, newvol->name)) {
1676 1677 1678
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("storage volume name '%s' already in use."),
                       newvol->name);
1679 1680 1681 1682 1683 1684 1685
        goto cleanup;
    }

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

1686 1687 1688 1689 1690
    /* 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;

1691
    if (!backend->buildVolFrom) {
1692 1693
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("storage pool does not support volume creation from an existing volume"));
1694 1695 1696 1697
        goto cleanup;
    }

    if (origvol->building) {
1698 1699 1700
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       origvol->name);
1701 1702 1703 1704 1705 1706 1707 1708
        goto cleanup;
    }

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

    if (VIR_REALLOC_N(pool->volumes.objs,
1709
                      pool->volumes.count+1) < 0)
1710 1711 1712 1713 1714 1715 1716 1717 1718
        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,
1719
                              newvol->key, NULL, NULL);
1720 1721 1722 1723 1724 1725 1726

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

1727
    if (origpool) {
1728 1729 1730 1731
        origpool->asyncjobs++;
        virStoragePoolObjUnlock(origpool);
    }

1732
    buildret = backend->buildVolFrom(obj->conn, pool, newvol, origvol, flags);
1733 1734 1735

    storageDriverLock(driver);
    virStoragePoolObjLock(pool);
1736
    if (origpool)
1737 1738 1739 1740 1741 1742 1743 1744
        virStoragePoolObjLock(origpool);
    storageDriverUnlock(driver);

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

1745
    if (origpool) {
1746 1747 1748 1749 1750 1751 1752
        origpool->asyncjobs--;
        virStoragePoolObjUnlock(origpool);
        origpool = NULL;
    }

    if (buildret < 0) {
        virStoragePoolObjUnlock(pool);
1753
        storageVolDelete(volobj, 0);
1754 1755 1756 1757
        pool = NULL;
        goto cleanup;
    }

1758
    VIR_INFO("Creating volume '%s' in storage pool '%s'",
1759
             volobj->name, pool->def->name);
1760 1761 1762 1763
    ret = volobj;
    volobj = NULL;

cleanup:
1764
    virObjectUnref(volobj);
1765 1766 1767
    virStorageVolDefFree(newvol);
    if (pool)
        virStoragePoolObjUnlock(pool);
1768
    if (origpool)
1769 1770 1771 1772
        virStoragePoolObjUnlock(origpool);
    return ret;
}

1773

1774
static int
1775 1776 1777 1778 1779
storageVolDownload(virStorageVolPtr obj,
                   virStreamPtr stream,
                   unsigned long long offset,
                   unsigned long long length,
                   unsigned int flags)
1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792
{
    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) {
1793
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1794 1795
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1796 1797 1798 1799
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1800
        virReportError(VIR_ERR_OPERATION_INVALID,
1801
                       _("storage pool '%s' is not active"), pool->def->name);
1802 1803 1804 1805 1806 1807
        goto out;
    }

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

    if (vol == NULL) {
1808 1809 1810
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1811 1812 1813
        goto out;
    }

1814 1815 1816
    if (virStorageVolDownloadEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

1817
    if (vol->building) {
1818 1819 1820
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1821 1822 1823 1824 1825 1826
        goto out;
    }

    if (virFDStreamOpenFile(stream,
                            vol->target.path,
                            offset, length,
E
Eric Blake 已提交
1827
                            O_RDONLY) < 0)
1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840
        goto out;

    ret = 0;

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}


static int
1841 1842 1843 1844 1845
storageVolUpload(virStorageVolPtr obj,
                 virStreamPtr stream,
                 unsigned long long offset,
                 unsigned long long length,
                 unsigned int flags)
1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858
{
    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) {
1859
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1860 1861
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1862 1863 1864 1865
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1866
        virReportError(VIR_ERR_OPERATION_INVALID,
1867
                       _("storage pool '%s' is not active"), pool->def->name);
1868 1869 1870 1871 1872 1873
        goto out;
    }

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

    if (vol == NULL) {
1874 1875 1876
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1877 1878 1879
        goto out;
    }

1880 1881 1882
    if (virStorageVolUploadEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

1883
    if (vol->building) {
1884 1885 1886
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1887 1888 1889 1890 1891 1892 1893 1894
        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 已提交
1895
                            O_WRONLY) < 0)
1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906
        goto out;

    ret = 0;

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}

1907
static int
1908 1909 1910
storageVolResize(virStorageVolPtr obj,
                 unsigned long long capacity,
                 unsigned int flags)
1911 1912 1913 1914 1915 1916 1917 1918
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStorageBackendPtr backend;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    unsigned long long abs_capacity;
    int ret = -1;

1919
    virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE |
1920 1921
                  VIR_STORAGE_VOL_RESIZE_DELTA |
                  VIR_STORAGE_VOL_RESIZE_SHRINK, -1);
1922 1923 1924 1925 1926 1927

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

    if (!pool) {
1928 1929 1930
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1931 1932 1933 1934
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1935 1936
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->def->name);
1937 1938 1939 1940 1941 1942 1943 1944 1945
        goto out;
    }

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

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

    if (vol == NULL) {
1946 1947 1948
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1949 1950 1951
        goto out;
    }

1952 1953 1954
    if (virStorageVolResizeEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

1955
    if (vol->building) {
1956 1957 1958
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1959 1960
        goto out;
    }
1961

1962 1963 1964 1965 1966 1967 1968 1969
    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) {
1970
        virReportError(VIR_ERR_INVALID_ARG, "%s",
1971 1972
                       _("can't shrink capacity below "
                         "existing allocation"));
1973 1974 1975
        goto out;
    }

1976 1977 1978 1979 1980 1981 1982 1983
    if (abs_capacity < vol->capacity &&
        !(flags & VIR_STORAGE_VOL_RESIZE_SHRINK)) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("Can't shrink capacity below current "
                         "capacity with shrink flag explicitly specified"));
        goto out;
    }

1984
    if (abs_capacity > vol->capacity + pool->def->available) {
1985
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
1986
                       _("Not enough space left on storage pool"));
1987 1988 1989 1990
        goto out;
    }

    if (!backend->resizeVol) {
1991
        virReportError(VIR_ERR_NO_SUPPORT, "%s",
1992 1993
                       _("storage pool does not support changing of "
                         "volume capacity"));
1994 1995 1996 1997 1998 1999
        goto out;
    }

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

O
Osier Yang 已提交
2000 2001
    vol->capacity = abs_capacity;
    ret = 0;
2002 2003 2004 2005 2006 2007 2008

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
2009

2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024
/* 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
2025 2026 2027
storageVolZeroSparseFile(virStorageVolDefPtr vol,
                         off_t size,
                         int fd)
2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043
{
    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 "
2044
                               "path '%s' to %ju bytes"),
E
Eric Blake 已提交
2045
                             vol->target.path, (uintmax_t)size);
2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066
    }

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 已提交
2067
              (uintmax_t)extent_start, (uintmax_t)extent_length);
2068 2069 2070 2071 2072

    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 已提交
2073
                             (uintmax_t)extent_start, vol->target.path);
2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094
        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;
    }

2095 2096 2097 2098 2099 2100 2101 2102
    if (fdatasync(fd) < 0) {
        ret = -errno;
        virReportSystemError(errno,
                             _("cannot sync data to volume with path '%s'"),
                             vol->target.path);
        goto out;
    }

2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113
    VIR_DEBUG("Wrote %zu bytes to volume with path '%s'",
              *bytes_wiped, vol->target.path);

    ret = 0;

out:
    return ret;
}


static int
2114 2115
storageVolWipeInternal(virStorageVolDefPtr def,
                       unsigned int algorithm)
2116 2117 2118 2119 2120
{
    int ret = -1, fd = -1;
    struct stat st;
    char *writebuf = NULL;
    size_t bytes_wiped = 0;
2121
    virCommandPtr cmd = NULL;
2122

2123 2124
    VIR_DEBUG("Wiping volume with path '%s' and algorithm %u",
              def->target.path, algorithm);
2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140

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

2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156
    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 已提交
2157
            alg_char = "schneier";
2158 2159 2160 2161 2162
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7:
            alg_char = "pfitzner7";
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33:
M
Michal Privoznik 已提交
2163
            alg_char = "pfitzner33";
2164 2165 2166 2167 2168
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_RANDOM:
            alg_char = "random";
            break;
        default:
2169 2170 2171
            virReportError(VIR_ERR_INVALID_ARG,
                           _("unsupported algorithm %d"),
                           algorithm);
2172 2173 2174 2175
        }
        cmd = virCommandNew(SCRUB);
        virCommandAddArgList(cmd, "-f", "-p", alg_char,
                             def->target.path, NULL);
2176

2177
        if (virCommandRun(cmd, NULL) < 0)
2178 2179
            goto out;

2180 2181 2182 2183
        ret = 0;
        goto out;
    } else {
        if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) {
2184
            ret = storageVolZeroSparseFile(def, st.st_size, fd);
2185 2186
        } else {

2187
            if (VIR_ALLOC_N(writebuf, st.st_blksize) < 0)
2188 2189 2190 2191 2192 2193 2194 2195 2196 2197
                goto out;

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

out:
2201
    virCommandFree(cmd);
2202
    VIR_FREE(writebuf);
2203
    VIR_FORCE_CLOSE(fd);
2204 2205 2206 2207 2208
    return ret;
}


static int
2209 2210 2211
storageVolWipePattern(virStorageVolPtr obj,
                      unsigned int algorithm,
                      unsigned int flags)
2212 2213 2214 2215 2216 2217
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    int ret = -1;

2218
    virCheckFlags(0, -1);
2219

2220
    if (algorithm >= VIR_STORAGE_VOL_WIPE_ALG_LAST) {
2221 2222 2223
        virReportError(VIR_ERR_INVALID_ARG,
                       _("wiping algorithm %d not supported"),
                       algorithm);
2224 2225 2226
        return -1;
    }

2227 2228 2229 2230 2231
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
    storageDriverUnlock(driver);

    if (!pool) {
2232
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2233 2234
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2235 2236 2237 2238
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
2239
        virReportError(VIR_ERR_OPERATION_INVALID,
2240
                       _("storage pool '%s' is not active"), pool->def->name);
2241 2242 2243 2244 2245 2246
        goto out;
    }

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

    if (vol == NULL) {
2247 2248 2249
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2250 2251 2252
        goto out;
    }

2253 2254 2255
    if (virStorageVolWipePatternEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

2256
    if (vol->building) {
2257 2258 2259
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
2260 2261 2262
        goto out;
    }

2263
    if (storageVolWipeInternal(vol, algorithm) == -1) {
2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277
        goto out;
    }

    ret = 0;

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

    return ret;

}

2278
static int
2279 2280
storageVolWipe(virStorageVolPtr obj,
               unsigned int flags)
2281
{
2282
    return storageVolWipePattern(obj, VIR_STORAGE_VOL_WIPE_ALG_ZERO, flags);
2283 2284
}

2285
static int
2286 2287
storageVolDelete(virStorageVolPtr obj,
                 unsigned int flags) {
2288 2289
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2290
    virStorageBackendPtr backend;
2291
    virStorageVolDefPtr vol = NULL;
2292
    size_t i;
2293
    int ret = -1;
2294

2295
    storageDriverLock(driver);
2296
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2297 2298
    storageDriverUnlock(driver);

2299
    if (!pool) {
2300
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2301 2302
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2303
        goto cleanup;
2304 2305 2306
    }

    if (!virStoragePoolObjIsActive(pool)) {
2307
        virReportError(VIR_ERR_OPERATION_INVALID,
2308
                       _("storage pool '%s' is not active"), pool->def->name);
2309
        goto cleanup;
2310 2311 2312
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2313
        goto cleanup;
2314 2315 2316 2317

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

    if (!vol) {
2318 2319 2320
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2321
        goto cleanup;
2322 2323
    }

2324 2325 2326
    if (virStorageVolDeleteEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2327
    if (vol->building) {
2328 2329 2330
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
2331 2332 2333
        goto cleanup;
    }

2334
    if (!backend->deleteVol) {
2335 2336
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("storage pool does not support vol deletion"));
2337

2338
        goto cleanup;
2339 2340
    }

2341 2342 2343
    if (backend->deleteVol(obj->conn, pool, vol, flags) < 0)
        goto cleanup;

2344
    for (i = 0; i < pool->volumes.count; i++) {
2345
        if (pool->volumes.objs[i] == vol) {
2346
            VIR_INFO("Deleting volume '%s' from storage pool '%s'",
2347
                     vol->name, pool->def->name);
2348
            virStorageVolDefFree(vol);
2349
            vol = NULL;
2350 2351 2352 2353 2354 2355 2356 2357 2358 2359

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

2360 2361 2362
            break;
        }
    }
2363
    ret = 0;
2364

2365
cleanup:
2366 2367
    if (pool)
        virStoragePoolObjUnlock(pool);
2368
    return ret;
2369 2370 2371
}

static int
2372 2373
storageVolGetInfo(virStorageVolPtr obj,
                  virStorageVolInfoPtr info) {
2374 2375
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2376 2377
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
2378
    int ret = -1;
2379

2380
    storageDriverLock(driver);
2381
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2382 2383
    storageDriverUnlock(driver);

2384
    if (!pool) {
2385
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2386 2387
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2388
        goto cleanup;
2389 2390 2391
    }

    if (!virStoragePoolObjIsActive(pool)) {
2392
        virReportError(VIR_ERR_OPERATION_INVALID,
2393
                       _("storage pool '%s' is not active"), pool->def->name);
2394
        goto cleanup;
2395 2396 2397 2398 2399
    }

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

    if (!vol) {
2400 2401 2402
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2403
        goto cleanup;
2404 2405
    }

2406 2407 2408
    if (virStorageVolGetInfoEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2409
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2410
        goto cleanup;
2411 2412 2413

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

    memset(info, 0, sizeof(*info));
2417
    info->type = vol->type;
2418 2419
    info->capacity = vol->capacity;
    info->allocation = vol->allocation;
2420
    ret = 0;
2421

2422
cleanup:
2423 2424
    if (pool)
        virStoragePoolObjUnlock(pool);
2425
    return ret;
2426 2427 2428
}

static char *
2429 2430
storageVolGetXMLDesc(virStorageVolPtr obj,
                     unsigned int flags)
E
Eric Blake 已提交
2431
{
2432 2433
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2434 2435
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
2436
    char *ret = NULL;
2437

E
Eric Blake 已提交
2438 2439
    virCheckFlags(0, NULL);

2440
    storageDriverLock(driver);
2441
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2442 2443
    storageDriverUnlock(driver);

2444
    if (!pool) {
2445
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2446 2447
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2448
        goto cleanup;
2449 2450 2451
    }

    if (!virStoragePoolObjIsActive(pool)) {
2452
        virReportError(VIR_ERR_OPERATION_INVALID,
2453
                       _("storage pool '%s' is not active"), pool->def->name);
2454
        goto cleanup;
2455 2456 2457 2458 2459
    }

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

    if (!vol) {
2460 2461 2462
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2463
        goto cleanup;
2464 2465
    }

2466 2467 2468
    if (virStorageVolGetXMLDescEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2469
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2470
        goto cleanup;
2471 2472 2473 2474

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

2476
    ret = virStorageVolDefFormat(pool->def, vol);
2477 2478

cleanup:
2479 2480 2481
    if (pool)
        virStoragePoolObjUnlock(pool);

2482
    return ret;
2483 2484 2485
}

static char *
2486
storageVolGetPath(virStorageVolPtr obj) {
2487
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
2488
    virStoragePoolObjPtr pool;
2489
    virStorageVolDefPtr vol;
2490
    char *ret = NULL;
2491

2492 2493 2494
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
    storageDriverUnlock(driver);
2495
    if (!pool) {
2496
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2497 2498
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2499
        goto cleanup;
2500 2501 2502
    }

    if (!virStoragePoolObjIsActive(pool)) {
2503
        virReportError(VIR_ERR_OPERATION_INVALID,
2504
                       _("storage pool '%s' is not active"), pool->def->name);
2505
        goto cleanup;
2506 2507 2508 2509 2510
    }

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

    if (!vol) {
2511 2512 2513
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2514
        goto cleanup;
2515 2516
    }

2517 2518 2519
    if (virStorageVolGetPathEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2520
    ignore_value(VIR_STRDUP(ret, vol->target.path));
2521 2522

cleanup:
2523 2524
    if (pool)
        virStoragePoolObjUnlock(pool);
2525 2526 2527
    return ret;
}

2528
static int
2529 2530 2531
storageConnectListAllStoragePools(virConnectPtr conn,
                                  virStoragePoolPtr **pools,
                                  unsigned int flags)
2532 2533 2534 2535 2536 2537
{
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

2538 2539 2540
    if (virConnectListAllStoragePoolsEnsureACL(conn) < 0)
        goto cleanup;

2541
    storageDriverLock(driver);
2542 2543
    ret = virStoragePoolObjListExport(conn, driver->pools, pools,
                                      virConnectListAllStoragePoolsCheckACL, flags);
2544 2545
    storageDriverUnlock(driver);

2546
cleanup:
2547 2548 2549
    return ret;
}

2550
static virStorageDriver storageDriver = {
2551
    .name = "storage",
2552 2553
    .storageOpen = storageOpen, /* 0.4.0 */
    .storageClose = storageClose, /* 0.4.0 */
2554 2555 2556 2557 2558 2559
    .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 */
2560 2561 2562
    .storagePoolLookupByName = storagePoolLookupByName, /* 0.4.0 */
    .storagePoolLookupByUUID = storagePoolLookupByUUID, /* 0.4.0 */
    .storagePoolLookupByVolume = storagePoolLookupByVolume, /* 0.4.0 */
2563 2564
    .storagePoolCreateXML = storagePoolCreateXML, /* 0.4.0 */
    .storagePoolDefineXML = storagePoolDefineXML, /* 0.4.0 */
2565 2566
    .storagePoolBuild = storagePoolBuild, /* 0.4.0 */
    .storagePoolUndefine = storagePoolUndefine, /* 0.4.0 */
2567
    .storagePoolCreate = storagePoolCreate, /* 0.4.0 */
2568 2569 2570 2571 2572 2573 2574
    .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 */
2575
    .storagePoolNumOfVolumes = storagePoolNumOfVolumes, /* 0.4.0 */
2576 2577 2578
    .storagePoolListVolumes = storagePoolListVolumes, /* 0.4.0 */
    .storagePoolListAllVolumes = storagePoolListAllVolumes, /* 0.10.2 */

2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592
    .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 */
2593 2594 2595

    .storagePoolIsActive = storagePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = storagePoolIsPersistent, /* 0.7.3 */
2596 2597 2598 2599
};


static virStateDriver stateDriver = {
2600
    .name = "Storage",
2601 2602 2603
    .stateInitialize = storageStateInitialize,
    .stateCleanup = storageStateCleanup,
    .stateReload = storageStateReload,
2604 2605 2606 2607 2608 2609 2610
};

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