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

54 55
#define VIR_FROM_THIS VIR_FROM_STORAGE

56 57
VIR_LOG_INIT("storage.storage_driver");

58 59
static virStorageDriverStatePtr driverState;

60
static int storageStateCleanup(void);
61

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

static void
72 73
storageDriverAutostart(virStorageDriverStatePtr driver)
{
74
    size_t i;
75 76 77 78 79 80 81 82
    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 */
83

84
    for (i = 0; i < driver->pools.count; i++) {
85
        virStoragePoolObjPtr pool = driver->pools.objs[i];
86 87
        virStorageBackendPtr backend;
        bool started = false;
88

89
        virStoragePoolObjLock(pool);
90 91 92 93 94
        if ((backend = virStorageBackendForType(pool->def->type)) == NULL) {
            VIR_ERROR(_("Missing backend %d"), pool->def->type);
            virStoragePoolObjUnlock(pool);
            continue;
        }
95

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

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

137
    virObjectUnref(conn);
138 139 140 141 142 143 144 145
}

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

152
    if (VIR_ALLOC(driverState) < 0)
153 154
        return -1;

155 156 157 158
    if (virMutexInit(&driverState->lock) < 0) {
        VIR_FREE(driverState);
        return -1;
    }
159 160
    storageDriverLock(driverState);

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

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

178 179
    if (virAsprintf(&driverState->autostartDir,
                    "%s/storage/autostart", base) == -1)
180
        goto error;
181

182
    VIR_FREE(base);
183

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

189
    storageDriverUnlock(driverState);
190 191
    return 0;

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

199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
/**
 * storageStateAutoStart:
 *
 * Function to auto start the storage driver
 */
static void
storageStateAutoStart(void)
{
    if (!driverState)
        return;

    storageDriverLock(driverState);
    storageDriverAutostart(driverState);
    storageDriverUnlock(driverState);
}

215
/**
216
 * storageStateReload:
217 218 219 220 221
 *
 * Function to restart the storage driver, it will recheck the configuration
 * files and update its state
 */
static int
222 223
storageStateReload(void)
{
224 225 226
    if (!driverState)
        return -1;

227
    storageDriverLock(driverState);
228
    virStoragePoolLoadAllConfigs(&driverState->pools,
229 230
                                 driverState->configDir,
                                 driverState->autostartDir);
231
    storageDriverAutostart(driverState);
232
    storageDriverUnlock(driverState);
233 234 235 236 237 238

    return 0;
}


/**
239
 * storageStateCleanup
240 241 242 243
 *
 * Shutdown the storage driver, it will stop all active storage pools
 */
static int
244 245
storageStateCleanup(void)
{
246 247 248
    if (!driverState)
        return -1;

249
    storageDriverLock(driverState);
250 251

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

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

    return 0;
}



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

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

277
    if (!pool) {
278 279
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(uuid, uuidstr);
280
        virReportError(VIR_ERR_NO_STORAGE_POOL,
281 282
                       _("no storage pool with matching uuid '%s'"), uuidstr);
        return NULL;
283 284
    }

285 286 287
    if (virStoragePoolLookupByUUIDEnsureACL(conn, pool->def) < 0)
        goto cleanup;

288 289
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
290

291
 cleanup:
292
    virStoragePoolObjUnlock(pool);
293 294 295 296 297
    return ret;
}

static virStoragePoolPtr
storagePoolLookupByName(virConnectPtr conn,
298 299
                        const char *name)
{
300 301 302
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
303

304
    storageDriverLock(driver);
305
    pool = virStoragePoolObjFindByName(&driver->pools, name);
306 307
    storageDriverUnlock(driver);

308
    if (!pool) {
309
        virReportError(VIR_ERR_NO_STORAGE_POOL,
310
                       _("no storage pool with matching name '%s'"), name);
311
        return NULL;
312 313
    }

314 315 316
    if (virStoragePoolLookupByNameEnsureACL(conn, pool->def) < 0)
        goto cleanup;

317 318
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
319

320
 cleanup:
321
    virStoragePoolObjUnlock(pool);
322 323 324 325
    return ret;
}

static virStoragePoolPtr
326 327
storagePoolLookupByVolume(virStorageVolPtr vol)
{
328 329 330 331 332 333 334 335 336 337 338
    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);
339
        return NULL;
340 341 342 343 344 345 346 347
    }

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

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

348
 cleanup:
349
    virStoragePoolObjUnlock(pool);
350
    return ret;
351 352 353 354 355
}

static virDrvOpenStatus
storageOpen(virConnectPtr conn,
            virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
356 357 358 359
            unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

360 361 362 363 364 365 366 367
    if (!driverState)
        return VIR_DRV_OPEN_DECLINED;

    conn->storagePrivateData = driverState;
    return VIR_DRV_OPEN_SUCCESS;
}

static int
368 369
storageClose(virConnectPtr conn)
{
370 371 372 373 374
    conn->storagePrivateData = NULL;
    return 0;
}

static int
375 376
storageConnectNumOfStoragePools(virConnectPtr conn)
{
377
    virStorageDriverStatePtr driver = conn->storagePrivateData;
378 379
    size_t i;
    int nactive = 0;
380

381 382 383
    if (virConnectNumOfStoragePoolsEnsureACL(conn) < 0)
        return -1;

384
    storageDriverLock(driver);
385
    for (i = 0; i < driver->pools.count; i++) {
386 387 388
        virStoragePoolObjPtr obj = driver->pools.objs[i];
        virStoragePoolObjLock(obj);
        if (virConnectNumOfStoragePoolsCheckACL(conn, obj->def) &&
389
            virStoragePoolObjIsActive(obj))
390
            nactive++;
391
        virStoragePoolObjUnlock(obj);
392 393
    }
    storageDriverUnlock(driver);
394 395

    return nactive;
396 397 398
}

static int
399 400
storageConnectListStoragePools(virConnectPtr conn,
                               char **const names,
401 402
                               int nnames)
{
403
    virStorageDriverStatePtr driver = conn->storagePrivateData;
404 405
    int got = 0;
    size_t i;
406

407 408 409
    if (virConnectListStoragePoolsEnsureACL(conn) < 0)
        return -1;

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

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

static int
436 437
storageConnectNumOfDefinedStoragePools(virConnectPtr conn)
{
438
    virStorageDriverStatePtr driver = conn->storagePrivateData;
439 440
    size_t i;
    int nactive = 0;
441

442 443 444
    if (virConnectNumOfDefinedStoragePoolsEnsureACL(conn) < 0)
        return -1;

445
    storageDriverLock(driver);
446
    for (i = 0; i < driver->pools.count; i++) {
447 448 449
        virStoragePoolObjPtr obj = driver->pools.objs[i];
        virStoragePoolObjLock(obj);
        if (virConnectNumOfDefinedStoragePoolsCheckACL(conn, obj->def) &&
450
            !virStoragePoolObjIsActive(obj))
451
            nactive++;
452
        virStoragePoolObjUnlock(obj);
453 454
    }
    storageDriverUnlock(driver);
455 456

    return nactive;
457 458 459
}

static int
460 461
storageConnectListDefinedStoragePools(virConnectPtr conn,
                                      char **const names,
462 463
                                      int nnames)
{
464
    virStorageDriverStatePtr driver = conn->storagePrivateData;
465 466
    int got = 0;
    size_t i;
467

468 469 470
    if (virConnectListDefinedStoragePoolsEnsureACL(conn) < 0)
        return -1;

471
    storageDriverLock(driver);
472
    for (i = 0; i < driver->pools.count && got < nnames; i++) {
473 474 475
        virStoragePoolObjPtr obj = driver->pools.objs[i];
        virStoragePoolObjLock(obj);
        if (virConnectListDefinedStoragePoolsCheckACL(conn, obj->def) &&
476
            !virStoragePoolObjIsActive(obj)) {
477 478
            if (VIR_STRDUP(names[got], obj->def->name) < 0) {
                virStoragePoolObjUnlock(obj);
479 480 481 482
                goto cleanup;
            }
            got++;
        }
483
        virStoragePoolObjUnlock(obj);
484
    }
485
    storageDriverUnlock(driver);
486 487 488
    return got;

 cleanup:
489
    storageDriverUnlock(driver);
490
    for (i = 0; i < got; i++) {
491
        VIR_FREE(names[i]);
492
    }
493
    memset(names, 0, nnames * sizeof(*names));
494 495 496
    return -1;
}

497 498
/* This method is required to be re-entrant / thread safe, so
   uses no driver lock */
499
static char *
500 501 502 503
storageConnectFindStoragePoolSources(virConnectPtr conn,
                                     const char *type,
                                     const char *srcSpec,
                                     unsigned int flags)
504 505 506
{
    int backend_type;
    virStorageBackendPtr backend;
507
    char *ret = NULL;
508

509 510 511
    if (virConnectFindStoragePoolSourcesEnsureACL(conn) < 0)
        return NULL;

512
    backend_type = virStoragePoolTypeFromString(type);
513
    if (backend_type < 0) {
514 515
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
516
        goto cleanup;
517
    }
518 519 520

    backend = virStorageBackendForType(backend_type);
    if (backend == NULL)
521
        goto cleanup;
522

523
    if (!backend->findPoolSources) {
524 525 526
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source "
                         "discovery"), type);
527 528 529 530
        goto cleanup;
    }

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

532
 cleanup:
533
    return ret;
534 535 536
}


537 538
static virStoragePoolObjPtr
virStoragePoolObjFromStoragePool(virStoragePoolPtr pool)
539
{
540
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
541 542
    char uuidstr[VIR_UUID_STRING_BUFLEN];
    virStoragePoolObjPtr ret;
543 544

    storageDriverLock(driver);
545 546 547 548 549
    if (!(ret = virStoragePoolObjFindByUUID(&driver->pools, pool->uuid))) {
        virUUIDFormat(pool->uuid, uuidstr);
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching uuid '%s' (%s)"),
                       uuidstr, pool->name);
550
    }
