storage_driver.c 75.6 KB
Newer Older
1 2 3
/*
 * storage_driver.c: core driver for storage APIs
 *
4
 * Copyright (C) 2006-2013 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17
 * Copyright (C) 2006-2008 Daniel P. Berrange
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library.  If not, see
O
Osier Yang 已提交
19
 * <http://www.gnu.org/licenses/>.
20 21 22 23 24 25 26 27 28
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 */

#include <config.h>

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
29 30 31 32
#include <sys/stat.h>
#include <sys/param.h>
#include <fcntl.h>

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

39
#include "virerror.h"
40
#include "datatypes.h"
41 42 43
#include "driver.h"
#include "storage_driver.h"
#include "storage_conf.h"
44
#include "viralloc.h"
45
#include "storage_backend.h"
46
#include "virlog.h"
E
Eric Blake 已提交
47
#include "virfile.h"
48
#include "fdstream.h"
49
#include "configmake.h"
50
#include "virstring.h"
51
#include "viraccessapicheck.h"
52

53 54
#define VIR_FROM_THIS VIR_FROM_STORAGE

55 56
static virStorageDriverStatePtr driverState;

57
static int storageStateCleanup(void);
58

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

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

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

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

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

92
        if (backend->checkPool &&
93
            backend->checkPool(conn, pool, &started) < 0) {
94 95 96 97 98 99 100 101 102 103 104
            virErrorPtr err = virGetLastError();
            VIR_ERROR(_("Failed to initialize storage pool '%s': %s"),
                      pool->def->name, err ? err->message :
                      _("no error message found"));
            virStoragePoolObjUnlock(pool);
            continue;
        }

        if (!started &&
            pool->autostart &&
            !virStoragePoolObjIsActive(pool)) {
105
            if (backend->startPool &&
106
                backend->startPool(conn, pool) < 0) {
107
                virErrorPtr err = virGetLastError();
108
                VIR_ERROR(_("Failed to autostart storage pool '%s': %s"),
109
                          pool->def->name, err ? err->message :
110
                          _("no error message found"));
111
                virStoragePoolObjUnlock(pool);
112 113
                continue;
            }
114 115
            started = true;
        }
116

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

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

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

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

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

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

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

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

179
    VIR_FREE(base);
180

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

186
    storageDriverUnlock(driverState);
187 188
    return 0;

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

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

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

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

223
    storageDriverLock(driverState);
224
    virStoragePoolLoadAllConfigs(&driverState->pools,
225 226
                                 driverState->configDir,
                                 driverState->autostartDir);
227
    storageDriverAutostart(driverState);
228
    storageDriverUnlock(driverState);
229 230 231 232 233 234

    return 0;
}


/**
235
 * storageStateCleanup
236 237 238 239
 *
 * Shutdown the storage driver, it will stop all active storage pools
 */
static int
240
storageStateCleanup(void) {
241 242 243
    if (!driverState)
        return -1;

244
    storageDriverLock(driverState);
245 246

    /* free inactive pools */
247 248 249 250
    virStoragePoolObjListFree(&driverState->pools);

    VIR_FREE(driverState->configDir);
    VIR_FREE(driverState->autostartDir);
251
    storageDriverUnlock(driverState);
252
    virMutexDestroy(&driverState->lock);
253
    VIR_FREE(driverState);
254 255 256 257 258 259 260 261 262

    return 0;
}



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

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

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

277 278 279
    if (virStoragePoolLookupByUUIDEnsureACL(conn, pool->def) < 0)
        goto cleanup;

280 281
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
282 283

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

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

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

300
    if (!pool) {
301
        virReportError(VIR_ERR_NO_STORAGE_POOL,
302
                       _("no storage pool with matching name '%s'"), name);
303
        goto cleanup;
304 305
    }

306 307 308
    if (virStoragePoolLookupByNameEnsureACL(conn, pool->def) < 0)
        goto cleanup;

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

cleanup:
313 314
    if (pool)
        virStoragePoolObjUnlock(pool);
315 316 317 318 319
    return ret;
}

static virStoragePoolPtr
storagePoolLookupByVolume(virStorageVolPtr vol) {
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
    virStorageDriverStatePtr driver = vol->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;

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

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

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

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

cleanup:
    if (pool)
        virStoragePoolObjUnlock(pool);
    return ret;
344 345 346 347 348
}

static virDrvOpenStatus
storageOpen(virConnectPtr conn,
            virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
349 350 351 352
            unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

353 354 355 356 357 358 359 360 361 362 363 364 365 366
    if (!driverState)
        return VIR_DRV_OPEN_DECLINED;

    conn->storagePrivateData = driverState;
    return VIR_DRV_OPEN_SUCCESS;
}

static int
storageClose(virConnectPtr conn) {
    conn->storagePrivateData = NULL;
    return 0;
}

static int
367
storageConnectNumOfStoragePools(virConnectPtr conn) {
368
    virStorageDriverStatePtr driver = conn->storagePrivateData;
369 370
    size_t i;
    int nactive = 0;
371

372 373 374
    if (virConnectNumOfStoragePoolsEnsureACL(conn) < 0)
        return -1;

375
    storageDriverLock(driver);
376
    for (i = 0; i < driver->pools.count; i++) {
377 378 379 380
        virStoragePoolObjPtr obj = driver->pools.objs[i];
        virStoragePoolObjLock(obj);
        if (virConnectNumOfStoragePoolsCheckACL(conn, obj->def) &&
            virStoragePoolObjIsActive(obj))
381
            nactive++;
382
        virStoragePoolObjUnlock(obj);
383 384
    }
    storageDriverUnlock(driver);
385 386

    return nactive;
387 388 389
}

static int
390 391 392
storageConnectListStoragePools(virConnectPtr conn,
                               char **const names,
                               int nnames) {
393
    virStorageDriverStatePtr driver = conn->storagePrivateData;
394 395
    int got = 0;
    size_t i;
396

397 398 399
    if (virConnectListStoragePoolsEnsureACL(conn) < 0)
        return -1;

400
    storageDriverLock(driver);
401
    for (i = 0; i < driver->pools.count && got < nnames; i++) {
402 403 404 405 406 407
        virStoragePoolObjPtr obj = driver->pools.objs[i];
        virStoragePoolObjLock(obj);
        if (virConnectListStoragePoolsCheckACL(conn, obj->def) &&
            virStoragePoolObjIsActive(obj)) {
            if (VIR_STRDUP(names[got], obj->def->name) < 0) {
                virStoragePoolObjUnlock(obj);
408 409 410 411
                goto cleanup;
            }
            got++;
        }
412
        virStoragePoolObjUnlock(obj);
413
    }
414
    storageDriverUnlock(driver);
415 416 417
    return got;

 cleanup:
418
    storageDriverUnlock(driver);
419
    for (i = 0; i < got; i++)
420
        VIR_FREE(names[i]);
421
    memset(names, 0, nnames * sizeof(*names));
422 423 424 425
    return -1;
}

static int
426
storageConnectNumOfDefinedStoragePools(virConnectPtr conn) {
427
    virStorageDriverStatePtr driver = conn->storagePrivateData;
428 429
    size_t i;
    int nactive = 0;
430

431 432 433
    if (virConnectNumOfDefinedStoragePoolsEnsureACL(conn) < 0)
        return -1;

434
    storageDriverLock(driver);
435
    for (i = 0; i < driver->pools.count; i++) {
436 437 438 439
        virStoragePoolObjPtr obj = driver->pools.objs[i];
        virStoragePoolObjLock(obj);
        if (virConnectNumOfDefinedStoragePoolsCheckACL(conn, obj->def) &&
            !virStoragePoolObjIsActive(obj))
440
            nactive++;
441
        virStoragePoolObjUnlock(obj);
442 443
    }
    storageDriverUnlock(driver);
444 445

    return nactive;
446 447 448
}

