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_STORAGE_VOL_EXIST,
1542
                       _("'%s'"), 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
    if (flags & VIR_STORAGE_VOL_RESIZE_ALLOCATE)
        vol->allocation = abs_capacity;
2034 2035 2036 2037 2038

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

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

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
2047

2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062
/* 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
2063 2064 2065
storageVolZeroSparseFile(virStorageVolDefPtr vol,
                         off_t size,
                         int fd)
2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081
{
    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 "
2082
                               "path '%s' to %ju bytes"),
E
Eric Blake 已提交
2083
                             vol->target.path, (uintmax_t)size);
2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104
    }

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 已提交
2105
              (uintmax_t)extent_start, (uintmax_t)extent_length);
2106 2107 2108 2109 2110

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

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

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

    ret = 0;

out:
    return ret;
}


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

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

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

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

2215
        if (virCommandRun(cmd, NULL) < 0)
2216 2217
            goto out;

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

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

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

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


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

2256
    virCheckFlags(0, -1);
2257

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

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

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

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

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

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

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

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

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

    ret = 0;

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

    return ret;

}

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

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

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

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

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

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

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

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

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

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

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

2376
        goto cleanup;
2377 2378
    }

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

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

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

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

2402 2403 2404
            break;
        }
    }
2405
    ret = 0;
2406

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

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

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

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

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

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

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

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

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

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

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

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

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

E
Eric Blake 已提交
2480 2481
    virCheckFlags(0, NULL);

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

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

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

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

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

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

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

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

2518
    ret = virStorageVolDefFormat(pool->def, vol);
2519 2520

cleanup:
2521 2522 2523
    if (pool)
        virStoragePoolObjUnlock(pool);

2524
    return ret;
2525 2526 2527
}

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

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

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

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

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

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

2562
    ignore_value(VIR_STRDUP(ret, vol->target.path));
2563 2564

cleanup:
2565 2566
    if (pool)
        virStoragePoolObjUnlock(pool);
2567 2568 2569
    return ret;
}

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

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

2580 2581 2582
    if (virConnectListAllStoragePoolsEnsureACL(conn) < 0)
        goto cleanup;

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

2588
cleanup:
2589 2590 2591
    return ret;
}

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

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

    .storagePoolIsActive = storagePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = storagePoolIsPersistent, /* 0.7.3 */
2638 2639 2640 2641
};


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

2649 2650 2651 2652
int storageRegister(void)
{
    if (virRegisterStorageDriver(&storageDriver) < 0)
        return -1;
2653 2654 2655
    virRegisterStateDriver(&stateDriver);
    return 0;
}