551 552 553 554 555 556 557 558 559 560 561 562 563
    storageDriverUnlock(driver);

    return ret;
}


static int storagePoolIsActive(virStoragePoolPtr pool)
{
    virStoragePoolObjPtr obj;
    int ret = -1;

    if (!(obj = virStoragePoolObjFromStoragePool(pool)))
        return -1;
564 565 566 567

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

568 569
    ret = virStoragePoolObjIsActive(obj);

570
 cleanup:
571
    virStoragePoolObjUnlock(obj);
572 573 574
    return ret;
}

575
static int storagePoolIsPersistent(virStoragePoolPtr pool)
576 577 578 579
{
    virStoragePoolObjPtr obj;
    int ret = -1;

580 581
    if (!(obj = virStoragePoolObjFromStoragePool(pool)))
        return -1;
582 583 584 585

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

586 587
    ret = obj->configFile ? 1 : 0;

588
 cleanup:
589
    virStoragePoolObjUnlock(obj);
590 591 592 593
    return ret;
}


594
static virStoragePoolPtr
595 596 597
storagePoolCreateXML(virConnectPtr conn,
                     const char *xml,
                     unsigned int flags)
E
Eric Blake 已提交
598
{
599
    virStorageDriverStatePtr driver = conn->storagePrivateData;
600
    virStoragePoolDefPtr def;
601
    virStoragePoolObjPtr pool = NULL;
602
    virStoragePoolPtr ret = NULL;
603 604
    virStorageBackendPtr backend;

E
Eric Blake 已提交
605 606
    virCheckFlags(0, NULL);

607
    storageDriverLock(driver);
608
    if (!(def = virStoragePoolDefParseString(xml)))
609
        goto cleanup;
610

611 612 613
    if (virStoragePoolCreateXMLEnsureACL(conn, def) < 0)
        goto cleanup;

614
    if (virStoragePoolObjIsDuplicate(&driver->pools, def, 1) < 0)
615
        goto cleanup;
616

617 618 619
    if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
        goto cleanup;

620 621
    if ((backend = virStorageBackendForType(def->type)) == NULL)
        goto cleanup;
622

623
    if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
624 625
        goto cleanup;
    def = NULL;
626

627
    if (backend->startPool &&
628 629 630
        backend->startPool(conn, pool) < 0) {
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
631
        goto cleanup;
632
    }
633

634 635 636
    if (backend->refreshPool(conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(conn, pool);
637 638
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
639
        goto cleanup;
640
    }
641
    VIR_INFO("Creating storage pool '%s'", pool->def->name);
642 643
    pool->active = 1;

644 645
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
646

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

static virStoragePoolPtr
656 657 658
storagePoolDefineXML(virConnectPtr conn,
                     const char *xml,
                     unsigned int flags)
E
Eric Blake 已提交
659
{
660
    virStorageDriverStatePtr driver = conn->storagePrivateData;
661
    virStoragePoolDefPtr def;
662
    virStoragePoolObjPtr pool = NULL;
663
    virStoragePoolPtr ret = NULL;
664

E
Eric Blake 已提交
665 666
    virCheckFlags(0, NULL);

667
    storageDriverLock(driver);
668
    if (!(def = virStoragePoolDefParseString(xml)))
669
        goto cleanup;
670

671 672 673
    if (virStoragePoolDefineXMLEnsureACL(conn, def) < 0)
        goto cleanup;

674 675 676
    if (virStoragePoolObjIsDuplicate(&driver->pools, def, 0) < 0)
        goto cleanup;

677 678 679
    if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
        goto cleanup;

680
    if (virStorageBackendForType(def->type) == NULL)
681
        goto cleanup;
682

683
    if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
684
        goto cleanup;
685

686
    if (virStoragePoolObjSaveDef(driver, pool, def) < 0) {
687
        virStoragePoolObjRemove(&driver->pools, pool);
688
        def = NULL;
689
        goto cleanup;
690
    }
691
    def = NULL;
692

693
    VIR_INFO("Defining storage pool '%s'", pool->def->name);
694 695
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
696

697
 cleanup:
698
    virStoragePoolDefFree(def);
699 700 701
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
702 703 704 705
    return ret;
}

static int
706 707
storagePoolUndefine(virStoragePoolPtr obj)
{
708 709 710
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
711

712
    storageDriverLock(driver);
713 714 715
    if (!(pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid))) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(obj->uuid, uuidstr);
716
        virReportError(VIR_ERR_NO_STORAGE_POOL,
717 718
                       _("no storage pool with matching uuid '%s' (%s)"),
                       uuidstr, obj->name);
719
        goto cleanup;
720 721
    }

722 723 724
    if (virStoragePoolUndefineEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

725
    if (virStoragePoolObjIsActive(pool)) {
726
        virReportError(VIR_ERR_OPERATION_INVALID,
727 728
                       _("storage pool '%s' is still active"),
                       pool->def->name);
729
        goto cleanup;
730 731
    }

732
    if (pool->asyncjobs > 0) {
733 734 735
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
                       pool->def->name);
736 737 738
        goto cleanup;
    }

739
    if (virStoragePoolObjDeleteDef(pool) < 0)
740
        goto cleanup;
741

742 743
    if (unlink(pool->autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
        char ebuf[1024];
744
        VIR_ERROR(_("Failed to delete autostart link '%s': %s"),
745
                  pool->autostartLink, virStrerror(errno, ebuf, sizeof(ebuf)));
746
    }
747

748 749
    VIR_FREE(pool->configFile);
    VIR_FREE(pool->autostartLink);
750

751
    VIR_INFO("Undefining storage pool '%s'", pool->def->name);
752
    virStoragePoolObjRemove(&driver->pools, pool);
753
    pool = NULL;
754
    ret = 0;
755

756
 cleanup:
757 758 759
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
760
    return ret;
761 762 763
}

static int
764 765
storagePoolCreate(virStoragePoolPtr obj,
                  unsigned int flags)
E
Eric Blake 已提交
766
{
767
    virStoragePoolObjPtr pool;
768
    virStorageBackendPtr backend;
769
    int ret = -1;
770

E
Eric Blake 已提交
771 772
    virCheckFlags(0, -1);

773 774
    if (!(pool = virStoragePoolObjFromStoragePool(obj)))
        return -1;
775

776 777 778
    if (virStoragePoolCreateEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

779 780
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
781 782

    if (virStoragePoolObjIsActive(pool)) {
783
        virReportError(VIR_ERR_OPERATION_INVALID,
784 785
                       _("storage pool '%s' is already active"),
                       pool->def->name);
786
        goto cleanup;
787 788 789
    }
    if (backend->startPool &&
        backend->startPool(obj->conn, pool) < 0)
790 791
        goto cleanup;

792 793 794
    if (backend->refreshPool(obj->conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(obj->conn, pool);
795
        goto cleanup;
796 797
    }

798
    VIR_INFO("Starting up storage pool '%s'", pool->def->name);
799
    pool->active = 1;
800
    ret = 0;
801

802
 cleanup:
803
    virStoragePoolObjUnlock(pool);
804
    return ret;
805 806 807 808
}

static int
storagePoolBuild(virStoragePoolPtr obj,
809 810
                 unsigned int flags)
{
811
    virStoragePoolObjPtr pool;
812
    virStorageBackendPtr backend;
813
    int ret = -1;
814

815 816
    if (!(pool = virStoragePoolObjFromStoragePool(obj)))
        return -1;
817

818 819 820
    if (virStoragePoolBuildEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

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

    if (virStoragePoolObjIsActive(pool)) {
825
        virReportError(VIR_ERR_OPERATION_INVALID,
826 827
                       _("storage pool '%s' is already active"),
                       pool->def->name);
828
        goto cleanup;
829 830 831 832
    }

    if (backend->buildPool &&
        backend->buildPool(obj->conn, pool, flags) < 0)
833 834
        goto cleanup;
    ret = 0;
835

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


static int
843 844
storagePoolDestroy(virStoragePoolPtr obj)
{
845 846
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
847
    virStorageBackendPtr backend;
848
    int ret = -1;
849

850
    storageDriverLock(driver);
851 852 853
    if (!(pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid))) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(obj->uuid, uuidstr);
854
        virReportError(VIR_ERR_NO_STORAGE_POOL,
855 856
                       _("no storage pool with matching uuid '%s' (%s)"),
                       uuidstr, obj->name);
857
        goto cleanup;
858 859
    }

860 861 862
    if (virStoragePoolDestroyEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

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 880
    if (backend->stopPool &&
        backend->stopPool(obj->conn, pool) < 0)
881
        goto cleanup;
882 883 884 885

    virStoragePoolObjClearVols(pool);

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

888
    if (pool->configFile == NULL) {
889
        virStoragePoolObjRemove(&driver->pools, pool);
890
        pool = NULL;
891 892 893 894
    } else if (pool->newDef) {
        virStoragePoolDefFree(pool->def);
        pool->def = pool->newDef;
        pool->newDef = NULL;
895
    }
896
    ret = 0;
897

898
 cleanup:
899 900 901
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
902
    return ret;
903 904 905 906
}

static int
storagePoolDelete(virStoragePoolPtr obj,
907 908
                  unsigned int flags)
{
909
    virStoragePoolObjPtr pool;
910
    virStorageBackendPtr backend;
911
    int ret = -1;
912

913 914
    if (!(pool = virStoragePoolObjFromStoragePool(obj)))
        return -1;
915

916 917 918
    if (virStoragePoolDeleteEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

919 920
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
921 922

    if (virStoragePoolObjIsActive(pool)) {
923
        virReportError(VIR_ERR_OPERATION_INVALID,
924 925
                       _("storage pool '%s' is still active"),
                       pool->def->name);
926
        goto cleanup;
927 928
    }

929
    if (pool->asyncjobs > 0) {
930 931
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
932 933 934 935
                              pool->def->name);
        goto cleanup;
    }

936
    if (!backend->deletePool) {
937 938
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("pool does not support pool deletion"));
939
        goto cleanup;
940 941
    }
    if (backend->deletePool(obj->conn, pool, flags) < 0)
942
        goto cleanup;
943
    VIR_INFO("Deleting storage pool '%s'", pool->def->name);
944
    ret = 0;
945

946
 cleanup:
947
    virStoragePoolObjUnlock(pool);
948
    return ret;
949 950 951 952 953
}


static int
storagePoolRefresh(virStoragePoolPtr obj,
E
Eric Blake 已提交
954 955
                   unsigned int flags)
{
956 957
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
958
    virStorageBackendPtr backend;
959
    int ret = -1;
960

E
Eric Blake 已提交
961 962
    virCheckFlags(0, -1);

963
    storageDriverLock(driver);
964 965 966
    if (!(pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid))) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(obj->uuid, uuidstr);
967
        virReportError(VIR_ERR_NO_STORAGE_POOL,
968 969
                       _("no storage pool with matching uuid '%s' (%s)"),
                       uuidstr, obj->name);
970
        goto cleanup;
971 972
    }

973 974 975
    if (virStoragePoolRefreshEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

976 977
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
978 979

    if (!virStoragePoolObjIsActive(pool)) {
980
        virReportError(VIR_ERR_OPERATION_INVALID,
981
                       _("storage pool '%s' is not active"), pool->def->name);
982
        goto cleanup;
983 984
    }

985
    if (pool->asyncjobs > 0) {
986 987 988
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
                       pool->def->name);
989 990 991
        goto cleanup;
    }

992
    virStoragePoolObjClearVols(pool);
993
    if (backend->refreshPool(obj->conn, pool) < 0) {
994 995 996 997 998
        if (backend->stopPool)
            backend->stopPool(obj->conn, pool);

        pool->active = 0;

999
        if (pool->configFile == NULL) {
1000
            virStoragePoolObjRemove(&driver->pools, pool);
1001 1002
            pool = NULL;
        }
1003
        goto cleanup;
1004
    }
1005
    ret = 0;
1006

1007
 cleanup:
1008 1009
    if (pool)
        virStoragePoolObjUnlock(pool);
1010
    storageDriverUnlock(driver);
1011 1012 1013 1014 1015 1016
    return ret;
}


static int
storagePoolGetInfo(virStoragePoolPtr obj,
1017 1018
                   virStoragePoolInfoPtr info)
{
1019 1020
    virStoragePoolObjPtr pool;
    int ret = -1;
1021

1022 1023
    if (!(pool = virStoragePoolObjFromStoragePool(obj)))
        return -1;
1024

1025 1026 1027
    if (virStoragePoolGetInfoEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1028
    if (virStorageBackendForType(pool->def->type) == NULL)
1029
        goto cleanup;
1030 1031 1032 1033 1034 1035 1036 1037 1038

    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;
1039
    ret = 0;
1040

1041
 cleanup:
1042
    virStoragePoolObjUnlock(pool);
1043
    return ret;
1044 1045 1046
}

static char *
1047
storagePoolGetXMLDesc(virStoragePoolPtr obj,
E
Eric Blake 已提交
1048 1049
                      unsigned int flags)
{
1050
    virStoragePoolObjPtr pool;
1051
    virStoragePoolDefPtr def;
1052
    char *ret = NULL;
1053

1054
    virCheckFlags(VIR_STORAGE_XML_INACTIVE, NULL);
E
Eric Blake 已提交
1055

1056 1057
    if (!(pool = virStoragePoolObjFromStoragePool(obj)))
        return NULL;
1058

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

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

    ret = virStoragePoolDefFormat(def);
1068

1069
 cleanup:
1070
    virStoragePoolObjUnlock(pool);
1071
    return ret;
1072 1073 1074 1075
}

static int
storagePoolGetAutostart(virStoragePoolPtr obj,
1076 1077
                        int *autostart)
{
1078 1079
    virStoragePoolObjPtr pool;
    int ret = -1;
1080

1081 1082
    if (!(pool = virStoragePoolObjFromStoragePool(obj)))
        return -1;
1083

1084 1085 1086
    if (virStoragePoolGetAutostartEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1087 1088 1089 1090 1091
    if (!pool->configFile) {
        *autostart = 0;
    } else {
        *autostart = pool->autostart;
    }
1092
    ret = 0;
1093

1094
 cleanup:
1095
    virStoragePoolObjUnlock(pool);
1096
    return ret;
1097 1098 1099 1100
}

static int
storagePoolSetAutostart(virStoragePoolPtr obj,
1101 1102
                        int autostart)
{
1103 1104 1105
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
1106

1107
    storageDriverLock(driver);
1108
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1109

1110
    if (!pool) {
1111 1112
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(obj->uuid, uuidstr);
1113
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1114 1115
                       _("no storage pool with matching uuid '%s' (%s)"),
                       uuidstr, obj->name);
1116
        goto cleanup;
1117 1118
    }

1119 1120 1121
    if (virStoragePoolSetAutostartEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1122
    if (!pool->configFile) {
1123 1124
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("pool has no config file"));
1125
        goto cleanup;
1126 1127 1128 1129
    }

    autostart = (autostart != 0);

1130 1131
    if (pool->autostart != autostart) {
        if (autostart) {
1132 1133
            if (virFileMakePath(driver->autostartDir) < 0) {
                virReportSystemError(errno,
1134 1135
                                     _("cannot create autostart directory %s"),
                                     driver->autostartDir);
1136 1137
                goto cleanup;
            }
1138

1139
            if (symlink(pool->configFile, pool->autostartLink) < 0) {
1140
                virReportSystemError(errno,
1141 1142
                                     _("Failed to create symlink '%s' to '%s'"),
                                     pool->autostartLink, pool->configFile);
1143 1144 1145 1146 1147
                goto cleanup;
            }
        } else {
            if (unlink(pool->autostartLink) < 0 &&
                errno != ENOENT && errno != ENOTDIR) {
1148
                virReportSystemError(errno,
1149 1150
                                     _("Failed to delete symlink '%s'"),
                                     pool->autostartLink);
1151 1152
                goto cleanup;
            }
1153
        }
1154
        pool->autostart = autostart;
1155
    }
1156
    ret = 0;
1157

1158
 cleanup:
1159 1160
    if (pool)
        virStoragePoolObjUnlock(pool);
1161
    storageDriverUnlock(driver);
1162
    return ret;
1163 1164 1165 1166
}


static int
1167 1168
storagePoolNumOfVolumes(virStoragePoolPtr obj)
{
1169
    virStoragePoolObjPtr pool;
1170 1171
    int ret = -1;
    size_t i;
1172

1173 1174
    if (!(pool = virStoragePoolObjFromStoragePool(obj)))
        return -1;
1175

1176 1177 1178
    if (virStoragePoolNumOfVolumesEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1179
    if (!virStoragePoolObjIsActive(pool)) {
1180
        virReportError(VIR_ERR_OPERATION_INVALID,
1181
                       _("storage pool '%s' is not active"), pool->def->name);
1182
        goto cleanup;
1183
    }
1184 1185 1186 1187 1188 1189
    ret = 0;
    for (i = 0; i < pool->volumes.count; i++) {
        if (virStoragePoolNumOfVolumesCheckACL(obj->conn, pool->def,
                                               pool->volumes.objs[i]))
            ret++;
    }
1190

1191
 cleanup:
1192
    virStoragePoolObjUnlock(pool);
1193
    return ret;
1194 1195 1196 1197 1198
}

static int
storagePoolListVolumes(virStoragePoolPtr obj,
                       char **const names,
1199 1200
                       int maxnames)
{
1201
    virStoragePoolObjPtr pool;
1202 1203
    size_t i;
    int n = 0;
1204

1205 1206
    memset(names, 0, maxnames * sizeof(*names));

1207 1208
    if (!(pool = virStoragePoolObjFromStoragePool(obj)))
        return -1;
1209

1210 1211 1212
    if (virStoragePoolListVolumesEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1213
    if (!virStoragePoolObjIsActive(pool)) {
1214
        virReportError(VIR_ERR_OPERATION_INVALID,
1215
                       _("storage pool '%s' is not active"), pool->def->name);
1216
        goto cleanup;
1217 1218
    }

1219
    for (i = 0; i < pool->volumes.count && n < maxnames; i++) {
1220 1221 1222
        if (!virStoragePoolListVolumesCheckACL(obj->conn, pool->def,
                                               pool->volumes.objs[i]))
            continue;
1223
        if (VIR_STRDUP(names[n++], pool->volumes.objs[i]->name) < 0)
1224 1225 1226
            goto cleanup;
    }

1227
    virStoragePoolObjUnlock(pool);
1228
    return n;
1229 1230

 cleanup:
1231
    virStoragePoolObjUnlock(pool);
1232
    for (n = 0; n < maxnames; n++)
1233
        VIR_FREE(names[n]);
1234

1235
    memset(names, 0, maxnames * sizeof(*names));
1236 1237 1238
    return -1;
}

1239 1240 1241
static int
storagePoolListAllVolumes(virStoragePoolPtr pool,
                          virStorageVolPtr **vols,
1242 1243
                          unsigned int flags)
{
1244
    virStoragePoolObjPtr obj;
1245
    size_t i;
1246 1247 1248 1249 1250 1251 1252
    virStorageVolPtr *tmp_vols = NULL;
    virStorageVolPtr vol = NULL;
    int nvols = 0;
    int ret = -1;

    virCheckFlags(0, -1);

1253 1254
    if (!(obj = virStoragePoolObjFromStoragePool(pool)))
        return -1;
1255

1256 1257 1258
    if (virStoragePoolListAllVolumesEnsureACL(pool->conn, obj->def) < 0)
        goto cleanup;

1259
    if (!virStoragePoolObjIsActive(obj)) {
1260 1261
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), obj->def->name);
1262 1263 1264 1265 1266 1267 1268 1269 1270
        goto cleanup;
    }

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

1271
    if (VIR_ALLOC_N(tmp_vols, obj->volumes.count + 1) < 0)
1272
        goto cleanup;
1273

1274
    for (i = 0; i < obj->volumes.count; i++) {
1275 1276 1277
        if (!virStoragePoolListAllVolumesCheckACL(pool->conn, obj->def,
                                                  obj->volumes.objs[i]))
            continue;
1278 1279
        if (!(vol = virGetStorageVol(pool->conn, obj->def->name,
                                     obj->volumes.objs[i]->name,
1280 1281
                                     obj->volumes.objs[i]->key,
                                     NULL, NULL)))
1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295
            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]);
        }
1296
        VIR_FREE(tmp_vols);
1297 1298
    }