static int
449 450 451
storageConnectListDefinedStoragePools(virConnectPtr conn,
                                      char **const names,
                                      int nnames) {
452
    virStorageDriverStatePtr driver = conn->storagePrivateData;
453 454
    int got = 0;
    size_t i;
455

456 457 458
    if (virConnectListDefinedStoragePoolsEnsureACL(conn) < 0)
        return -1;

459
    storageDriverLock(driver);
460
    for (i = 0; i < driver->pools.count && got < nnames; i++) {
461 462 463 464 465 466
        virStoragePoolObjPtr obj = driver->pools.objs[i];
        virStoragePoolObjLock(obj);
        if (virConnectListDefinedStoragePoolsCheckACL(conn, obj->def) &&
            !virStoragePoolObjIsActive(obj)) {
            if (VIR_STRDUP(names[got], obj->def->name) < 0) {
                virStoragePoolObjUnlock(obj);
467 468 469 470
                goto cleanup;
            }
            got++;
        }
471
        virStoragePoolObjUnlock(obj);
472
    }
473
    storageDriverUnlock(driver);
474 475 476
    return got;

 cleanup:
477
    storageDriverUnlock(driver);
478
    for (i = 0; i < got; i++) {
479
        VIR_FREE(names[i]);
480
    }
481
    memset(names, 0, nnames * sizeof(*names));
482 483 484
    return -1;
}

485 486
/* This method is required to be re-entrant / thread safe, so
   uses no driver lock */
487
static char *
488 489 490 491
storageConnectFindStoragePoolSources(virConnectPtr conn,
                                     const char *type,
                                     const char *srcSpec,
                                     unsigned int flags)
492 493 494
{
    int backend_type;
    virStorageBackendPtr backend;
495
    char *ret = NULL;
496

497 498 499
    if (virConnectFindStoragePoolSourcesEnsureACL(conn) < 0)
        return NULL;

500
    backend_type = virStoragePoolTypeFromString(type);
501
    if (backend_type < 0) {
502 503
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
504
        goto cleanup;
505
    }
506 507 508

    backend = virStorageBackendForType(backend_type);
    if (backend == NULL)
509
        goto cleanup;
510

511
    if (!backend->findPoolSources) {
512 513 514
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source "
                         "discovery"), type);
515 516 517 518
        goto cleanup;
    }

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

520 521
cleanup:
    return ret;
522 523 524
}


