storage_driver.c 74.7 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 1454
            const char *stable_path;

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

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

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

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

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

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

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

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

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

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

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

1556
    if (backend->createVol(obj->conn, pool, voldef) < 0) {
1557
        goto cleanup;
1558 1559
    }

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

1568
    if (backend->buildVol) {
1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587
        int buildret;
        virStorageVolDefPtr buildvoldef = NULL;

        if (VIR_ALLOC(buildvoldef) < 0) {
            voldef = NULL;
            goto cleanup;
        }

        /* Make a shallow copy of the 'defined' volume definition, since the
         * original allocation value will change as the user polls 'info',
         * but we only need the initial requested values
         */
        memcpy(buildvoldef, voldef, sizeof(*voldef));

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

1588
        buildret = backend->buildVol(obj->conn, pool, buildvoldef, flags);
1589

1590
        storageDriverLock(driver);
1591
        virStoragePoolObjLock(pool);
1592 1593
        storageDriverUnlock(driver);

1594 1595 1596 1597 1598 1599 1600 1601
        voldef->building = 0;
        pool->asyncjobs--;

        voldef = NULL;
        VIR_FREE(buildvoldef);

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

    }

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

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

1623
static virStorageVolPtr
1624 1625 1626 1627
storageVolCreateXMLFrom(virStoragePoolPtr obj,
                        const char *xmldesc,
                        virStorageVolPtr vobj,
                        unsigned int flags)
E
Eric Blake 已提交
1628
{
1629 1630 1631 1632 1633
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool, origpool = NULL;
    virStorageBackendPtr backend;
    virStorageVolDefPtr origvol = NULL, newvol = NULL;
    virStorageVolPtr ret = NULL, volobj = NULL;
1634
    int buildret;
1635

1636
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
E
Eric Blake 已提交
1637

1638 1639
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1640
    if (pool && STRNEQ(obj->name, vobj->pool)) {
1641
        virStoragePoolObjUnlock(pool);
1642
        origpool = virStoragePoolObjFindByName(&driver->pools, vobj->pool);
1643
        virStoragePoolObjLock(pool);
1644
    }
1645 1646
    storageDriverUnlock(driver);
    if (!pool) {
1647
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1648
                       _("no storage pool with matching uuid %s"), obj->uuid);
1649 1650 1651
        goto cleanup;
    }

1652
    if (STRNEQ(obj->name, vobj->pool) && !origpool) {
1653 1654 1655
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       vobj->pool);
1656 1657 1658 1659
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1660
        virReportError(VIR_ERR_OPERATION_INVALID,
1661
                       _("storage pool '%s' is not active"), pool->def->name);
1662 1663 1664
        goto cleanup;
    }

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

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

1675
    origvol = virStorageVolDefFindByName(origpool ? origpool : pool, vobj->name);
1676
    if (!origvol) {
1677 1678 1679
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vobj->name);
1680 1681 1682
        goto cleanup;
    }

1683
    newvol = virStorageVolDefParseString(pool->def, xmldesc);
1684 1685 1686
    if (newvol == NULL)
        goto cleanup;

1687 1688 1689
    if (virStorageVolCreateXMLFromEnsureACL(obj->conn, pool->def, newvol) < 0)
        goto cleanup;

1690
    if (virStorageVolDefFindByName(pool, newvol->name)) {
1691 1692 1693
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("storage volume name '%s' already in use."),
                       newvol->name);
1694 1695 1696 1697 1698 1699 1700
        goto cleanup;
    }

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

1701 1702 1703 1704 1705
    /* 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;

1706
    if (!backend->buildVolFrom) {
1707 1708
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("storage pool does not support volume creation from an existing volume"));
1709 1710 1711 1712
        goto cleanup;
    }

    if (origvol->building) {
1713 1714 1715
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       origvol->name);
1716 1717 1718 1719 1720 1721 1722 1723
        goto cleanup;
    }

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

    if (VIR_REALLOC_N(pool->volumes.objs,
1724
                      pool->volumes.count+1) < 0)
1725 1726 1727 1728 1729 1730 1731 1732 1733
        goto cleanup;

    /* 'Define' the new volume so we get async progress reporting */
    if (backend->createVol(obj->conn, pool, newvol) < 0) {
        goto cleanup;
    }

    pool->volumes.objs[pool->volumes.count++] = newvol;
    volobj = virGetStorageVol(obj->conn, pool->def->name, newvol->name,
1734
                              newvol->key, NULL, NULL);