1299
    virStoragePoolObjUnlock(obj);
1300 1301 1302

    return ret;
}
1303 1304

static virStorageVolPtr
1305
storageVolLookupByName(virStoragePoolPtr obj,
1306 1307
                       const char *name)
{
1308
    virStoragePoolObjPtr pool;
1309
    virStorageVolDefPtr vol;
1310
    virStorageVolPtr ret = NULL;
1311

1312 1313
    if (!(pool = virStoragePoolObjFromStoragePool(obj)))
        return NULL;
1314 1315

    if (!virStoragePoolObjIsActive(pool)) {
1316
        virReportError(VIR_ERR_OPERATION_INVALID,
1317
                       _("storage pool '%s' is not active"), pool->def->name);
1318
        goto cleanup;
1319 1320 1321 1322 1323
    }

    vol = virStorageVolDefFindByName(pool, name);

    if (!vol) {
1324 1325 1326
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       name);
1327
        goto cleanup;
1328 1329
    }

1330 1331 1332
    if (virStorageVolLookupByNameEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

1333 1334
    ret = virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key,
                           NULL, NULL);
1335

1336
 cleanup:
1337
    virStoragePoolObjUnlock(pool);
1338
    return ret;
1339 1340 1341 1342
}


static virStorageVolPtr
1343
storageVolLookupByKey(virConnectPtr conn,
1344 1345
                      const char *key)
{
1346
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1347
    size_t i;
1348
    virStorageVolPtr ret = NULL;
1349

1350
    storageDriverLock(driver);
1351
    for (i = 0; i < driver->pools.count && !ret; i++) {
1352
        virStoragePoolObjLock(driver->pools.objs[i]);
1353 1354 1355
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
            virStorageVolDefPtr vol =
                virStorageVolDefFindByKey(driver->pools.objs[i], key);
1356

1357
            if (vol) {
1358 1359
                if (virStorageVolLookupByKeyEnsureACL(conn, driver->pools.objs[i]->def, vol) < 0) {
                    virStoragePoolObjUnlock(driver->pools.objs[i]);
1360
                    goto cleanup;
1361
                }
1362

1363
                ret = virGetStorageVol(conn,
1364 1365
                                       driver->pools.objs[i]->def->name,
                                       vol->name,
1366 1367
                                       vol->key,
                                       NULL, NULL);
1368
            }
1369
        }
1370
        virStoragePoolObjUnlock(driver->pools.objs[i]);
1371 1372
    }