525
static int storagePoolIsActive(virStoragePoolPtr pool)
526
{
527
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
528 529 530 531
    virStoragePoolObjPtr obj;
    int ret = -1;

    storageDriverLock(driver);
532
    obj = virStoragePoolObjFindByUUID(&driver->pools, pool->uuid);
533 534
    storageDriverUnlock(driver);
    if (!obj) {
535
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
536 537
        goto cleanup;
    }
538 539 540 541

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

542 543 544 545 546 547 548 549
    ret = virStoragePoolObjIsActive(obj);

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

550
static int storagePoolIsPersistent(virStoragePoolPtr pool)
551
{
552
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
553 554 555 556
    virStoragePoolObjPtr obj;
    int ret = -1;

    storageDriverLock(driver);
557
    obj = virStoragePoolObjFindByUUID(&driver->pools, pool->uuid);
558 559
    storageDriverUnlock(driver);
    if (!obj) {
560
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
561 562
        goto cleanup;
    }
563 564 565 566

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

567 568 569 570 571 572 573 574 575
    ret = obj->configFile ? 1 : 0;

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


576
static virStoragePoolPtr
577 578 579
storagePoolCreateXML(virConnectPtr conn,
                     const char *xml,
                     unsigned int flags)
E
Eric Blake 已提交
580
{
581
    virStorageDriverStatePtr driver = conn->storagePrivateData;
582
    virStoragePoolDefPtr def;
583
    virStoragePoolObjPtr pool = NULL;
584
    virStoragePoolPtr ret = NULL;
585 586
    virStorageBackendPtr backend;

E
Eric Blake 已提交
587 588
    virCheckFlags(0, NULL);

589
    storageDriverLock(driver);
590
    if (!(def = virStoragePoolDefParseString(xml)))
591
        goto cleanup;
592

593 594 595
    if (virStoragePoolCreateXMLEnsureACL(conn, def) < 0)
        goto cleanup;

596
    if (virStoragePoolObjIsDuplicate(&driver->pools, def, 1) < 0)
597
        goto cleanup;
598

599 600 601
    if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
        goto cleanup;

602 603
    if ((backend = virStorageBackendForType(def->type)) == NULL)
        goto cleanup;
604

605
    if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
606 607
        goto cleanup;
    def = NULL;
608

609
    if (backend->startPool &&
610 611 612
        backend->startPool(conn, pool) < 0) {
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
613
        goto cleanup;
614
    }
615

616 617 618
    if (backend->refreshPool(conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(conn, pool);
619 620
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
621
        goto cleanup;
622
    }
623
    VIR_INFO("Creating storage pool '%s'", pool->def->name);
624 625
    pool->active = 1;

626 627
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
628

629 630
cleanup:
    virStoragePoolDefFree(def);
631
    if (pool)
632
        virStoragePoolObjUnlock(pool);
633
    storageDriverUnlock(driver);
634 635 636 637
    return ret;
}

static virStoragePoolPtr
638 639 640
storagePoolDefineXML(virConnectPtr conn,
                     const char *xml,
                     unsigned int flags)
E
Eric Blake 已提交
641
{
642
    virStorageDriverStatePtr driver = conn->storagePrivateData;
643
    virStoragePoolDefPtr def;
644
    virStoragePoolObjPtr pool = NULL;
645
    virStoragePoolPtr ret = NULL;
646

E
Eric Blake 已提交
647 648
    virCheckFlags(0, NULL);

649
    storageDriverLock(driver);
650
    if (!(def = virStoragePoolDefParseString(xml)))
651
        goto cleanup;
652

653 654 655
    if (virStoragePoolDefineXMLEnsureACL(conn, def) < 0)
        goto cleanup;

656 657 658
    if (virStoragePoolObjIsDuplicate(&driver->pools, def, 0) < 0)
        goto cleanup;

659 660 661
    if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
        goto cleanup;

662
    if (virStorageBackendForType(def->type) == NULL)
663
        goto cleanup;
664

665
    if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
666
        goto cleanup;
667

668
    if (virStoragePoolObjSaveDef(driver, pool, def) < 0) {
669
        virStoragePoolObjRemove(&driver->pools, pool);
670
        def = NULL;
671
        goto cleanup;
672
    }
673
    def = NULL;
674

675
    VIR_INFO("Defining storage pool '%s'", pool->def->name);
676 677
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
678 679 680

cleanup:
    virStoragePoolDefFree(def);
681 682 683
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
684 685 686 687 688
    return ret;
}

static int
storagePoolUndefine(virStoragePoolPtr obj) {
689 690 691
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
692

693
    storageDriverLock(driver);
694
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
695
    if (!pool) {
696
        virReportError(VIR_ERR_NO_STORAGE_POOL,
697
                       _("no storage pool with matching uuid %s"), obj->uuid);
698
        goto cleanup;
699 700
    }

701 702 703
    if (virStoragePoolUndefineEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

704
    if (virStoragePoolObjIsActive(pool)) {
705
        virReportError(VIR_ERR_OPERATION_INVALID,
706 707
                       _("storage pool '%s' is still active"),
                       pool->def->name);
708
        goto cleanup;
709 710
    }

711
    if (pool->asyncjobs > 0) {
712 713 714
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
                       pool->def->name);
715 716 717
        goto cleanup;
    }

718
    if (virStoragePoolObjDeleteDef(pool) < 0)
719
        goto cleanup;
720

721 722
    if (unlink(pool->autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
        char ebuf[1024];
723
        VIR_ERROR(_("Failed to delete autostart link '%s': %s"),
724
                  pool->autostartLink, virStrerror(errno, ebuf, sizeof(ebuf)));
725
    }
726

727 728
    VIR_FREE(pool->configFile);
    VIR_FREE(pool->autostartLink);
729

730
    VIR_INFO("Undefining storage pool '%s'", pool->def->name);
731
    virStoragePoolObjRemove(&driver->pools, pool);
732
    pool = NULL;
733
    ret = 0;
734

735
cleanup:
736 737 738
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
739
    return ret;
740 741 742
}

static int
743 744
storagePoolCreate(virStoragePoolPtr obj,
                  unsigned int flags)
E
Eric Blake 已提交
745
{
746 747
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
748
    virStorageBackendPtr backend;
749
    int ret = -1;
750

E
Eric Blake 已提交
751 752
    virCheckFlags(0, -1);

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

757
    if (!pool) {
758
        virReportError(VIR_ERR_NO_STORAGE_POOL,
759
                       _("no storage pool with matching uuid %s"), obj->uuid);
760
        goto cleanup;
761 762
    }

763 764 765
    if (virStoragePoolCreateEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

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

    if (virStoragePoolObjIsActive(pool)) {
770
        virReportError(VIR_ERR_OPERATION_INVALID,
771 772
                       _("storage pool '%s' is already active"),
                       pool->def->name);
773
        goto cleanup;
774 775 776
    }
    if (backend->startPool &&
        backend->startPool(obj->conn, pool) < 0)
777 778
        goto cleanup;

779 780 781
    if (backend->refreshPool(obj->conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(obj->conn, pool);
782
        goto cleanup;
783 784
    }

785
    VIR_INFO("Starting up storage pool '%s'", pool->def->name);
786
    pool->active = 1;
787
    ret = 0;
788

789
cleanup:
790 791
    if (pool)
        virStoragePoolObjUnlock(pool);
792
    return ret;
793 794 795 796 797
}

static int
storagePoolBuild(virStoragePoolPtr obj,
                 unsigned int flags) {
798 799
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
800
    virStorageBackendPtr backend;
801
    int ret = -1;
802

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

807
    if (!pool) {
808
        virReportError(VIR_ERR_NO_STORAGE_POOL,
809
                       _("no storage pool with matching uuid %s"), obj->uuid);
810
        goto cleanup;
811 812
    }

813 814 815
    if (virStoragePoolBuildEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

816 817
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
818 819

    if (virStoragePoolObjIsActive(pool)) {
820
        virReportError(VIR_ERR_OPERATION_INVALID,
821 822
                       _("storage pool '%s' is already active"),
                       pool->def->name);
823
        goto cleanup;
824 825 826 827
    }

    if (backend->buildPool &&
        backend->buildPool(obj->conn, pool, flags) < 0)
828 829
        goto cleanup;
    ret = 0;
830

831
cleanup:
832 833
    if (pool)
        virStoragePoolObjUnlock(pool);
834
    return ret;
835 836 837 838 839
}


static int
storagePoolDestroy(virStoragePoolPtr obj) {
840 841
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
842
    virStorageBackendPtr backend;
843
    int ret = -1;
844

845
    storageDriverLock(driver);
846
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
847

848
    if (!pool) {
849
        virReportError(VIR_ERR_NO_STORAGE_POOL,
850
                       _("no storage pool with matching uuid %s"), obj->uuid);
851
        goto cleanup;
852 853
    }

854 855 856
    if (virStoragePoolDestroyEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

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

    if (!virStoragePoolObjIsActive(pool)) {
861
        virReportError(VIR_ERR_OPERATION_INVALID,
862
                       _("storage pool '%s' is not active"), pool->def->name);
863
        goto cleanup;
864 865
    }

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

873 874
    if (backend->stopPool &&
        backend->stopPool(obj->conn, pool) < 0)
875
        goto cleanup;
876 877 878 879

    virStoragePoolObjClearVols(pool);

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

882
    if (pool->configFile == NULL) {
883
        virStoragePoolObjRemove(&driver->pools, pool);
884
        pool = NULL;
885 886 887 888
    } else if (pool->newDef) {
        virStoragePoolDefFree(pool->def);
        pool->def = pool->newDef;
        pool->newDef = NULL;
889
    }
890
    ret = 0;
891

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

static int
storagePoolDelete(virStoragePoolPtr obj,
                  unsigned int flags) {
902 903
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
904
    virStorageBackendPtr backend;
905
    int ret = -1;
906

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

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

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

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

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

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

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

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


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

E
Eric Blake 已提交
963 964
    virCheckFlags(0, -1);

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

968
    if (!pool) {
969
        virReportError(VIR_ERR_NO_STORAGE_POOL,
970
                       _("no storage pool with matching uuid %s"), obj->uuid);
971
        goto cleanup;
972 973
    }

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

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

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

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

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

        pool->active = 0;

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

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


static int
storagePoolGetInfo(virStoragePoolPtr obj,
                   virStoragePoolInfoPtr info) {
1019 1020 1021
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
1022

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

1027
    if (!pool) {
1028
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1029
                       _("no storage pool with matching uuid %s"), obj->uuid);
1030
        goto cleanup;
1031 1032
    }

1033 1034 1035
    if (virStoragePoolGetInfoEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1036
    if (virStorageBackendForType(pool->def->type) == NULL)
1037
        goto cleanup;
1038 1039 1040 1041 1042 1043 1044 1045 1046

    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;
1047
    ret = 0;
1048

1049
cleanup:
1050 1051
    if (pool)
        virStoragePoolObjUnlock(pool);
1052
    return ret;
1053 1054 1055
}

static char *
1056
storagePoolGetXMLDesc(virStoragePoolPtr obj,
E
Eric Blake 已提交
1057 1058
                      unsigned int flags)
{
1059 1060
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1061
    virStoragePoolDefPtr def;
1062
    char *ret = NULL;
1063

1064
    virCheckFlags(VIR_STORAGE_XML_INACTIVE, NULL);
E
Eric Blake 已提交
1065

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

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

1076 1077 1078
    if (virStoragePoolGetXMLDescEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1079 1080 1081 1082 1083 1084
    if ((flags & VIR_STORAGE_XML_INACTIVE) && pool->newDef)
        def = pool->newDef;
    else
        def = pool->def;

    ret = virStoragePoolDefFormat(def);
1085 1086

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

static int
storagePoolGetAutostart(virStoragePoolPtr obj,
                        int *autostart) {
1095 1096 1097
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
1098

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

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

1109 1110 1111
    if (virStoragePoolGetAutostartEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1112 1113 1114 1115 1116
    if (!pool->configFile) {
        *autostart = 0;
    } else {
        *autostart = pool->autostart;
    }
1117
    ret = 0;
1118

1119
cleanup:
1120 1121
    if (pool)
        virStoragePoolObjUnlock(pool);
1122
    return ret;
1123 1124 1125 1126 1127
}

static int
storagePoolSetAutostart(virStoragePoolPtr obj,
                        int autostart) {
1128 1129 1130
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
1131

1132
    storageDriverLock(driver);
1133
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1134

1135
    if (!pool) {
1136
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1137
                       _("no storage pool with matching uuid %s"), obj->uuid);
1138
        goto cleanup;
1139 1140
    }

1141 1142 1143
    if (virStoragePoolSetAutostartEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1144
    if (!pool->configFile) {
1145 1146
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("pool has no config file"));
1147
        goto cleanup;
1148 1149 1150 1151
    }

    autostart = (autostart != 0);

1152 1153
    if (pool->autostart != autostart) {
        if (autostart) {
1154 1155
            if (virFileMakePath(driver->autostartDir) < 0) {
                virReportSystemError(errno,
1156 1157
                                     _("cannot create autostart directory %s"),
                                     driver->autostartDir);
1158 1159
                goto cleanup;
            }
1160

1161
            if (symlink(pool->configFile, pool->autostartLink) < 0) {
1162
                virReportSystemError(errno,
1163 1164
                                     _("Failed to create symlink '%s' to '%s'"),
                                     pool->autostartLink, pool->configFile);
1165 1166 1167 1168 1169
                goto cleanup;
            }
        } else {
            if (unlink(pool->autostartLink) < 0 &&
                errno != ENOENT && errno != ENOTDIR) {
1170
                virReportSystemError(errno,
1171 1172
                                     _("Failed to delete symlink '%s'"),
                                     pool->autostartLink);
1173 1174
                goto cleanup;
            }
1175
        }
1176
        pool->autostart = autostart;
1177
    }
1178
    ret = 0;
1179

1180
cleanup:
1181 1182
    if (pool)
        virStoragePoolObjUnlock(pool);
1183
    storageDriverUnlock(driver);
1184
    return ret;
1185 1186 1187 1188
}


static int
1189
storagePoolNumOfVolumes(virStoragePoolPtr obj) {
1190 1191
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1192 1193
    int ret = -1;
    size_t i;
1194

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

1199
    if (!pool) {
1200
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1201
                       _("no storage pool with matching uuid %s"), obj->uuid);
1202
        goto cleanup;
1203 1204
    }

1205 1206 1207
    if (virStoragePoolNumOfVolumesEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1208
    if (!virStoragePoolObjIsActive(pool)) {
1209
        virReportError(VIR_ERR_OPERATION_INVALID,
1210
                       _("storage pool '%s' is not active"), pool->def->name);
1211
        goto cleanup;
1212
    }
1213 1214 1215 1216 1217 1218
    ret = 0;
    for (i = 0; i < pool->volumes.count; i++) {
        if (virStoragePoolNumOfVolumesCheckACL(obj->conn, pool->def,
                                               pool->volumes.objs[i]))
            ret++;
    }
1219

1220
cleanup:
1221 1222
    if (pool)
        virStoragePoolObjUnlock(pool);
1223
    return ret;
1224 1225 1226 1227 1228 1229
}

static int
storagePoolListVolumes(virStoragePoolPtr obj,
                       char **const names,
                       int maxnames) {
1230 1231
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1232 1233
    size_t i;
    int n = 0;
1234

1235 1236
    memset(names, 0, maxnames * sizeof(*names));

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

1241
    if (!pool) {
1242
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1243
                       _("no storage pool with matching uuid %s"), obj->uuid);
1244
        goto cleanup;
1245 1246
    }

1247 1248 1249
    if (virStoragePoolListVolumesEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1250
    if (!virStoragePoolObjIsActive(pool)) {
1251
        virReportError(VIR_ERR_OPERATION_INVALID,
1252
                       _("storage pool '%s' is not active"), pool->def->name);
1253
        goto cleanup;
1254 1255
    }

1256
    for (i = 0; i < pool->volumes.count && n < maxnames; i++) {
1257 1258 1259
        if (!virStoragePoolListVolumesCheckACL(obj->conn, pool->def,
                                               pool->volumes.objs[i]))
            continue;
1260
        if (VIR_STRDUP(names[n++], pool->volumes.objs[i]->name) < 0)
1261 1262 1263
            goto cleanup;
    }

1264
    virStoragePoolObjUnlock(pool);
1265
    return n;
1266 1267

 cleanup:
1268 1269
    if (pool)
        virStoragePoolObjUnlock(pool);
1270
    for (n = 0; n < maxnames; n++)
1271
        VIR_FREE(names[n]);
1272

1273
    memset(names, 0, maxnames * sizeof(*names));
1274 1275 1276
    return -1;
}

1277 1278 1279 1280 1281 1282
static int
storagePoolListAllVolumes(virStoragePoolPtr pool,
                          virStorageVolPtr **vols,
                          unsigned int flags) {
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
    virStoragePoolObjPtr obj;
1283
    size_t i;
1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295
    virStorageVolPtr *tmp_vols = NULL;
    virStorageVolPtr vol = NULL;
    int nvols = 0;
    int ret = -1;

    virCheckFlags(0, -1);

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

    if (!obj) {
1296 1297 1298
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching uuid %s"),
                       pool->uuid);
1299 1300 1301
        goto cleanup;
    }

1302 1303 1304
    if (virStoragePoolListAllVolumesEnsureACL(pool->conn, obj->def) < 0)
        goto cleanup;

1305
    if (!virStoragePoolObjIsActive(obj)) {
1306 1307
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), obj->def->name);
1308 1309 1310 1311 1312 1313 1314 1315 1316
        goto cleanup;
    }

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

1317
    if (VIR_ALLOC_N(tmp_vols, obj->volumes.count + 1) < 0)
1318
        goto cleanup;
1319

1320
    for (i = 0; i < obj->volumes.count; i++) {
1321 1322 1323
        if (!virStoragePoolListAllVolumesCheckACL(pool->conn, obj->def,
                                                  obj->volumes.objs[i]))
            continue;
1324 1325
        if (!(vol = virGetStorageVol(pool->conn, obj->def->name,
                                     obj->volumes.objs[i]->name,
1326 1327
                                     obj->volumes.objs[i]->key,
                                     NULL, NULL)))
1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341
            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]);
        }
1342
        VIR_FREE(tmp_vols);
1343 1344 1345 1346 1347 1348 1349
    }

    if (obj)
        virStoragePoolObjUnlock(obj);

    return ret;
}
1350 1351

static virStorageVolPtr
1352 1353
storageVolLookupByName(virStoragePoolPtr obj,
                       const char *name) {
1354 1355
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1356
    virStorageVolDefPtr vol;
1357
    virStorageVolPtr ret = NULL;
1358

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

1363
    if (!pool) {
1364
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1365
                       _("no storage pool with matching uuid %s"), obj->uuid);
1366
        goto cleanup;
1367 1368 1369
    }

    if (!virStoragePoolObjIsActive(pool)) {
1370
        virReportError(VIR_ERR_OPERATION_INVALID,
1371
                       _("storage pool '%s' is not active"), pool->def->name);
1372
        goto cleanup;
1373 1374 1375 1376 1377
    }

    vol = virStorageVolDefFindByName(pool, name);

    if (!vol) {
1378 1379 1380
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       name);
1381
        goto cleanup;
1382 1383
    }

1384 1385 1386
    if (virStorageVolLookupByNameEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

1387 1388
    ret = virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key,
                           NULL, NULL);
1389 1390

cleanup:
1391 1392
    if (pool)
        virStoragePoolObjUnlock(pool);
1393
    return ret;
1394 1395 1396 1397
}


static virStorageVolPtr
1398 1399
storageVolLookupByKey(virConnectPtr conn,
                      const char *key) {
1400
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1401
    size_t i;
1402
    virStorageVolPtr ret = NULL;
1403

1404
    storageDriverLock(driver);
1405
    for (i = 0; i < driver->pools.count && !ret; i++) {
1406
        virStoragePoolObjLock(driver->pools.objs[i]);
1407 1408 1409
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
            virStorageVolDefPtr vol =
                virStorageVolDefFindByKey(driver->pools.objs[i], key);
1410

1411
            if (vol) {
1412 1413
                if (virStorageVolLookupByKeyEnsureACL(conn, driver->pools.objs[i]->def, vol) < 0) {
                    virStoragePoolObjUnlock(driver->pools.objs[i]);
1414
                    goto cleanup;
1415
                }
1416

1417
                ret = virGetStorageVol(conn,
1418 1419
                                       driver->pools.objs[i]->def->name,
                                       vol->name,
1420 1421
                                       vol->key,
                                       NULL, NULL);
1422
            }
1423
        }
1424
        virStoragePoolObjUnlock(driver->pools.objs[i]);
1425 1426
    }

1427
    if (!ret)
1428
        virReportError(VIR_ERR_NO_STORAGE_VOL,
1429
                       _("no storage vol with matching key %s"), key);
1430

1431 1432
cleanup:
    storageDriverUnlock(driver);
1433
    return ret;
1434 1435 1436
}

static virStorageVolPtr
1437 1438
storageVolLookupByPath(virConnectPtr conn,
                       const char *path) {
1439
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1440
    size_t i;
1441
    virStorageVolPtr ret = NULL;
1442 1443 1444 1445 1446
    char *cleanpath;

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

1448
    storageDriverLock(driver);
1449
    for (i = 0; i < driver->pools.count && !ret; i++) {
1450
        virStoragePoolObjLock(driver->pools.objs[i]);
1451
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
1452
            virStorageVolDefPtr vol;
1453
            char *stable_path;
1454

1455
            stable_path = virStorageBackendStablePath(driver->pools.objs[i],
1456 1457
                                                      cleanpath,
                                                      false);
1458
            if (stable_path == NULL) {
1459 1460 1461 1462 1463
                /* Don't break the whole lookup process if it fails on
                 * getting the stable path for some of the pools.
                 */
                VIR_WARN("Failed to get stable path for pool '%s'",
                         driver->pools.objs[i]->def->name);
1464
                virStoragePoolObjUnlock(driver->pools.objs[i]);
1465
                continue;
1466
            }
1467 1468 1469 1470

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

1472
            if (vol) {
1473 1474
                if (virStorageVolLookupByPathEnsureACL(conn, driver->pools.objs[i]->def, vol) < 0) {
                    virStoragePoolObjUnlock(driver->pools.objs[i]);
1475
                    goto cleanup;
1476
                }
1477

1478 1479 1480
                ret = virGetStorageVol(conn,
                                       driver->pools.objs[i]->def->name,
                                       vol->name,
1481 1482
                                       vol->key,
                                       NULL, NULL);
1483
            }
1484
        }
1485
        virStoragePoolObjUnlock(driver->pools.objs[i]);
1486 1487
    }

1488
    if (!ret)
1489
        virReportError(VIR_ERR_NO_STORAGE_VOL,
1490
                       _("no storage vol with matching path %s"), path);
1491

1492
cleanup:
1493
    VIR_FREE(cleanpath);
1494
    storageDriverUnlock(driver);
1495
    return ret;
1496 1497
}

1498
static int storageVolDelete(virStorageVolPtr obj, unsigned int flags);
1499

1500
static virStorageVolPtr
1501 1502 1503
storageVolCreateXML(virStoragePoolPtr obj,
                    const char *xmldesc,
                    unsigned int flags)
E
Eric Blake 已提交
1504
{
1505 1506
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1507
    virStorageBackendPtr backend;
1508 1509
    virStorageVolDefPtr voldef = NULL;
    virStorageVolPtr ret = NULL, volobj = NULL;
1510
    virStorageVolDefPtr buildvoldef = NULL;
1511

1512
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
E
Eric Blake 已提交
1513

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

1518
    if (!pool) {
1519
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1520
                       _("no storage pool with matching uuid %s"), obj->uuid);
1521
        goto cleanup;
1522 1523 1524
    }

    if (!virStoragePoolObjIsActive(pool)) {
1525
        virReportError(VIR_ERR_OPERATION_INVALID,
1526
                       _("storage pool '%s' is not active"), pool->def->name);
1527
        goto cleanup;
1528 1529 1530
    }

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

1533
    voldef = virStorageVolDefParseString(pool->def, xmldesc);
1534
    if (voldef == NULL)
1535
        goto cleanup;
1536

1537 1538 1539
    if (virStorageVolCreateXMLEnsureACL(obj->conn, pool->def, voldef) < 0)
        goto cleanup;

1540
    if (virStorageVolDefFindByName(pool, voldef->name)) {
1541
        virReportError(VIR_ERR_NO_STORAGE_VOL,
1542
                       _("storage vol '%s' already exists"), voldef->name);
1543
        goto cleanup;
1544 1545
    }

1546
    if (VIR_REALLOC_N(pool->volumes.objs,
1547
                      pool->volumes.count+1) < 0)
1548
        goto cleanup;
1549

1550
    if (!backend->createVol) {
1551 1552 1553
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("storage pool does not support volume "
                               "creation"));
1554
        goto cleanup;
1555 1556
    }

1557 1558 1559
    /* Wipe any key the user may have suggested, as volume creation
     * will generate the canonical key.  */
    VIR_FREE(voldef->key);
1560
    if (backend->createVol(obj->conn, pool, voldef) < 0) {
1561
        goto cleanup;
1562 1563
    }

1564 1565
    pool->volumes.objs[pool->volumes.count++] = voldef;
    volobj = virGetStorageVol(obj->conn, pool->def->name, voldef->name,
1566
                              voldef->key, NULL, NULL);
1567 1568 1569 1570
    if (!volobj) {
        pool->volumes.count--;
        goto cleanup;
    }
1571

1572 1573 1574 1575
    if (VIR_ALLOC(buildvoldef) < 0) {
        voldef = NULL;
        goto cleanup;
    }
1576

1577 1578 1579 1580 1581
    /* 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));
1582

1583 1584
    if (backend->buildVol) {
        int buildret;
1585 1586 1587 1588 1589 1590

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

1591
        buildret = backend->buildVol(obj->conn, pool, buildvoldef, flags);
1592

1593
        storageDriverLock(driver);
1594
        virStoragePoolObjLock(pool);
1595 1596
        storageDriverUnlock(driver);

1597 1598 1599 1600 1601 1602 1603
        voldef->building = 0;
        pool->asyncjobs--;

        voldef = NULL;

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

    }

1611 1612 1613 1614
    /* Update pool metadata */
    pool->def->allocation += buildvoldef->allocation;
    pool->def->available -= buildvoldef->allocation;

1615
    VIR_INFO("Creating volume '%s' in storage pool '%s'",
1616
             volobj->name, pool->def->name);
1617 1618 1619
    ret = volobj;
    volobj = NULL;
    voldef = NULL;
1620

1621
cleanup:
1622
    virObjectUnref(volobj);
1623
    virStorageVolDefFree(voldef);
1624
    VIR_FREE(buildvoldef);
1625 1626
    if (pool)
        virStoragePoolObjUnlock(pool);
1627
    return ret;
1628 1629
}