1735 1736 1737 1738 1739 1740 1741

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

1742
    if (origpool) {
1743 1744 1745 1746
        origpool->asyncjobs++;
        virStoragePoolObjUnlock(origpool);
    }

1747
    buildret = backend->buildVolFrom(obj->conn, pool, newvol, origvol, flags);
1748 1749 1750

    storageDriverLock(driver);
    virStoragePoolObjLock(pool);
1751
    if (origpool)
1752 1753 1754 1755 1756 1757 1758 1759
        virStoragePoolObjLock(origpool);
    storageDriverUnlock(driver);

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

1760
    if (origpool) {
1761 1762 1763 1764 1765 1766 1767
        origpool->asyncjobs--;
        virStoragePoolObjUnlock(origpool);
        origpool = NULL;
    }

    if (buildret < 0) {
        virStoragePoolObjUnlock(pool);
1768
        storageVolDelete(volobj, 0);
1769 1770 1771 1772
        pool = NULL;
        goto cleanup;
    }

1773
    VIR_INFO("Creating volume '%s' in storage pool '%s'",
1774
             volobj->name, pool->def->name);
1775 1776 1777 1778
    ret = volobj;
    volobj = NULL;

cleanup:
1779
    virObjectUnref(volobj);
1780 1781 1782
    virStorageVolDefFree(newvol);
    if (pool)
        virStoragePoolObjUnlock(pool);
1783
    if (origpool)
1784 1785 1786 1787
        virStoragePoolObjUnlock(origpool);
    return ret;
}

1788

1789
static int
1790 1791 1792 1793 1794
storageVolDownload(virStorageVolPtr obj,
                   virStreamPtr stream,
                   unsigned long long offset,
                   unsigned long long length,
                   unsigned int flags)
1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807
{
    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) {
1808
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1809 1810
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1811 1812 1813 1814
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1815
        virReportError(VIR_ERR_OPERATION_INVALID,
1816
                       _("storage pool '%s' is not active"), pool->def->name);
1817 1818 1819 1820 1821 1822
        goto out;
    }

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

    if (vol == NULL) {
1823 1824 1825
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1826 1827 1828
        goto out;
    }

1829 1830 1831
    if (virStorageVolDownloadEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

1832
    if (vol->building) {
1833 1834 1835
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1836 1837 1838 1839 1840 1841
        goto out;
    }

    if (virFDStreamOpenFile(stream,
                            vol->target.path,
                            offset, length,
E
Eric Blake 已提交
1842
                            O_RDONLY) < 0)
1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855
        goto out;

    ret = 0;

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}


static int
1856 1857 1858 1859 1860
storageVolUpload(virStorageVolPtr obj,
                 virStreamPtr stream,
                 unsigned long long offset,
                 unsigned long long length,
                 unsigned int flags)
1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873
{
    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) {
1874
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1875 1876
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1877 1878 1879 1880
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1881
        virReportError(VIR_ERR_OPERATION_INVALID,
1882
                       _("storage pool '%s' is not active"), pool->def->name);
1883 1884 1885 1886 1887 1888
        goto out;
    }

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

    if (vol == NULL) {
1889 1890 1891
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1892 1893 1894
        goto out;
    }

1895 1896 1897
    if (virStorageVolUploadEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

1898
    if (vol->building) {
1899 1900 1901
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1902 1903 1904 1905 1906 1907 1908 1909
        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 已提交
1910
                            O_WRONLY) < 0)
1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921
        goto out;

    ret = 0;

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}

1922
static int
1923 1924 1925
storageVolResize(virStorageVolPtr obj,
                 unsigned long long capacity,
                 unsigned int flags)
1926 1927 1928 1929 1930 1931 1932 1933
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStorageBackendPtr backend;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    unsigned long long abs_capacity;
    int ret = -1;

1934
    virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE |
1935 1936
                  VIR_STORAGE_VOL_RESIZE_DELTA |
                  VIR_STORAGE_VOL_RESIZE_SHRINK, -1);
1937 1938 1939 1940 1941 1942

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

    if (!pool) {
1943 1944 1945
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1946 1947 1948 1949
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1950 1951
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->def->name);
1952 1953 1954 1955 1956 1957 1958 1959 1960
        goto out;
    }

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

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

    if (vol == NULL) {
1961 1962 1963
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1964 1965 1966
        goto out;
    }