1373
    if (!ret)
1374
        virReportError(VIR_ERR_NO_STORAGE_VOL,
1375
                       _("no storage vol with matching key %s"), key);
1376

1377
 cleanup:
1378
    storageDriverUnlock(driver);
1379
    return ret;
1380 1381 1382
}

static virStorageVolPtr
1383
storageVolLookupByPath(virConnectPtr conn,
1384 1385
                       const char *path)
{
1386
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1387
    size_t i;
1388
    virStorageVolPtr ret = NULL;
1389 1390 1391 1392 1393
    char *cleanpath;

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

1395
    storageDriverLock(driver);
1396
    for (i = 0; i < driver->pools.count && !ret; i++) {
1397 1398 1399 1400 1401
        virStoragePoolObjPtr pool = driver->pools.objs[i];
        virStorageVolDefPtr vol;
        char *stable_path = NULL;

        virStoragePoolObjLock(pool);
1402

1403 1404 1405 1406
        if (!virStoragePoolObjIsActive(pool)) {
           virStoragePoolObjUnlock(pool);
           continue;
        }
1407

1408
        switch ((virStoragePoolType) pool->def->type) {
1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436
            case VIR_STORAGE_POOL_DIR:
            case VIR_STORAGE_POOL_FS:
            case VIR_STORAGE_POOL_NETFS:
            case VIR_STORAGE_POOL_LOGICAL:
            case VIR_STORAGE_POOL_DISK:
            case VIR_STORAGE_POOL_ISCSI:
            case VIR_STORAGE_POOL_SCSI:
            case VIR_STORAGE_POOL_MPATH:
                stable_path = virStorageBackendStablePath(pool,
                                                          cleanpath,
                                                          false);
                if (stable_path == NULL) {
                    /* 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'",
                             pool->def->name);
                    virStoragePoolObjUnlock(pool);
                    continue;
                }
                break;

            case VIR_STORAGE_POOL_GLUSTER:
            case VIR_STORAGE_POOL_RBD:
            case VIR_STORAGE_POOL_SHEEPDOG:
            case VIR_STORAGE_POOL_LAST:
                if (VIR_STRDUP(stable_path, path) < 0) {
                     virStoragePoolObjUnlock(pool);
1437
                    goto cleanup;
1438
                }
1439 1440
                break;
        }
1441

1442 1443 1444 1445 1446 1447 1448
        vol = virStorageVolDefFindByPath(pool, stable_path);
        VIR_FREE(stable_path);

        if (vol) {
            if (virStorageVolLookupByPathEnsureACL(conn, pool->def, vol) < 0) {
                virStoragePoolObjUnlock(pool);
                goto cleanup;
1449
            }
1450 1451 1452 1453

            ret = virGetStorageVol(conn, pool->def->name,
                                   vol->name, vol->key,
                                   NULL, NULL);
1454
        }
1455 1456

        virStoragePoolObjUnlock(pool);
1457 1458
    }

1459 1460 1461 1462 1463 1464 1465 1466 1467 1468
    if (!ret) {
        if (STREQ(path, cleanpath)) {
            virReportError(VIR_ERR_NO_STORAGE_VOL,
                           _("no storage vol with matching path '%s'"), path);
        } else {
            virReportError(VIR_ERR_NO_STORAGE_VOL,
                           _("no storage vol with matching path '%s' (%s)"),
                           path, cleanpath);
        }
    }
1469

1470
 cleanup:
1471
    VIR_FREE(cleanpath);
1472
    storageDriverUnlock(driver);
1473
    return ret;
1474 1475
}

1476

1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522
static int
storageVolDeleteInternal(virStorageVolPtr obj,
                         virStorageBackendPtr backend,
                         virStoragePoolObjPtr pool,
                         virStorageVolDefPtr vol,
                         unsigned int flags,
                         bool updateMeta)
{
    size_t i;
    int ret = -1;

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

        goto cleanup;
    }

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

    /* Update pool metadata - don't update meta data from error paths
     * in this module since the allocation/available weren't adjusted yet
     */
    if (updateMeta) {
        pool->def->allocation -= vol->target.allocation;
        pool->def->available += vol->target.allocation;
    }

    for (i = 0; i < pool->volumes.count; i++) {
        if (pool->volumes.objs[i] == vol) {
            VIR_INFO("Deleting volume '%s' from storage pool '%s'",
                     vol->name, pool->def->name);
            virStorageVolDefFree(vol);

            VIR_DELETE_ELEMENT(pool->volumes.objs, i, pool->volumes.count);
            break;
        }
    }
    ret = 0;

 cleanup:
    return ret;
}


1523 1524 1525 1526
static virStorageVolDefPtr
virStorageVolDefFromVol(virStorageVolPtr obj,
                        virStoragePoolObjPtr *pool,
                        virStorageBackendPtr *backend)
1527 1528 1529
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStorageVolDefPtr vol = NULL;
1530 1531

    *pool = NULL;
1532 1533

    storageDriverLock(driver);
1534
    *pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
1535 1536
    storageDriverUnlock(driver);

1537
    if (!*pool) {
1538 1539 1540
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1541
        return NULL;
1542 1543
    }

1544
    if (!virStoragePoolObjIsActive(*pool)) {
1545
        virReportError(VIR_ERR_OPERATION_INVALID,
1546 1547 1548
                       _("storage pool '%s' is not active"),
                       (*pool)->def->name);
        goto error;
1549 1550
    }

1551
    if (!(vol = virStorageVolDefFindByName(*pool, obj->name))) {
1552 1553 1554
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1555
        goto error;
1556 1557
    }

1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584
    if (backend) {
        if (!(*backend = virStorageBackendForType((*pool)->def->type)))
            goto error;
    }

    return vol;

 error:
    virStoragePoolObjUnlock(*pool);
    *pool = NULL;

    return NULL;
}


static int
storageVolDelete(virStorageVolPtr obj,
                 unsigned int flags)
{
    virStoragePoolObjPtr pool;
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol = NULL;
    int ret = -1;

    if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
        return -1;

1585 1586 1587
    if (virStorageVolDeleteEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

1588 1589 1590 1591 1592 1593 1594
    if (vol->in_use) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still in use."),
                       vol->name);
        goto cleanup;
    }

1595 1596 1597 1598 1599 1600 1601
    if (vol->building) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
        goto cleanup;
    }

1602
    if (storageVolDeleteInternal(obj, backend, pool, vol, flags, true) < 0)
1603 1604 1605 1606
        goto cleanup;

    ret = 0;

1607
 cleanup:
1608
    virStoragePoolObjUnlock(pool);
1609 1610 1611
    return ret;
}

1612