1630
static virStorageVolPtr
1631 1632 1633 1634
storageVolCreateXMLFrom(virStoragePoolPtr obj,
                        const char *xmldesc,
                        virStorageVolPtr vobj,
                        unsigned int flags)
E
Eric Blake 已提交
1635
{
1636 1637 1638 1639 1640
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool, origpool = NULL;
    virStorageBackendPtr backend;
    virStorageVolDefPtr origvol = NULL, newvol = NULL;
    virStorageVolPtr ret = NULL, volobj = NULL;
O
Osier Yang 已提交
1641
    unsigned long long allocation;
1642
    int buildret;
1643

1644
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
E
Eric Blake 已提交
1645

1646 1647
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1648
    if (pool && STRNEQ(obj->name, vobj->pool)) {
1649
        virStoragePoolObjUnlock(pool);
1650
        origpool = virStoragePoolObjFindByName(&driver->pools, vobj->pool);
1651
        virStoragePoolObjLock(pool);
1652
    }
1653 1654
    storageDriverUnlock(driver);
    if (!pool) {
1655
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1656
                       _("no storage pool with matching uuid %s"), obj->uuid);
1657 1658 1659
        goto cleanup;
    }

1660
    if (STRNEQ(obj->name, vobj->pool) && !origpool) {
1661 1662 1663
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       vobj->pool);
1664 1665 1666 1667
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1668
        virReportError(VIR_ERR_OPERATION_INVALID,
1669
                       _("storage pool '%s' is not active"), pool->def->name);