1967 1968 1969
    if (virStorageVolResizeEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

1970
    if (vol->building) {
1971 1972 1973
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1974 1975
        goto out;
    }
1976

1977 1978 1979 1980 1981 1982 1983 1984
    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) {
1985
        virReportError(VIR_ERR_INVALID_ARG, "%s",
1986 1987
                       _("can't shrink capacity below "
                         "existing allocation"));
1988 1989 1990
        goto out;
    }

1991 1992 1993 1994 1995 1996 1997 1998
    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;
    }

1999
    if (abs_capacity > vol->capacity + pool->def->available) {
2000
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
2001
                       _("Not enough space left on storage pool"));
2002 2003 2004 2005
        goto out;
    }

    if (!backend->resizeVol) {
2006
        virReportError(VIR_ERR_NO_SUPPORT, "%s",
2007 2008
                       _("storage pool does not support changing of "
                         "volume capacity"));
2009 2010 2011 2012 2013 2014
        goto out;
    }

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

O
Osier Yang 已提交
2015 2016
    vol->capacity = abs_capacity;
    ret = 0;
2017 2018 2019 2020 2021 2022 2023

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
2024

2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039
/* 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
2040 2041 2042
storageVolZeroSparseFile(virStorageVolDefPtr vol,
                         off_t size,
                         int fd)
2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058
{
    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 "
2059
                               "path '%s' to %ju bytes"),
E
Eric Blake 已提交
2060
                             vol->target.path, (uintmax_t)size);
2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081
    }

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 已提交
2082
              (uintmax_t)extent_start, (uintmax_t)extent_length);
2083 2084 2085 2086 2087

    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 已提交
2088
                             (uintmax_t)extent_start, vol->target.path);
2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109
        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;
    }

2110 2111 2112 2113 2114 2115 2116 2117
    if (fdatasync(fd) < 0) {
        ret = -errno;
        virReportSystemError(errno,
                             _("cannot sync data to volume with path '%s'"),
                             vol->target.path);
        goto out;
    }

2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128
    VIR_DEBUG("Wrote %zu bytes to volume with path '%s'",
              *bytes_wiped, vol->target.path);

    ret = 0;

out:
    return ret;
}


static int
2129 2130
storageVolWipeInternal(virStorageVolDefPtr def,
                       unsigned int algorithm)
2131 2132 2133 2134 2135
{
    int ret = -1, fd = -1;
    struct stat st;
    char *writebuf = NULL;
    size_t bytes_wiped = 0;
2136
    virCommandPtr cmd = NULL;
2137

2138 2139
    VIR_DEBUG("Wiping volume with path '%s' and algorithm %u",
              def->target.path, algorithm);
2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155

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

2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171
    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 已提交
2172
            alg_char = "schneier";
2173 2174 2175 2176 2177
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7:
            alg_char = "pfitzner7";
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33:
M
Michal Privoznik 已提交
2178
            alg_char = "pfitzner33";
2179 2180 2181 2182 2183
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_RANDOM:
            alg_char = "random";
            break;
        default:
2184 2185 2186
            virReportError(VIR_ERR_INVALID_ARG,
                           _("unsupported algorithm %d"),
                           algorithm);
2187 2188 2189 2190
        }
        cmd = virCommandNew(SCRUB);
        virCommandAddArgList(cmd, "-f", "-p", alg_char,
                             def->target.path, NULL);
2191

2192
        if (virCommandRun(cmd, NULL) < 0)
2193 2194
            goto out;

2195 2196 2197 2198
        ret = 0;
        goto out;
    } else {
        if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) {
2199
            ret = storageVolZeroSparseFile(def, st.st_size, fd);
2200 2201
        } else {

2202
            if (VIR_ALLOC_N(writebuf, st.st_blksize) < 0)
2203 2204 2205 2206 2207 2208 2209 2210 2211 2212
                goto out;

            ret = storageWipeExtent(def,
                                    fd,
                                    0,
                                    def->allocation,
                                    writebuf,
                                    st.st_blksize,
                                    &bytes_wiped);
        }
2213 2214 2215
    }

out:
2216
    virCommandFree(cmd);
2217
    VIR_FREE(writebuf);
2218
    VIR_FORCE_CLOSE(fd);
2219 2220 2221 2222 2223
    return ret;
}


static int
2224 2225 2226
storageVolWipePattern(virStorageVolPtr obj,
                      unsigned int algorithm,
                      unsigned int flags)
2227 2228 2229 2230 2231 2232
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    int ret = -1;

2233
    virCheckFlags(0, -1);
2234

2235
    if (algorithm >= VIR_STORAGE_VOL_WIPE_ALG_LAST) {
2236 2237 2238
        virReportError(VIR_ERR_INVALID_ARG,
                       _("wiping algorithm %d not supported"),
                       algorithm);
2239 2240 2241
        return -1;
    }

2242 2243 2244 2245 2246
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
    storageDriverUnlock(driver);

    if (!pool) {
2247
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2248 2249
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2250 2251 2252 2253
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
2254
        virReportError(VIR_ERR_OPERATION_INVALID,
2255
                       _("storage pool '%s' is not active"), pool->def->name);
2256 2257 2258 2259 2260 2261
        goto out;
    }

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

    if (vol == NULL) {
2262 2263 2264
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2265 2266 2267
        goto out;
    }

2268 2269 2270
    if (virStorageVolWipePatternEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

2271
    if (vol->building) {
2272 2273 2274
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
2275 2276 2277
        goto out;
    }

2278
    if (storageVolWipeInternal(vol, algorithm) == -1) {
2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292
        goto out;
    }

    ret = 0;

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

    return ret;

}

2293
static int
2294 2295
storageVolWipe(virStorageVolPtr obj,
               unsigned int flags)
2296
{
2297
    return storageVolWipePattern(obj, VIR_STORAGE_VOL_WIPE_ALG_ZERO, flags);
2298 2299
}

2300
static int
2301 2302
storageVolDelete(virStorageVolPtr obj,
                 unsigned int flags) {
2303 2304
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2305
    virStorageBackendPtr backend;
2306
    virStorageVolDefPtr vol = NULL;
2307
    size_t i;
2308
    int ret = -1;
2309

2310
    storageDriverLock(driver);
2311
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2312 2313
    storageDriverUnlock(driver);

2314
    if (!pool) {
2315
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2316 2317
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2318
        goto cleanup;
2319 2320 2321
    }

    if (!virStoragePoolObjIsActive(pool)) {
2322
        virReportError(VIR_ERR_OPERATION_INVALID,
2323
                       _("storage pool '%s' is not active"), pool->def->name);
2324
        goto cleanup;
2325 2326 2327
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2328
        goto cleanup;
2329 2330 2331 2332

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

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

2339 2340 2341
    if (virStorageVolDeleteEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

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

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

2353
        goto cleanup;
2354 2355
    }

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

2359
    for (i = 0; i < pool->volumes.count; i++) {
2360
        if (pool->volumes.objs[i] == vol) {
2361
            VIR_INFO("Deleting volume '%s' from storage pool '%s'",
2362
                     vol->name, pool->def->name);
2363
            virStorageVolDefFree(vol);
2364
            vol = NULL;
2365 2366 2367 2368 2369 2370 2371 2372 2373 2374

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

2375 2376 2377
            break;
        }
    }
2378
    ret = 0;
2379

2380
cleanup:
2381 2382
    if (pool)
        virStoragePoolObjUnlock(pool);
2383
    return ret;
2384 2385 2386
}

static int
2387 2388
storageVolGetInfo(virStorageVolPtr obj,
                  virStorageVolInfoPtr info) {
2389 2390
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2391 2392
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
2393
    int ret = -1;
2394

2395
    storageDriverLock(driver);
2396
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2397 2398
    storageDriverUnlock(driver);

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

    if (!virStoragePoolObjIsActive(pool)) {
2407
        virReportError(VIR_ERR_OPERATION_INVALID,
2408
                       _("storage pool '%s' is not active"), pool->def->name);
2409
        goto cleanup;
2410 2411 2412 2413 2414
    }

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

    if (!vol) {
2415 2416 2417
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2418
        goto cleanup;
2419 2420
    }

2421 2422 2423
    if (virStorageVolGetInfoEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2424
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2425
        goto cleanup;
2426 2427 2428

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

    memset(info, 0, sizeof(*info));
2432
    info->type = vol->type;
2433 2434
    info->capacity = vol->capacity;
    info->allocation = vol->allocation;
2435
    ret = 0;
2436

2437
cleanup:
2438 2439
    if (pool)
        virStoragePoolObjUnlock(pool);
2440
    return ret;
2441 2442 2443
}

static char *
2444 2445
storageVolGetXMLDesc(virStorageVolPtr obj,
                     unsigned int flags)
E
Eric Blake 已提交
2446
{
2447 2448
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2449 2450
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
2451
    char *ret = NULL;
2452

E
Eric Blake 已提交
2453 2454
    virCheckFlags(0, NULL);

2455
    storageDriverLock(driver);
2456
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2457 2458
    storageDriverUnlock(driver);

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

    if (!virStoragePoolObjIsActive(pool)) {
2467
        virReportError(VIR_ERR_OPERATION_INVALID,
2468
                       _("storage pool '%s' is not active"), pool->def->name);
2469
        goto cleanup;
2470 2471 2472 2473 2474
    }

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

    if (!vol) {
2475 2476 2477
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2478
        goto cleanup;
2479 2480
    }

2481 2482 2483
    if (virStorageVolGetXMLDescEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2484
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2485
        goto cleanup;
2486 2487 2488 2489

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

2491
    ret = virStorageVolDefFormat(pool->def, vol);
2492 2493

cleanup:
2494 2495 2496
    if (pool)
        virStoragePoolObjUnlock(pool);

2497
    return ret;
2498 2499 2500
}

static char *
2501
storageVolGetPath(virStorageVolPtr obj) {
2502
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
2503
    virStoragePoolObjPtr pool;
2504
    virStorageVolDefPtr vol;
2505
    char *ret = NULL;
2506

2507 2508 2509
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
    storageDriverUnlock(driver);
2510
    if (!pool) {
2511
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2512 2513
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2514
        goto cleanup;
2515 2516 2517
    }

    if (!virStoragePoolObjIsActive(pool)) {
2518
        virReportError(VIR_ERR_OPERATION_INVALID,
2519
                       _("storage pool '%s' is not active"), pool->def->name);
2520
        goto cleanup;
2521 2522 2523 2524 2525
    }

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

    if (!vol) {
2526 2527 2528
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2529
        goto cleanup;
2530 2531
    }

2532 2533 2534
    if (virStorageVolGetPathEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2535
    ignore_value(VIR_STRDUP(ret, vol->target.path));
2536 2537

cleanup:
2538 2539
    if (pool)
        virStoragePoolObjUnlock(pool);
2540 2541 2542
    return ret;
}

2543
static int
2544 2545 2546
storageConnectListAllStoragePools(virConnectPtr conn,
                                  virStoragePoolPtr **pools,
                                  unsigned int flags)
2547 2548 2549 2550 2551 2552
{
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

2553 2554 2555
    if (virConnectListAllStoragePoolsEnsureACL(conn) < 0)
        goto cleanup;

2556
    storageDriverLock(driver);
2557 2558
    ret = virStoragePoolObjListExport(conn, driver->pools, pools,
                                      virConnectListAllStoragePoolsCheckACL, flags);
2559 2560
    storageDriverUnlock(driver);

2561
cleanup:
2562 2563 2564
    return ret;
}

2565
static virStorageDriver storageDriver = {
2566
    .name = "storage",
2567 2568
    .storageOpen = storageOpen, /* 0.4.0 */
    .storageClose = storageClose, /* 0.4.0 */