1613
static virStorageVolPtr
1614 1615 1616
storageVolCreateXML(virStoragePoolPtr obj,
                    const char *xmldesc,
                    unsigned int flags)
E
Eric Blake 已提交
1617
{
1618 1619
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1620
    virStorageBackendPtr backend;
1621 1622
    virStorageVolDefPtr voldef = NULL;
    virStorageVolPtr ret = NULL, volobj = NULL;
1623
    virStorageVolDefPtr buildvoldef = NULL;
1624

1625
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
E
Eric Blake 已提交
1626

1627 1628
    if (!(pool = virStoragePoolObjFromStoragePool(obj)))
        return NULL;
1629 1630

    if (!virStoragePoolObjIsActive(pool)) {
1631
        virReportError(VIR_ERR_OPERATION_INVALID,
1632
                       _("storage pool '%s' is not active"), pool->def->name);
1633
        goto cleanup;
1634 1635 1636
    }

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

1639
    voldef = virStorageVolDefParseString(pool->def, xmldesc);
1640
    if (voldef == NULL)
1641
        goto cleanup;
1642

1643 1644 1645
    if (virStorageVolCreateXMLEnsureACL(obj->conn, pool->def, voldef) < 0)
        goto cleanup;

1646
    if (virStorageVolDefFindByName(pool, voldef->name)) {
1647
        virReportError(VIR_ERR_STORAGE_VOL_EXIST,
1648
                       _("'%s'"), voldef->name);
1649
        goto cleanup;
1650 1651
    }

1652
    if (VIR_REALLOC_N(pool->volumes.objs,
1653
                      pool->volumes.count+1) < 0)
1654
        goto cleanup;
1655

1656
    if (!backend->createVol) {
1657 1658 1659
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("storage pool does not support volume "
                               "creation"));
1660
        goto cleanup;
1661 1662
    }

1663 1664 1665
    /* Wipe any key the user may have suggested, as volume creation
     * will generate the canonical key.  */
    VIR_FREE(voldef->key);
1666
    if (backend->createVol(obj->conn, pool, voldef) < 0) {
1667
        goto cleanup;
1668 1669
    }

1670 1671
    pool->volumes.objs[pool->volumes.count++] = voldef;
    volobj = virGetStorageVol(obj->conn, pool->def->name, voldef->name,
1672
                              voldef->key, NULL, NULL);
1673 1674 1675 1676
    if (!volobj) {
        pool->volumes.count--;
        goto cleanup;
    }
1677

1678 1679 1680 1681
    if (VIR_ALLOC(buildvoldef) < 0) {
        voldef = NULL;
        goto cleanup;
    }
1682

1683 1684 1685 1686 1687
    /* 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));
1688

1689 1690
    if (backend->buildVol) {
        int buildret;
1691 1692 1693 1694 1695 1696

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

1697
        buildret = backend->buildVol(obj->conn, pool, buildvoldef, flags);
1698

1699
        storageDriverLock(driver);
1700
        virStoragePoolObjLock(pool);
1701 1702
        storageDriverUnlock(driver);

1703 1704 1705 1706
        voldef->building = 0;
        pool->asyncjobs--;

        if (buildret < 0) {
1707 1708
            VIR_FREE(buildvoldef);
            storageVolDeleteInternal(volobj, backend, pool, voldef,
1709
                                     0, false);
1710
            voldef = NULL;
1711 1712 1713 1714 1715
            goto cleanup;
        }

    }

1716
    /* Update pool metadata */
1717 1718
    pool->def->allocation += buildvoldef->target.allocation;
    pool->def->available -= buildvoldef->target.allocation;
1719

1720
    VIR_INFO("Creating volume '%s' in storage pool '%s'",
1721
             volobj->name, pool->def->name);
1722 1723 1724
    ret = volobj;
    volobj = NULL;
    voldef = NULL;
1725

1726
 cleanup:
1727
    virObjectUnref(volobj);
1728
    virStorageVolDefFree(voldef);
1729
    VIR_FREE(buildvoldef);
1730 1731
    if (pool)
        virStoragePoolObjUnlock(pool);
1732
    return ret;
1733 1734
}

1735
static virStorageVolPtr
1736 1737 1738 1739
storageVolCreateXMLFrom(virStoragePoolPtr obj,
                        const char *xmldesc,
                        virStorageVolPtr vobj,
                        unsigned int flags)
E
Eric Blake 已提交
1740
{
1741 1742 1743 1744 1745
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool, origpool = NULL;
    virStorageBackendPtr backend;
    virStorageVolDefPtr origvol = NULL, newvol = NULL;
    virStorageVolPtr ret = NULL, volobj = NULL;
O
Osier Yang 已提交
1746
    unsigned long long allocation;
1747
    int buildret;
1748

1749
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
E
Eric Blake 已提交
1750

1751 1752
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1753
    if (pool && STRNEQ(obj->name, vobj->pool)) {
1754
        virStoragePoolObjUnlock(pool);
1755
        origpool = virStoragePoolObjFindByName(&driver->pools, vobj->pool);
1756
        virStoragePoolObjLock(pool);
1757
    }
1758 1759
    storageDriverUnlock(driver);
    if (!pool) {
1760 1761
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(obj->uuid, uuidstr);
1762
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1763 1764
                       _("no storage pool with matching uuid '%s' (%s)"),
                       uuidstr, obj->name);
1765 1766 1767
        goto cleanup;
    }

1768
    if (STRNEQ(obj->name, vobj->pool) && !origpool) {
1769 1770 1771
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       vobj->pool);
1772 1773 1774 1775
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1776
        virReportError(VIR_ERR_OPERATION_INVALID,
1777
                       _("storage pool '%s' is not active"), pool->def->name);
1778 1779 1780
        goto cleanup;
    }

1781
    if (origpool && !virStoragePoolObjIsActive(origpool)) {
1782
        virReportError(VIR_ERR_OPERATION_INVALID,
1783 1784
                       _("storage pool '%s' is not active"),
                       origpool->def->name);
1785 1786 1787 1788 1789 1790
        goto cleanup;
    }

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

1791
    origvol = virStorageVolDefFindByName(origpool ? origpool : pool, vobj->name);
1792
    if (!origvol) {
1793 1794 1795
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vobj->name);
1796 1797 1798
        goto cleanup;
    }

1799
    newvol = virStorageVolDefParseString(pool->def, xmldesc);
1800 1801 1802
    if (newvol == NULL)
        goto cleanup;

1803 1804 1805
    if (virStorageVolCreateXMLFromEnsureACL(obj->conn, pool->def, newvol) < 0)
        goto cleanup;

1806
    if (virStorageVolDefFindByName(pool, newvol->name)) {
1807 1808 1809
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("storage volume name '%s' already in use."),
                       newvol->name);
1810 1811 1812 1813
        goto cleanup;
    }

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

1817 1818
    /* Make sure allocation is at least as large as the destination cap,
     * to make absolutely sure we copy all possible contents */
1819 1820
    if (newvol->target.allocation < origvol->target.capacity)
        newvol->target.allocation = origvol->target.capacity;
1821

1822
    if (!backend->buildVolFrom) {
1823 1824
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("storage pool does not support volume creation from an existing volume"));
1825 1826 1827 1828
        goto cleanup;
    }

    if (origvol->building) {
1829 1830 1831
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       origvol->name);
1832 1833 1834 1835 1836 1837 1838 1839
        goto cleanup;
    }

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

    if (VIR_REALLOC_N(pool->volumes.objs,
1840
                      pool->volumes.count+1) < 0)
1841 1842
        goto cleanup;

1843 1844 1845 1846
    /* 'Define' the new volume so we get async progress reporting.
     * Wipe any key the user may have suggested, as volume creation
     * will generate the canonical key.  */
    VIR_FREE(newvol->key);
1847 1848 1849 1850 1851 1852
    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,
1853
                              newvol->key, NULL, NULL);
1854 1855 1856 1857
    if (!volobj) {
        pool->volumes.count--;
        goto cleanup;
    }
1858 1859 1860 1861

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

1865
    if (origpool) {
1866 1867 1868 1869
        origpool->asyncjobs++;
        virStoragePoolObjUnlock(origpool);
    }

1870
    buildret = backend->buildVolFrom(obj->conn, pool, newvol, origvol, flags);
1871 1872 1873

    storageDriverLock(driver);
    virStoragePoolObjLock(pool);
1874
    if (origpool)
1875 1876 1877
        virStoragePoolObjLock(origpool);
    storageDriverUnlock(driver);

1878
    origvol->in_use--;
1879
    newvol->building = 0;
1880
    allocation = newvol->target.allocation;
1881 1882
    pool->asyncjobs--;

1883
    if (origpool) {
1884 1885 1886 1887 1888 1889
        origpool->asyncjobs--;
        virStoragePoolObjUnlock(origpool);
        origpool = NULL;
    }

    if (buildret < 0) {
1890 1891
        storageVolDeleteInternal(volobj, backend, pool, newvol, 0, false);
        newvol = NULL;
1892 1893
        goto cleanup;
    }
1894
    newvol = NULL;
1895

1896
    /* Updating pool metadata */
O
Osier Yang 已提交
1897 1898
    pool->def->allocation += allocation;
    pool->def->available -= allocation;
1899

1900
    VIR_INFO("Creating volume '%s' in storage pool '%s'",
1901
             volobj->name, pool->def->name);
1902 1903 1904
    ret = volobj;
    volobj = NULL;

1905
 cleanup:
1906
    virObjectUnref(volobj);
1907 1908 1909
    virStorageVolDefFree(newvol);
    if (pool)
        virStoragePoolObjUnlock(pool);
1910
    if (origpool)
1911 1912 1913 1914
        virStoragePoolObjUnlock(origpool);
    return ret;
}

1915

1916
static int
1917 1918 1919 1920 1921
storageVolDownload(virStorageVolPtr obj,
                   virStreamPtr stream,
                   unsigned long long offset,
                   unsigned long long length,
                   unsigned int flags)