1670 1671 1672
        goto cleanup;
    }

1673
    if (origpool && !virStoragePoolObjIsActive(origpool)) {
1674
        virReportError(VIR_ERR_OPERATION_INVALID,
1675 1676
                       _("storage pool '%s' is not active"),
                       origpool->def->name);
1677 1678 1679 1680 1681 1682
        goto cleanup;
    }

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

1683
    origvol = virStorageVolDefFindByName(origpool ? origpool : pool, vobj->name);
1684
    if (!origvol) {
1685 1686 1687
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vobj->name);
1688 1689 1690
        goto cleanup;
    }

1691
    newvol = virStorageVolDefParseString(pool->def, xmldesc);
1692 1693 1694
    if (newvol == NULL)
        goto cleanup;

1695 1696 1697
    if (virStorageVolCreateXMLFromEnsureACL(obj->conn, pool->def, newvol) < 0)
        goto cleanup;

1698
    if (virStorageVolDefFindByName(pool, newvol->name)) {
1699 1700 1701
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("storage volume name '%s' already in use."),
                       newvol->name);
1702 1703 1704 1705 1706 1707 1708
        goto cleanup;
    }

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

1709 1710 1711 1712 1713
    /* Make sure allocation is at least as large as the destination cap,
     * to make absolutely sure we copy all possible contents */
    if (newvol->allocation < origvol->capacity)
        newvol->allocation = origvol->capacity;