2569 2570 2571 2572 2573 2574
    .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 */
2575 2576 2577
    .storagePoolLookupByName = storagePoolLookupByName, /* 0.4.0 */
    .storagePoolLookupByUUID = storagePoolLookupByUUID, /* 0.4.0 */
    .storagePoolLookupByVolume = storagePoolLookupByVolume, /* 0.4.0 */
2578 2579
    .storagePoolCreateXML = storagePoolCreateXML, /* 0.4.0 */
    .storagePoolDefineXML = storagePoolDefineXML, /* 0.4.0 */
2580 2581
    .storagePoolBuild = storagePoolBuild, /* 0.4.0 */
    .storagePoolUndefine = storagePoolUndefine, /* 0.4.0 */
2582
    .storagePoolCreate = storagePoolCreate, /* 0.4.0 */
2583 2584 2585 2586 2587 2588 2589
    .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 */
2590
    .storagePoolNumOfVolumes = storagePoolNumOfVolumes, /* 0.4.0 */
2591 2592 2593
    .storagePoolListVolumes = storagePoolListVolumes, /* 0.4.0 */
    .storagePoolListAllVolumes = storagePoolListAllVolumes, /* 0.10.2 */

2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607
    .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 */
2608 2609 2610

    .storagePoolIsActive = storagePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = storagePoolIsPersistent, /* 0.7.3 */
2611 2612 2613 2614
};


static virStateDriver stateDriver = {
2615
    .name = "Storage",
2616
    .stateInitialize = storageStateInitialize,
2617
    .stateAutoStart = storageStateAutoStart,
2618 2619
    .stateCleanup = storageStateCleanup,
    .stateReload = storageStateReload,
2620 2621 2622 2623 2624 2625 2626
};

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