1922 1923 1924 1925 1926 1927 1928
{
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

1929 1930
    if (!(vol = virStorageVolDefFromVol(obj, &pool, NULL)))
        return -1;
1931

1932
    if (virStorageVolDownloadEnsureACL(obj->conn, pool->def, vol) < 0)
1933
        goto cleanup;
1934

1935
    if (vol->building) {
1936 1937 1938
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1939
        goto cleanup;
1940 1941 1942 1943 1944
    }

    if (virFDStreamOpenFile(stream,
                            vol->target.path,
                            offset, length,
E
Eric Blake 已提交
1945
                            O_RDONLY) < 0)
1946
        goto cleanup;
1947 1948 1949

    ret = 0;

1950
 cleanup:
1951
    virStoragePoolObjUnlock(pool);
1952 1953 1954 1955 1956 1957

    return ret;
}


static int
1958 1959 1960 1961 1962
storageVolUpload(virStorageVolPtr obj,
                 virStreamPtr stream,
                 unsigned long long offset,
                 unsigned long long length,
                 unsigned int flags)
1963 1964 1965 1966 1967 1968 1969
{
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

1970 1971
    if (!(vol = virStorageVolDefFromVol(obj, &pool, NULL)))
        return -1;
1972

1973
    if (virStorageVolUploadEnsureACL(obj->conn, pool->def, vol) < 0)
1974
        goto cleanup;
1975

1976 1977 1978 1979 1980 1981 1982
    if (vol->in_use) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still in use."),
                       vol->name);
        goto cleanup;
    }

1983
    if (vol->building) {
1984 1985 1986
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1987
        goto cleanup;
1988 1989
    }

1990
    switch ((virStoragePoolType) pool->def->type) {
1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
    case VIR_STORAGE_POOL_DIR:
    case VIR_STORAGE_POOL_FS:
    case VIR_STORAGE_POOL_NETFS:
    case VIR_STORAGE_POOL_LOGICAL:
    case VIR_STORAGE_POOL_DISK:
    case VIR_STORAGE_POOL_ISCSI:
    case VIR_STORAGE_POOL_SCSI:
    case VIR_STORAGE_POOL_MPATH:
        /* Not using O_CREAT because the file is required to already exist at
         * this point */
        if (virFDStreamOpenFile(stream, vol->target.path,
                                offset, length, O_WRONLY) < 0)
            goto cleanup;

        break;

    case VIR_STORAGE_POOL_SHEEPDOG:
    case VIR_STORAGE_POOL_RBD:
    case VIR_STORAGE_POOL_GLUSTER:
    case VIR_STORAGE_POOL_LAST:
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                       _("volume upload is not supported with pools of type %s"),
                       virStoragePoolTypeToString(pool->def->type));
2014
        goto cleanup;
2015
    }
2016 2017 2018

    ret = 0;

2019
 cleanup:
2020
    virStoragePoolObjUnlock(pool);
2021 2022 2023 2024

    return ret;
}

2025
static int
2026 2027 2028
storageVolResize(virStorageVolPtr obj,
                 unsigned long long capacity,
                 unsigned int flags)
2029 2030 2031 2032 2033 2034 2035
{
    virStorageBackendPtr backend;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    unsigned long long abs_capacity;
    int ret = -1;

2036
    virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE |
2037 2038
                  VIR_STORAGE_VOL_RESIZE_DELTA |
                  VIR_STORAGE_VOL_RESIZE_SHRINK, -1);
2039

2040 2041
    if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
        return -1;
2042

2043
    if (virStorageVolResizeEnsureACL(obj->conn, pool->def, vol) < 0)
2044
        goto cleanup;
2045

2046 2047 2048 2049 2050 2051 2052
    if (vol->in_use) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still in use."),
                       vol->name);
        goto cleanup;
    }

2053
    if (vol->building) {
2054 2055 2056
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
2057
        goto cleanup;
2058
    }
2059

2060
    if (flags & VIR_STORAGE_VOL_RESIZE_DELTA) {
2061
        abs_capacity = vol->target.capacity + capacity;
2062 2063 2064 2065 2066
        flags &= ~VIR_STORAGE_VOL_RESIZE_DELTA;
    } else {
        abs_capacity = capacity;
    }

2067
    if (abs_capacity < vol->target.allocation) {
2068
        virReportError(VIR_ERR_INVALID_ARG, "%s",
2069 2070
                       _("can't shrink capacity below "
                         "existing allocation"));
2071
        goto cleanup;
2072 2073
    }

2074
    if (abs_capacity < vol->target.capacity &&
2075 2076 2077 2078
        !(flags & VIR_STORAGE_VOL_RESIZE_SHRINK)) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("Can't shrink capacity below current "
                         "capacity with shrink flag explicitly specified"));
2079
        goto cleanup;
2080 2081
    }

2082
    if (abs_capacity > vol->target.capacity + pool->def->available) {
2083
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
2084
                       _("Not enough space left on storage pool"));
2085
        goto cleanup;
2086 2087 2088
    }

    if (!backend->resizeVol) {
2089
        virReportError(VIR_ERR_NO_SUPPORT, "%s",
2090 2091
                       _("storage pool does not support changing of "
                         "volume capacity"));
2092
        goto cleanup;
2093 2094 2095
    }

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

2098
    vol->target.capacity = abs_capacity;
2099
    if (flags & VIR_STORAGE_VOL_RESIZE_ALLOCATE)
2100
        vol->target.allocation = abs_capacity;
2101 2102

    /* Update pool metadata */
2103 2104
    pool->def->allocation += (abs_capacity - vol->target.capacity);
    pool->def->available -= (abs_capacity - vol->target.capacity);
2105

O
Osier Yang 已提交
2106
    ret = 0;
2107

2108
 cleanup:
2109
    virStoragePoolObjUnlock(pool);
2110 2111 2112

    return ret;
}
2113