1714
    if (!backend->buildVolFrom) {
1715 1716
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("storage pool does not support volume creation from an existing volume"));
1717 1718 1719 1720
        goto cleanup;
    }

    if (origvol->building) {
1721 1722 1723
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       origvol->name);
1724 1725 1726 1727 1728 1729 1730 1731
        goto cleanup;
    }

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

    if (VIR_REALLOC_N(pool->volumes.objs,
1732
                      pool->volumes.count+1) < 0)
1733 1734
        goto cleanup;

1735 1736 1737 1738
    /* '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);
1739 1740 1741 1742 1743 1744
    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,
1745
                              newvol->key, NULL, NULL);
1746 1747 1748 1749 1750 1751 1752

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

1753
    if (origpool) {
1754 1755 1756 1757
        origpool->asyncjobs++;
        virStoragePoolObjUnlock(origpool);
    }

1758
    buildret = backend->buildVolFrom(obj->conn, pool, newvol, origvol, flags);
1759 1760 1761

    storageDriverLock(driver);
    virStoragePoolObjLock(pool);
1762
    if (origpool)
1763 1764 1765 1766 1767
        virStoragePoolObjLock(origpool);
    storageDriverUnlock(driver);

    origvol->building = 0;
    newvol->building = 0;
O
Osier Yang 已提交
1768
    allocation = newvol->allocation;
1769 1770 1771
    newvol = NULL;
    pool->asyncjobs--;

1772
    if (origpool) {
1773 1774 1775 1776 1777 1778 1779
        origpool->asyncjobs--;
        virStoragePoolObjUnlock(origpool);
        origpool = NULL;
    }

    if (buildret < 0) {
        virStoragePoolObjUnlock(pool);
1780
        storageVolDelete(volobj, 0);
1781 1782 1783 1784
        pool = NULL;
        goto cleanup;
    }

1785
    /* Updating pool metadata */
O
Osier Yang 已提交
1786 1787
    pool->def->allocation += allocation;
    pool->def->available -= allocation;
1788

1789
    VIR_INFO("Creating volume '%s' in storage pool '%s'",
1790
             volobj->name, pool->def->name);
1791 1792 1793 1794
    ret = volobj;
    volobj = NULL;

cleanup:
1795
    virObjectUnref(volobj);
1796 1797 1798
    virStorageVolDefFree(newvol);
    if (pool)
        virStoragePoolObjUnlock(pool);
1799
    if (origpool)
1800 1801 1802 1803
        virStoragePoolObjUnlock(origpool);
    return ret;
}

1804

1805
static int
1806 1807 1808 1809 1810
storageVolDownload(virStorageVolPtr obj,
                   virStreamPtr stream,
                   unsigned long long offset,
                   unsigned long long length,
                   unsigned int flags)
1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

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

    if (!pool) {
1824
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1825 1826
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1827 1828 1829 1830
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1831
        virReportError(VIR_ERR_OPERATION_INVALID,
1832
                       _("storage pool '%s' is not active"), pool->def->name);
1833 1834 1835 1836 1837 1838
        goto out;
    }

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

    if (vol == NULL) {
1839 1840 1841
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1842 1843 1844
        goto out;
    }

1845 1846 1847
    if (virStorageVolDownloadEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

1848
    if (vol->building) {
1849 1850 1851
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1852 1853 1854 1855 1856 1857
        goto out;
    }

    if (virFDStreamOpenFile(stream,
                            vol->target.path,
                            offset, length,
E
Eric Blake 已提交
1858
                            O_RDONLY) < 0)
1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871
        goto out;

    ret = 0;

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}


static int
1872 1873 1874 1875 1876
storageVolUpload(virStorageVolPtr obj,
                 virStreamPtr stream,
                 unsigned long long offset,
                 unsigned long long length,
                 unsigned int flags)
1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

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

    if (!pool) {
1890
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1891 1892
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1893 1894 1895 1896
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1897
        virReportError(VIR_ERR_OPERATION_INVALID,
1898
                       _("storage pool '%s' is not active"), pool->def->name);
1899 1900 1901 1902 1903 1904
        goto out;
    }

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

    if (vol == NULL) {
1905 1906 1907
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1908 1909 1910
        goto out;
    }

1911 1912 1913
    if (virStorageVolUploadEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

1914
    if (vol->building) {
1915 1916 1917
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1918 1919 1920 1921 1922 1923 1924 1925
        goto out;
    }

    /* Not using O_CREAT because the file is required to
     * already exist at this point */
    if (virFDStreamOpenFile(stream,
                            vol->target.path,
                            offset, length,
E
Eric Blake 已提交
1926
                            O_WRONLY) < 0)
1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937
        goto out;

    ret = 0;

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}

1938
static int
1939 1940 1941
storageVolResize(virStorageVolPtr obj,
                 unsigned long long capacity,
                 unsigned int flags)
1942 1943 1944 1945 1946 1947 1948 1949
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStorageBackendPtr backend;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    unsigned long long abs_capacity;
    int ret = -1;

1950
    virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE |
1951 1952
                  VIR_STORAGE_VOL_RESIZE_DELTA |
                  VIR_STORAGE_VOL_RESIZE_SHRINK, -1);
1953 1954 1955 1956 1957 1958

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

    if (!pool) {
1959 1960 1961
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1962 1963 1964 1965
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1966 1967
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->def->name);
1968 1969 1970 1971 1972 1973 1974 1975 1976
        goto out;
    }

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

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

    if (vol == NULL) {
1977 1978 1979
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1980 1981 1982
        goto out;
    }

1983 1984 1985
    if (virStorageVolResizeEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

1986
    if (vol->building) {
1987 1988 1989
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1990 1991
        goto out;
    }
1992

1993 1994 1995 1996 1997 1998 1999 2000
    if (flags & VIR_STORAGE_VOL_RESIZE_DELTA) {
        abs_capacity = vol->capacity + capacity;
        flags &= ~VIR_STORAGE_VOL_RESIZE_DELTA;
    } else {
        abs_capacity = capacity;
    }

    if (abs_capacity < vol->allocation) {
2001
        virReportError(VIR_ERR_INVALID_ARG, "%s",
2002 2003
                       _("can't shrink capacity below "
                         "existing allocation"));
2004 2005 2006
        goto out;
    }

2007 2008 2009 2010 2011 2012 2013 2014
    if (abs_capacity < vol->capacity &&
        !(flags & VIR_STORAGE_VOL_RESIZE_SHRINK)) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("Can't shrink capacity below current "
                         "capacity with shrink flag explicitly specified"));
        goto out;
    }

2015
    if (abs_capacity > vol->capacity + pool->def->available) {
2016
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
2017
                       _("Not enough space left on storage pool"));
2018 2019 2020 2021
        goto out;
    }

    if (!backend->resizeVol) {
2022
        virReportError(VIR_ERR_NO_SUPPORT, "%s",
2023 2024
                       _("storage pool does not support changing of "
                         "volume capacity"));
2025 2026 2027 2028 2029 2030
        goto out;
    }

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

O
Osier Yang 已提交
2031
    vol->capacity = abs_capacity;
2032 2033 2034 2035 2036

    /* Update pool metadata */
    pool->def->allocation += (abs_capacity - vol->capacity);
    pool->def->available -= (abs_capacity - vol->capacity);

O
Osier Yang 已提交
2037
    ret = 0;
2038 2039 2040 2041 2042 2043 2044

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
2045

2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060
/* 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
2061 2062 2063
storageVolZeroSparseFile(virStorageVolDefPtr vol,
                         off_t size,
                         int fd)
2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079
{
    int ret = -1;

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

    ret = ftruncate(fd, size);
    if (ret == -1) {
        virReportSystemError(errno,
                             _("Failed to truncate volume with "
2080
                               "path '%s' to %ju bytes"),
E
Eric Blake 已提交
2081
                             vol->target.path, (uintmax_t)size);
2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102
    }

out:
    return ret;
}


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

    VIR_DEBUG("extent logical start: %ju len: %ju",
E
Eric Blake 已提交
2103
              (uintmax_t)extent_start, (uintmax_t)extent_length);
2104 2105 2106 2107 2108

    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 已提交
2109
                             (uintmax_t)extent_start, vol->target.path);
2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130
        goto out;
    }

    remaining = extent_length;
    while (remaining > 0) {

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

            goto out;
        }

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

2131 2132 2133 2134 2135 2136 2137 2138
    if (fdatasync(fd) < 0) {
        ret = -errno;
        virReportSystemError(errno,
                             _("cannot sync data to volume with path '%s'"),
                             vol->target.path);
        goto out;
    }

2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149
    VIR_DEBUG("Wrote %zu bytes to volume with path '%s'",
              *bytes_wiped, vol->target.path);

    ret = 0;

out:
    return ret;
}


static int
2150 2151
storageVolWipeInternal(virStorageVolDefPtr def,
                       unsigned int algorithm)
2152 2153 2154 2155 2156
{
    int ret = -1, fd = -1;
    struct stat st;
    char *writebuf = NULL;
    size_t bytes_wiped = 0;
2157
    virCommandPtr cmd = NULL;
2158

2159 2160
    VIR_DEBUG("Wiping volume with path '%s' and algorithm %u",
              def->target.path, algorithm);
2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176

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

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

2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192
    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 已提交
2193
            alg_char = "schneier";
2194 2195 2196 2197 2198
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7:
            alg_char = "pfitzner7";
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33:
M
Michal Privoznik 已提交
2199
            alg_char = "pfitzner33";
2200 2201 2202 2203 2204
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_RANDOM:
            alg_char = "random";
            break;
        default:
2205 2206 2207
            virReportError(VIR_ERR_INVALID_ARG,
                           _("unsupported algorithm %d"),
                           algorithm);
2208 2209 2210 2211
        }
        cmd = virCommandNew(SCRUB);
        virCommandAddArgList(cmd, "-f", "-p", alg_char,
                             def->target.path, NULL);
2212

2213
        if (virCommandRun(cmd, NULL) < 0)
2214 2215
            goto out;

2216 2217 2218 2219
        ret = 0;
        goto out;
    } else {
        if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) {
2220
            ret = storageVolZeroSparseFile(def, st.st_size, fd);
2221 2222
        } else {

2223
            if (VIR_ALLOC_N(writebuf, st.st_blksize) < 0)
2224 2225 2226 2227 2228 2229 2230 2231 2232 2233
                goto out;

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

out:
2237
    virCommandFree(cmd);
2238
    VIR_FREE(writebuf);
2239
    VIR_FORCE_CLOSE(fd);
2240 2241 2242 2243 2244
    return ret;
}


static int
2245 2246 2247
storageVolWipePattern(virStorageVolPtr obj,
                      unsigned int algorithm,
                      unsigned int flags)
2248 2249 2250 2251 2252 2253
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    int ret = -1;

2254
    virCheckFlags(0, -1);
2255

2256
    if (algorithm >= VIR_STORAGE_VOL_WIPE_ALG_LAST) {
2257 2258 2259
        virReportError(VIR_ERR_INVALID_ARG,
                       _("wiping algorithm %d not supported"),
                       algorithm);
2260 2261 2262
        return -1;
    }

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

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

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

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

    if (vol == NULL) {
2283 2284 2285
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2286 2287 2288
        goto out;
    }

2289 2290 2291
    if (virStorageVolWipePatternEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

2292
    if (vol->building) {
2293 2294 2295
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
2296 2297 2298
        goto out;
    }

2299
    if (storageVolWipeInternal(vol, algorithm) == -1) {
2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313
        goto out;
    }

    ret = 0;

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

    return ret;

}

2314
static int
2315 2316
storageVolWipe(virStorageVolPtr obj,
               unsigned int flags)
2317
{
2318
    return storageVolWipePattern(obj, VIR_STORAGE_VOL_WIPE_ALG_ZERO, flags);
2319 2320
}

2321
static int
2322 2323
storageVolDelete(virStorageVolPtr obj,
                 unsigned int flags) {
2324 2325
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2326
    virStorageBackendPtr backend;
2327
    virStorageVolDefPtr vol = NULL;
2328
    size_t i;
2329
    int ret = -1;
2330

2331
    storageDriverLock(driver);
2332
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2333 2334
    storageDriverUnlock(driver);

2335
    if (!pool) {
2336
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2337 2338
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2339
        goto cleanup;
2340 2341 2342
    }

    if (!virStoragePoolObjIsActive(pool)) {
2343
        virReportError(VIR_ERR_OPERATION_INVALID,
2344
                       _("storage pool '%s' is not active"), pool->def->name);
2345
        goto cleanup;
2346 2347 2348
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2349
        goto cleanup;
2350 2351 2352 2353

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

    if (!vol) {
2354 2355 2356
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2357
        goto cleanup;
2358 2359
    }

2360 2361 2362
    if (virStorageVolDeleteEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2363
    if (vol->building) {
2364 2365 2366
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
2367 2368 2369
        goto cleanup;
    }

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

2374
        goto cleanup;
2375 2376
    }

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

2380 2381 2382 2383
    /* Update pool metadata */
    pool->def->allocation -= vol->allocation;
    pool->def->available += vol->allocation;