2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128
/* 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
2129 2130 2131
storageVolZeroSparseFile(virStorageVolDefPtr vol,
                         off_t size,
                         int fd)
2132 2133 2134 2135 2136 2137 2138 2139 2140
{
    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);
2141
        return ret;
2142 2143 2144 2145 2146 2147
    }

    ret = ftruncate(fd, size);
    if (ret == -1) {
        virReportSystemError(errno,
                             _("Failed to truncate volume with "
2148
                               "path '%s' to %ju bytes"),
E
Eric Blake 已提交
2149
                             vol->target.path, (uintmax_t)size);
2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169
    }

    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 已提交
2170
              (uintmax_t)extent_start, (uintmax_t)extent_length);
2171 2172 2173 2174 2175

    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 已提交
2176
                             (uintmax_t)extent_start, vol->target.path);
2177
        goto cleanup;
2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190
    }

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

2191
            goto cleanup;
2192 2193 2194 2195 2196 2197
        }

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

2198 2199 2200 2201 2202
    if (fdatasync(fd) < 0) {
        ret = -errno;
        virReportSystemError(errno,
                             _("cannot sync data to volume with path '%s'"),
                             vol->target.path);
2203
        goto cleanup;
2204 2205
    }

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

    ret = 0;

2211
 cleanup:
2212 2213 2214 2215 2216
    return ret;
}


static int
2217 2218
storageVolWipeInternal(virStorageVolDefPtr def,
                       unsigned int algorithm)
2219 2220 2221 2222 2223
{
    int ret = -1, fd = -1;
    struct stat st;
    char *writebuf = NULL;
    size_t bytes_wiped = 0;
2224
    virCommandPtr cmd = NULL;
2225

2226 2227
    VIR_DEBUG("Wiping volume with path '%s' and algorithm %u",
              def->target.path, algorithm);
2228 2229 2230 2231 2232 2233

    fd = open(def->target.path, O_RDWR);
    if (fd == -1) {
        virReportSystemError(errno,
                             _("Failed to open storage volume with path '%s'"),
                             def->target.path);
2234
        goto cleanup;
2235 2236 2237 2238 2239 2240
    }

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

2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259
    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 已提交
2260
            alg_char = "schneier";
2261 2262 2263 2264 2265
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7:
            alg_char = "pfitzner7";
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33:
M
Michal Privoznik 已提交
2266
            alg_char = "pfitzner33";
2267 2268 2269 2270 2271
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_RANDOM:
            alg_char = "random";
            break;
        default:
2272 2273 2274
            virReportError(VIR_ERR_INVALID_ARG,
                           _("unsupported algorithm %d"),
                           algorithm);
2275 2276 2277 2278
        }
        cmd = virCommandNew(SCRUB);
        virCommandAddArgList(cmd, "-f", "-p", alg_char,
                             def->target.path, NULL);
2279

2280
        if (virCommandRun(cmd, NULL) < 0)
2281
            goto cleanup;
2282

2283
        ret = 0;
2284
        goto cleanup;
2285 2286
    } else {
        if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) {
2287
            ret = storageVolZeroSparseFile(def, st.st_size, fd);
2288 2289
        } else {

2290
            if (VIR_ALLOC_N(writebuf, st.st_blksize) < 0)
2291
                goto cleanup;
2292 2293 2294 2295

            ret = storageWipeExtent(def,
                                    fd,
                                    0,
2296
                                    def->target.allocation,
2297 2298 2299 2300
                                    writebuf,
                                    st.st_blksize,
                                    &bytes_wiped);
        }
2301 2302
    }

2303
 cleanup:
2304
    virCommandFree(cmd);
2305
    VIR_FREE(writebuf);
2306
    VIR_FORCE_CLOSE(fd);
2307 2308 2309 2310 2311
    return ret;
}


static int
2312 2313 2314
storageVolWipePattern(virStorageVolPtr obj,
                      unsigned int algorithm,
                      unsigned int flags)
2315 2316 2317 2318 2319
{
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    int ret = -1;

2320
    virCheckFlags(0, -1);
2321

2322
    if (algorithm >= VIR_STORAGE_VOL_WIPE_ALG_LAST) {
2323 2324 2325
        virReportError(VIR_ERR_INVALID_ARG,
                       _("wiping algorithm %d not supported"),
                       algorithm);
2326 2327 2328
        return -1;
    }

2329 2330
    if (!(vol = virStorageVolDefFromVol(obj, &pool, NULL)))
        return -1;
2331 2332


2333
    if (virStorageVolWipePatternEnsureACL(obj->conn, pool->def, vol) < 0)
2334
        goto cleanup;
2335

2336 2337 2338 2339 2340 2341 2342
    if (vol->in_use) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still in use."),
                       vol->name);
        goto cleanup;
    }

2343
    if (vol->building) {
2344 2345 2346
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
2347
        goto cleanup;
2348 2349
    }

2350
    if (storageVolWipeInternal(vol, algorithm) == -1) {
2351
        goto cleanup;
2352 2353 2354 2355
    }

    ret = 0;

2356
 cleanup:
2357
    virStoragePoolObjUnlock(pool);
2358 2359 2360 2361

    return ret;
}

2362
static int
2363 2364
storageVolWipe(virStorageVolPtr obj,
               unsigned int flags)
2365
{
2366
    return storageVolWipePattern(obj, VIR_STORAGE_VOL_WIPE_ALG_ZERO, flags);
2367 2368
}

2369 2370

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

2379 2380
    if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
        return -1;
2381

2382 2383 2384
    if (virStorageVolGetInfoEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2385 2386
    if (backend->refreshVol &&
        backend->refreshVol(obj->conn, pool, vol) < 0)
2387
        goto cleanup;
2388 2389

    memset(info, 0, sizeof(*info));
2390
    info->type = vol->type;
2391 2392
    info->capacity = vol->target.capacity;
    info->allocation = vol->target.allocation;
2393
    ret = 0;
2394

2395
 cleanup:
2396
    virStoragePoolObjUnlock(pool);
2397
    return ret;
2398 2399 2400
}

static char *
2401 2402
storageVolGetXMLDesc(virStorageVolPtr obj,
                     unsigned int flags)
E
Eric Blake 已提交
2403
{
2404
    virStoragePoolObjPtr pool;
2405 2406
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
2407
    char *ret = NULL;
2408

E
Eric Blake 已提交
2409 2410
    virCheckFlags(0, NULL);

2411 2412
    if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend)))
        return NULL;
2413

2414 2415 2416
    if (virStorageVolGetXMLDescEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2417 2418 2419
    if (backend->refreshVol &&
        backend->refreshVol(obj->conn, pool, vol) < 0)
        goto cleanup;
2420

2421
    ret = virStorageVolDefFormat(pool->def, vol);
2422

2423
 cleanup:
2424
    virStoragePoolObjUnlock(pool);
2425

2426
    return ret;
2427 2428 2429
}

static char *
2430 2431
storageVolGetPath(virStorageVolPtr obj)
{
2432
    virStoragePoolObjPtr pool;
2433
    virStorageVolDefPtr vol;
2434
    char *ret = NULL;
2435

2436 2437
    if (!(vol = virStorageVolDefFromVol(obj, &pool, NULL)))
        return NULL;
2438

2439 2440 2441
    if (virStorageVolGetPathEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2442
    ignore_value(VIR_STRDUP(ret, vol->target.path));
2443

2444
 cleanup:
2445
    virStoragePoolObjUnlock(pool);
2446 2447 2448
    return ret;
}

2449
static int
2450 2451 2452
storageConnectListAllStoragePools(virConnectPtr conn,
                                  virStoragePoolPtr **pools,
                                  unsigned int flags)
2453 2454 2455 2456 2457 2458
{
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

2459 2460 2461
    if (virConnectListAllStoragePoolsEnsureACL(conn) < 0)
        goto cleanup;

2462
    storageDriverLock(driver);
2463 2464
    ret = virStoragePoolObjListExport(conn, driver->pools, pools,
                                      virConnectListAllStoragePoolsCheckACL, flags);
2465 2466
    storageDriverUnlock(driver);

2467
 cleanup:
2468 2469 2470
    return ret;
}

2471

2472
static virStorageDriver storageDriver = {
2473
    .name = "storage",
2474 2475
    .storageOpen = storageOpen, /* 0.4.0 */
    .storageClose = storageClose, /* 0.4.0 */
2476 2477 2478 2479 2480 2481
    .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 */
2482 2483 2484
    .storagePoolLookupByName = storagePoolLookupByName, /* 0.4.0 */
    .storagePoolLookupByUUID = storagePoolLookupByUUID, /* 0.4.0 */
    .storagePoolLookupByVolume = storagePoolLookupByVolume, /* 0.4.0 */
2485 2486
    .storagePoolCreateXML = storagePoolCreateXML, /* 0.4.0 */
    .storagePoolDefineXML = storagePoolDefineXML, /* 0.4.0 */
2487 2488
    .storagePoolBuild = storagePoolBuild, /* 0.4.0 */
    .storagePoolUndefine = storagePoolUndefine, /* 0.4.0 */
2489
    .storagePoolCreate = storagePoolCreate, /* 0.4.0 */
2490 2491 2492 2493 2494 2495 2496
    .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 */
2497
    .storagePoolNumOfVolumes = storagePoolNumOfVolumes, /* 0.4.0 */
2498 2499 2500
    .storagePoolListVolumes = storagePoolListVolumes, /* 0.4.0 */
    .storagePoolListAllVolumes = storagePoolListAllVolumes, /* 0.10.2 */

2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514
    .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 */
2515 2516 2517

    .storagePoolIsActive = storagePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = storagePoolIsPersistent, /* 0.7.3 */
2518 2519 2520 2521
};


static virStateDriver stateDriver = {
2522
    .name = "Storage",
2523
    .stateInitialize = storageStateInitialize,
2524
    .stateAutoStart = storageStateAutoStart,
2525 2526
    .stateCleanup = storageStateCleanup,
    .stateReload = storageStateReload,
2527 2528
};

2529 2530 2531 2532
int storageRegister(void)
{
    if (virRegisterStorageDriver(&storageDriver) < 0)
        return -1;
2533 2534
    if (virRegisterStateDriver(&stateDriver) < 0)
        return -1;
2535 2536
    return 0;
}
2537 2538 2539


/* ----------- file handlers cooperating with storage driver --------------- */
2540 2541 2542 2543 2544 2545
static bool
virStorageFileIsInitialized(virStorageSourcePtr src)
{
    return !!src->drv;
}

2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569

static bool
virStorageFileSupportsBackingChainTraversal(virStorageSourcePtr src)
{
    int actualType = virStorageSourceGetActualType(src);
    virStorageFileBackendPtr backend;

    if (!src)
        return false;

    if (src->drv) {
        backend = src->drv->backend;
    } else {
        if (!(backend = virStorageFileBackendForTypeInternal(actualType,
                                                             src->protocol,
                                                             false)))
            return false;
    }

    return backend->storageFileGetUniqueIdentifier &&
           backend->storageFileReadHeader &&
           backend->storageFileAccess;
}

2570
void
2571
virStorageFileDeinit(virStorageSourcePtr src)
2572
{
2573
    if (!virStorageFileIsInitialized(src))
2574 2575
        return;

2576 2577 2578
    if (src->drv->backend &&
        src->drv->backend->backendDeinit)
        src->drv->backend->backendDeinit(src);
2579

2580
    VIR_FREE(src->drv);
2581 2582 2583
}


2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596
/**
 * virStorageFileInitAs:
 *
 * @src: storage source definition
 * @uid: uid used to access the file, or -1 for current uid
 * @gid: gid used to access the file, or -1 for current gid
 *
 * Initialize a storage source to be used with storage driver. Use the provided
 * uid and gid if possible for the operations.
 *
 * Returns 0 if the storage file was successfully initialized, -1 if the
 * initialization failed. Libvirt error is reported.
 */
2597
int
2598 2599
virStorageFileInitAs(virStorageSourcePtr src,
                     uid_t uid, gid_t gid)
2600
{
2601 2602 2603
    int actualType = virStorageSourceGetActualType(src);
    if (VIR_ALLOC(src->drv) < 0)
        return -1;
2604

2605 2606 2607 2608 2609 2610 2611 2612 2613 2614
    if (uid == (uid_t) -1)
        src->drv->uid = geteuid();
    else
        src->drv->uid = uid;

    if (gid == (gid_t) -1)
        src->drv->gid = getegid();
    else
        src->drv->gid = gid;

2615 2616
    if (!(src->drv->backend = virStorageFileBackendForType(actualType,
                                                           src->protocol)))
2617 2618
        goto error;

2619 2620
    if (src->drv->backend->backendInit &&
        src->drv->backend->backendInit(src) < 0)
2621 2622
        goto error;

2623
    return 0;
2624

2625
 error:
2626 2627
    VIR_FREE(src->drv);
    return -1;
2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640
}


/**
 * virStorageFileInit:
 *
 * See virStorageFileInitAs. The file is initialized to be accessed by the
 * current user.
 */
int
virStorageFileInit(virStorageSourcePtr src)
{
    return virStorageFileInitAs(src, -1, -1);
2641 2642 2643 2644 2645 2646
}


/**
 * virStorageFileCreate: Creates an empty storage file via storage driver
 *
2647
 * @src: file structure pointing to the file
2648 2649 2650 2651 2652
 *
 * Returns 0 on success, -2 if the function isn't supported by the backend,
 * -1 on other failure. Errno is set in case of failure.
 */
int
2653
virStorageFileCreate(virStorageSourcePtr src)
2654
{
2655 2656
    int ret;

2657 2658
    if (!virStorageFileIsInitialized(src) ||
        !src->drv->backend->storageFileCreate) {
2659 2660 2661 2662
        errno = ENOSYS;
        return -2;
    }

2663 2664 2665 2666 2667 2668
    ret = src->drv->backend->storageFileCreate(src);

    VIR_DEBUG("created storage file %p: ret=%d, errno=%d",
              src, ret, errno);

    return ret;
2669 2670 2671 2672 2673 2674
}


/**
 * virStorageFileUnlink: Unlink storage file via storage driver
 *
2675
 * @src: file structure pointing to the file
2676 2677 2678 2679 2680 2681 2682
 *
 * Unlinks the file described by the @file structure.
 *
 * Returns 0 on success, -2 if the function isn't supported by the backend,
 * -1 on other failure. Errno is set in case of failure.
 */
int
2683
virStorageFileUnlink(virStorageSourcePtr src)
2684
{
2685 2686
    int ret;

2687 2688
    if (!virStorageFileIsInitialized(src) ||
        !src->drv->backend->storageFileUnlink) {
2689 2690 2691 2692
        errno = ENOSYS;
        return -2;
    }

2693 2694 2695 2696 2697 2698
    ret = src->drv->backend->storageFileUnlink(src);

    VIR_DEBUG("unlinked storage file %p: ret=%d, errno=%d",
              src, ret, errno);

    return ret;
2699 2700 2701 2702 2703 2704
}


/**
 * virStorageFileStat: returns stat struct of a file via storage driver
 *
2705
 * @src: file structure pointing to the file
2706 2707 2708 2709 2710 2711
 * @stat: stat structure to return data
 *
 * Returns 0 on success, -2 if the function isn't supported by the backend,
 * -1 on other failure. Errno is set in case of failure.
*/
int
2712
virStorageFileStat(virStorageSourcePtr src,
2713 2714
                   struct stat *st)
{
2715 2716
    int ret;

2717 2718
    if (!virStorageFileIsInitialized(src) ||
        !src->drv->backend->storageFileStat) {
2719 2720 2721 2722
        errno = ENOSYS;
        return -2;
    }

2723 2724 2725 2726 2727 2728
    ret = src->drv->backend->storageFileStat(src, st);

    VIR_DEBUG("stat of storage file %p: ret=%d, errno=%d",
              src, ret, errno);

    return ret;
2729
}
2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757


/**
 * virStorageFileReadHeader: read the beginning bytes of a file into a buffer
 *
 * @src: file structure pointing to the file
 * @max_len: maximum number of bytes read from the storage file
 * @buf: buffer to read the data into. buffer shall be freed by caller)
 *
 * Returns the count of bytes read on success and -1 on failure, -2 if the
 * function isn't supported by the backend. Libvirt error is reported on failure.
 */
ssize_t
virStorageFileReadHeader(virStorageSourcePtr src,
                         ssize_t max_len,
                         char **buf)
{
    ssize_t ret;

    if (!virStorageFileIsInitialized(src)) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("storage file backend not initialized"));
        return -1;
    }

    if (!src->drv->backend->storageFileReadHeader) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("storage file header reading is not supported for "
2758
                         "storage type %s (protocol: %s)"),
2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769
                       virStorageTypeToString(src->type),
                       virStorageNetProtocolTypeToString(src->protocol));
        return -2;
    }

    ret = src->drv->backend->storageFileReadHeader(src, max_len, buf);

    VIR_DEBUG("read of storage header %p: ret=%zd", src, ret);

    return ret;
}
2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799


/*
 * virStorageFileGetUniqueIdentifier: Get a unique string describing the volume
 *
 * @src: file structure pointing to the file
 *
 * Returns a string uniquely describing a single volume (canonical path).
 * The string shall not be freed and is valid until the storage file is
 * deinitialized. Returns NULL on error and sets a libvirt error code */
const char *
virStorageFileGetUniqueIdentifier(virStorageSourcePtr src)
{
    if (!virStorageFileIsInitialized(src)) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("storage file backend not initialized"));
        return NULL;
    }

    if (!src->drv->backend->storageFileGetUniqueIdentifier) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unique storage file identifier not implemented for "
                          "storage type %s (protocol: %s)'"),
                       virStorageTypeToString(src->type),
                       virStorageNetProtocolTypeToString(src->protocol));
        return NULL;
    }

    return src->drv->backend->storageFileGetUniqueIdentifier(src);
}
2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823


/**
 * virStorageFileAccess: Check accessibility of a storage file
 *
 * @src: storage file to check access permissions
 * @mode: accessibility check options (see man 2 access)
 *
 * Returns 0 on success, -1 on error and sets errno. No libvirt
 * error is reported. Returns -2 if the operation isn't supported
 * by libvirt storage backend.
 */
int
virStorageFileAccess(virStorageSourcePtr src,
                     int mode)
{
    if (!virStorageFileIsInitialized(src) ||
        !src->drv->backend->storageFileAccess) {
        errno = ENOSYS;
        return -2;
    }

    return src->drv->backend->storageFileAccess(src, mode);
}
2824 2825 2826 2827 2828 2829 2830 2831 2832 2833


/* Recursive workhorse for virStorageFileGetMetadata.  */
static int
virStorageFileGetMetadataRecurse(virStorageSourcePtr src,
                                 uid_t uid, gid_t gid,
                                 bool allow_probe,
                                 virHashTablePtr cycle)
{
    int ret = -1;
2834
    const char *uniqueName;
2835 2836
    char *buf = NULL;
    ssize_t headerLen;
2837 2838 2839
    virStorageSourcePtr backingStore = NULL;
    int backingFormat;

2840 2841
    VIR_DEBUG("path=%s dir=%s format=%d uid=%d gid=%d probe=%d",
              src->path, NULLSTR(src->relDir), src->format,
2842 2843
              (int)uid, (int)gid, allow_probe);

2844 2845 2846 2847 2848
    /* exit if we can't load information about the current image */
    if (!virStorageFileSupportsBackingChainTraversal(src))
        return 0;

    if (virStorageFileInitAs(src, uid, gid) < 0)
2849
        return -1;
2850

2851 2852 2853 2854 2855 2856 2857
    if (virStorageFileAccess(src, F_OK) < 0) {
        virReportSystemError(errno,
                             _("Cannot access backing file %s"),
                             src->path);
        goto cleanup;
    }

2858 2859 2860 2861 2862 2863 2864 2865
    if (!(uniqueName = virStorageFileGetUniqueIdentifier(src)))
        goto cleanup;

    if (virHashLookup(cycle, uniqueName)) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("backing store for %s (%s) is self-referential"),
                       src->path, uniqueName);
        goto cleanup;
2866 2867
    }

2868 2869
    if (virHashAddEntry(cycle, uniqueName, (void *)1) < 0)
        goto cleanup;
2870

2871 2872 2873
    if ((headerLen = virStorageFileReadHeader(src, VIR_STORAGE_MAX_HEADER,
                                              &buf)) < 0)
        goto cleanup;
2874

2875 2876
    if (virStorageFileGetMetadataInternal(src, buf, headerLen,
                                          &backingFormat) < 0)
2877
        goto cleanup;
2878 2879

    /* check whether we need to go deeper */
2880 2881 2882 2883
    if (!src->backingStoreRaw) {
        ret = 0;
        goto cleanup;
    }
2884

2885
    if (!(backingStore = virStorageSourceNewFromBacking(src)))
2886
        goto cleanup;
2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908

    if (backingFormat == VIR_STORAGE_FILE_AUTO && !allow_probe)
        backingStore->format = VIR_STORAGE_FILE_RAW;
    else if (backingFormat == VIR_STORAGE_FILE_AUTO_SAFE)
        backingStore->format = VIR_STORAGE_FILE_AUTO;
    else
        backingStore->format = backingFormat;

    if (virStorageFileGetMetadataRecurse(backingStore,
                                         uid, gid, allow_probe,
                                         cycle) < 0) {
        /* if we fail somewhere midway, just accept and return a
         * broken chain */
        ret = 0;
        goto cleanup;
    }

    src->backingStore = backingStore;
    backingStore = NULL;
    ret = 0;

 cleanup:
2909
    VIR_FREE(buf);
2910
    virStorageFileDeinit(src);
2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947
    virStorageSourceFree(backingStore);
    return ret;
}


/**
 * virStorageFileGetMetadata:
 *
 * Extract metadata about the storage volume with the specified
 * image format. If image format is VIR_STORAGE_FILE_AUTO, it
 * will probe to automatically identify the format.  Recurses through
 * the entire chain.
 *
 * Open files using UID and GID (or pass -1 for the current user/group).
 * Treat any backing files without explicit type as raw, unless ALLOW_PROBE.
 *
 * Callers are advised never to use VIR_STORAGE_FILE_AUTO as a
 * format, since a malicious guest can turn a raw file into any
 * other non-raw format at will.
 *
 * Caller MUST free result after use via virStorageSourceFree.
 */
int
virStorageFileGetMetadata(virStorageSourcePtr src,
                          uid_t uid, gid_t gid,
                          bool allow_probe)
{
    VIR_DEBUG("path=%s format=%d uid=%d gid=%d probe=%d",
              src->path, src->format, (int)uid, (int)gid, allow_probe);

    virHashTablePtr cycle = NULL;
    char *canonPath = NULL;
    int ret = -1;

    if (!(cycle = virHashCreate(5, NULL)))
        return -1;

2948 2949 2950
    if (!src->relPath &&
        VIR_STRDUP(src->relPath, src->path) < 0)
        goto cleanup;
2951

2952 2953 2954
    if (!src->relDir &&
        !(src->relDir = mdir_name(src->path))) {
        virReportOOMError();
2955 2956 2957 2958 2959 2960
        goto cleanup;
    }

    if (src->format <= VIR_STORAGE_FILE_NONE)
        src->format = allow_probe ? VIR_STORAGE_FILE_AUTO : VIR_STORAGE_FILE_RAW;

2961
    ret = virStorageFileGetMetadataRecurse(src, uid, gid,
2962 2963 2964 2965 2966 2967 2968
                                           allow_probe, cycle);

 cleanup:
    VIR_FREE(canonPath);
    virHashFree(cycle);
    return ret;
}