2384
    for (i = 0; i < pool->volumes.count; i++) {
2385
        if (pool->volumes.objs[i] == vol) {
2386
            VIR_INFO("Deleting volume '%s' from storage pool '%s'",
2387
                     vol->name, pool->def->name);
2388
            virStorageVolDefFree(vol);
2389
            vol = NULL;
2390 2391 2392 2393 2394 2395 2396 2397 2398 2399

            if (i < (pool->volumes.count - 1))
                memmove(pool->volumes.objs + i, pool->volumes.objs + i + 1,
                        sizeof(*(pool->volumes.objs)) * (pool->volumes.count - (i + 1)));

            if (VIR_REALLOC_N(pool->volumes.objs, pool->volumes.count - 1) < 0) {
                ; /* Failure to reduce memory allocation isn't fatal */
            }
            pool->volumes.count--;

2400 2401 2402
            break;
        }
    }
2403
    ret = 0;
2404

2405
cleanup:
2406 2407
    if (pool)
        virStoragePoolObjUnlock(pool);
2408
    return ret;
2409 2410 2411
}

static int
2412 2413
storageVolGetInfo(virStorageVolPtr obj,
                  virStorageVolInfoPtr info) {
2414 2415
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2416 2417
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
2418
    int ret = -1;
2419

2420
    storageDriverLock(driver);
2421
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2422 2423
    storageDriverUnlock(driver);

2424
    if (!pool) {
2425
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2426 2427
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2428
        goto cleanup;
2429 2430 2431
    }

    if (!virStoragePoolObjIsActive(pool)) {
2432
        virReportError(VIR_ERR_OPERATION_INVALID,
2433
                       _("storage pool '%s' is not active"), pool->def->name);
2434
        goto cleanup;
2435 2436 2437 2438 2439
    }

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

    if (!vol) {
2440 2441 2442
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2443
        goto cleanup;
2444 2445
    }

2446 2447 2448
    if (virStorageVolGetInfoEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2449
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2450
        goto cleanup;
2451 2452 2453

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

    memset(info, 0, sizeof(*info));
2457
    info->type = vol->type;
2458 2459
    info->capacity = vol->capacity;
    info->allocation = vol->allocation;
2460
    ret = 0;
2461

2462
cleanup:
2463 2464
    if (pool)
        virStoragePoolObjUnlock(pool);
2465
    return ret;
2466 2467 2468
}

static char *
2469 2470
storageVolGetXMLDesc(virStorageVolPtr obj,
                     unsigned int flags)
E
Eric Blake 已提交
2471
{
2472 2473
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2474 2475
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
2476
    char *ret = NULL;
2477

E
Eric Blake 已提交
2478 2479
    virCheckFlags(0, NULL);

2480
    storageDriverLock(driver);
2481
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2482 2483
    storageDriverUnlock(driver);

2484
    if (!pool) {
2485
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2486 2487
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2488
        goto cleanup;
2489 2490 2491
    }

    if (!virStoragePoolObjIsActive(pool)) {
2492
        virReportError(VIR_ERR_OPERATION_INVALID,
2493
                       _("storage pool '%s' is not active"), pool->def->name);
2494
        goto cleanup;
2495 2496 2497 2498 2499
    }

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

    if (!vol) {
2500 2501 2502
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2503
        goto cleanup;
2504 2505
    }

2506 2507 2508
    if (virStorageVolGetXMLDescEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2509
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2510
        goto cleanup;
2511 2512 2513 2514

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

2516
    ret = virStorageVolDefFormat(pool->def, vol);
2517 2518

cleanup:
2519 2520 2521
    if (pool)
        virStoragePoolObjUnlock(pool);

2522
    return ret;
2523 2524 2525
}

static char *
2526
storageVolGetPath(virStorageVolPtr obj) {
2527
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
2528
    virStoragePoolObjPtr pool;
2529
    virStorageVolDefPtr vol;
2530
    char *ret = NULL;
2531

2532 2533 2534
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
    storageDriverUnlock(driver);
2535
    if (!pool) {
2536
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2537 2538
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2539
        goto cleanup;
2540 2541 2542
    }

    if (!virStoragePoolObjIsActive(pool)) {
2543
        virReportError(VIR_ERR_OPERATION_INVALID,
2544
                       _("storage pool '%s' is not active"), pool->def->name);
2545
        goto cleanup;
2546 2547 2548 2549 2550
    }

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

    if (!vol) {
2551 2552 2553
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2554
        goto cleanup;
2555 2556
    }

2557 2558 2559
    if (virStorageVolGetPathEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2560
    ignore_value(VIR_STRDUP(ret, vol->target.path));
2561 2562

cleanup:
2563 2564
    if (pool)
        virStoragePoolObjUnlock(pool);
2565 2566 2567
    return ret;
}

2568
static int
2569 2570 2571
storageConnectListAllStoragePools(virConnectPtr conn,
                                  virStoragePoolPtr **pools,
                                  unsigned int flags)
2572 2573 2574 2575 2576 2577
{
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

2578 2579 2580
    if (virConnectListAllStoragePoolsEnsureACL(conn) < 0)
        goto cleanup;

2581
    storageDriverLock(driver);
2582 2583
    ret = virStoragePoolObjListExport(conn, driver->pools, pools,
                                      virConnectListAllStoragePoolsCheckACL, flags);
2584 2585
    storageDriverUnlock(driver);

2586
cleanup:
2587 2588 2589
    return ret;
}

2590
static virStorageDriver storageDriver = {
2591
    .name = "storage",
2592 2593
    .storageOpen = storageOpen, /* 0.4.0 */
    .storageClose = storageClose, /* 0.4.0 */
2594 2595 2596 2597 2598 2599
    .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 */
2600 2601 2602
    .storagePoolLookupByName = storagePoolLookupByName, /* 0.4.0 */
    .storagePoolLookupByUUID = storagePoolLookupByUUID, /* 0.4.0 */
    .storagePoolLookupByVolume = storagePoolLookupByVolume, /* 0.4.0 */
2603 2604
    .storagePoolCreateXML = storagePoolCreateXML, /* 0.4.0 */
    .storagePoolDefineXML = storagePoolDefineXML, /* 0.4.0 */
2605 2606
    .storagePoolBuild = storagePoolBuild, /* 0.4.0 */
    .storagePoolUndefine = storagePoolUndefine, /* 0.4.0 */
2607
    .storagePoolCreate = storagePoolCreate, /* 0.4.0 */
2608 2609 2610 2611 2612 2613 2614
    .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 */
2615
    .storagePoolNumOfVolumes = storagePoolNumOfVolumes, /* 0.4.0 */
2616 2617 2618
    .storagePoolListVolumes = storagePoolListVolumes, /* 0.4.0 */
    .storagePoolListAllVolumes = storagePoolListAllVolumes, /* 0.10.2 */

2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632
    .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 */
2633 2634 2635

    .storagePoolIsActive = storagePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = storagePoolIsPersistent, /* 0.7.3 */
2636 2637 2638 2639
};


static virStateDriver stateDriver = {
2640
    .name = "Storage",
2641
    .stateInitialize = storageStateInitialize,
2642
    .stateAutoStart = storageStateAutoStart,
2643 2644
    .stateCleanup = storageStateCleanup,
    .stateReload = storageStateReload,
2645 2646 2647 2648 2649 2650 2651
};

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