storage_driver.c 74.1 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
    for (i = 0; i < driver->pools.count; i++) {
73
        virStoragePoolObjPtr pool = driver->pools.objs[i];
74 75
        virStorageBackendPtr backend;
        bool started = false;
76

77
        virStoragePoolObjLock(pool);
78 79 80 81 82
        if ((backend = virStorageBackendForType(pool->def->type)) == NULL) {
            VIR_ERROR(_("Missing backend %d"), pool->def->type);
            virStoragePoolObjUnlock(pool);
            continue;
        }
83

84 85 86 87 88 89 90 91 92 93 94 95 96
        if (backend->checkPool &&
            backend->checkPool(NULL, pool, &started) < 0) {
            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)) {
97 98 99
            if (backend->startPool &&
                backend->startPool(NULL, pool) < 0) {
                virErrorPtr err = virGetLastError();
100
                VIR_ERROR(_("Failed to autostart storage pool '%s': %s"),
101
                          pool->def->name, err ? err->message :
102
                          _("no error message found"));
103
                virStoragePoolObjUnlock(pool);
104 105
                continue;
            }
106 107
            started = true;
        }
108

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

/**
 * virStorageStartup:
 *
 * Initialization function for the QEmu daemon
 */
static int
132 133 134
storageStateInitialize(bool privileged,
                       virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                       void *opaque ATTRIBUTE_UNUSED)
135
{
136 137
    char *base = NULL;

138
    if (VIR_ALLOC(driverState) < 0)
139 140
        return -1;

141 142 143 144
    if (virMutexInit(&driverState->lock) < 0) {
        VIR_FREE(driverState);
        return -1;
    }
145 146
    storageDriverLock(driverState);

147
    if (privileged) {
148 149
        if (VIR_STRDUP(base, SYSCONFDIR "/libvirt") < 0)
            goto error;
150
    } else {
151
        base = virGetUserConfigDirectory();
152
        if (!base)
153
            goto error;
154 155
    }

156
    /* Configuration paths are either $USER_CONFIG_HOME/libvirt/storage/... (session) or
157 158
     * /etc/libvirt/storage/... (system).
     */
159 160
    if (virAsprintf(&driverState->configDir,
                    "%s/storage", base) == -1)
161
        goto error;
162

163 164
    if (virAsprintf(&driverState->autostartDir,
                    "%s/storage/autostart", base) == -1)
165
        goto error;
166

167
    VIR_FREE(base);
168

169
    if (virStoragePoolLoadAllConfigs(&driverState->pools,
170
                                     driverState->configDir,
171 172
                                     driverState->autostartDir) < 0)
        goto error;
173 174
    storageDriverAutostart(driverState);

175
    storageDriverUnlock(driverState);
176 177
    return 0;

178 179 180
error:
    VIR_FREE(base);
    storageDriverUnlock(driverState);
181
    storageStateCleanup();
182 183 184 185
    return -1;
}

/**
186
 * storageStateReload:
187 188 189 190 191
 *
 * Function to restart the storage driver, it will recheck the configuration
 * files and update its state
 */
static int
192
storageStateReload(void) {
193 194 195
    if (!driverState)
        return -1;

196
    storageDriverLock(driverState);
197
    virStoragePoolLoadAllConfigs(&driverState->pools,
198 199
                                 driverState->configDir,
                                 driverState->autostartDir);
200
    storageDriverAutostart(driverState);
201
    storageDriverUnlock(driverState);
202 203 204 205 206 207

    return 0;
}


/**
208
 * storageStateCleanup
209 210 211 212
 *
 * Shutdown the storage driver, it will stop all active storage pools
 */
static int
213
storageStateCleanup(void) {
214 215 216
    if (!driverState)
        return -1;

217
    storageDriverLock(driverState);
218 219

    /* free inactive pools */
220 221 222 223
    virStoragePoolObjListFree(&driverState->pools);

    VIR_FREE(driverState->configDir);
    VIR_FREE(driverState->autostartDir);
224
    storageDriverUnlock(driverState);
225
    virMutexDestroy(&driverState->lock);
226
    VIR_FREE(driverState);
227 228 229 230 231 232 233 234 235

    return 0;
}



static virStoragePoolPtr
storagePoolLookupByUUID(virConnectPtr conn,
                        const unsigned char *uuid) {
236 237 238
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
239

240
    storageDriverLock(driver);
241
    pool = virStoragePoolObjFindByUUID(&driver->pools, uuid);
242 243
    storageDriverUnlock(driver);

244
    if (!pool) {
245
        virReportError(VIR_ERR_NO_STORAGE_POOL,
246
                       _("no storage pool with matching uuid %s"), uuid);
247
        goto cleanup;
248 249
    }

250 251 252
    if (virStoragePoolLookupByUUIDEnsureACL(conn, pool->def) < 0)
        goto cleanup;

253 254
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
255 256

cleanup:
257 258
    if (pool)
        virStoragePoolObjUnlock(pool);
259 260 261 262 263 264
    return ret;
}

static virStoragePoolPtr
storagePoolLookupByName(virConnectPtr conn,
                        const char *name) {
265 266 267
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    virStoragePoolPtr ret = NULL;
268

269
    storageDriverLock(driver);
270
    pool = virStoragePoolObjFindByName(&driver->pools, name);
271 272
    storageDriverUnlock(driver);

273
    if (!pool) {
274
        virReportError(VIR_ERR_NO_STORAGE_POOL,
275
                       _("no storage pool with matching name '%s'"), name);
276
        goto cleanup;
277 278
    }

279 280 281
    if (virStoragePoolLookupByNameEnsureACL(conn, pool->def) < 0)
        goto cleanup;

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

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

static virStoragePoolPtr
storagePoolLookupByVolume(virStorageVolPtr vol) {
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
    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;
317 318 319 320 321
}

static virDrvOpenStatus
storageOpen(virConnectPtr conn,
            virConnectAuthPtr auth ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
322 323 324 325
            unsigned int flags)
{
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

326 327 328 329 330 331 332 333 334 335 336 337 338 339
    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
340
storageConnectNumOfStoragePools(virConnectPtr conn) {
341
    virStorageDriverStatePtr driver = conn->storagePrivateData;
342 343
    size_t i;
    int nactive = 0;
344

345 346 347
    if (virConnectNumOfStoragePoolsEnsureACL(conn) < 0)
        return -1;

348
    storageDriverLock(driver);
349
    for (i = 0; i < driver->pools.count; i++) {
350 351 352 353
        virStoragePoolObjPtr obj = driver->pools.objs[i];
        virStoragePoolObjLock(obj);
        if (virConnectNumOfStoragePoolsCheckACL(conn, obj->def) &&
            virStoragePoolObjIsActive(obj))
354
            nactive++;
355
        virStoragePoolObjUnlock(obj);
356 357
    }
    storageDriverUnlock(driver);
358 359

    return nactive;
360 361 362
}

static int
363 364 365
storageConnectListStoragePools(virConnectPtr conn,
                               char **const names,
                               int nnames) {
366
    virStorageDriverStatePtr driver = conn->storagePrivateData;
367 368
    int got = 0;
    size_t i;
369

370 371 372
    if (virConnectListStoragePoolsEnsureACL(conn) < 0)
        return -1;

373
    storageDriverLock(driver);
374
    for (i = 0; i < driver->pools.count && got < nnames; i++) {
375 376 377 378 379 380
        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);
381 382 383 384
                goto cleanup;
            }
            got++;
        }
385
        virStoragePoolObjUnlock(obj);
386
    }
387
    storageDriverUnlock(driver);
388 389 390
    return got;

 cleanup:
391
    storageDriverUnlock(driver);
392
    for (i = 0; i < got; i++)
393
        VIR_FREE(names[i]);
394
    memset(names, 0, nnames * sizeof(*names));
395 396 397 398
    return -1;
}

static int
399
storageConnectNumOfDefinedStoragePools(virConnectPtr conn) {
400
    virStorageDriverStatePtr driver = conn->storagePrivateData;
401 402
    size_t i;
    int nactive = 0;
403

404 405 406
    if (virConnectNumOfDefinedStoragePoolsEnsureACL(conn) < 0)
        return -1;

407
    storageDriverLock(driver);
408
    for (i = 0; i < driver->pools.count; i++) {
409 410 411 412
        virStoragePoolObjPtr obj = driver->pools.objs[i];
        virStoragePoolObjLock(obj);
        if (virConnectNumOfDefinedStoragePoolsCheckACL(conn, obj->def) &&
            !virStoragePoolObjIsActive(obj))
413
            nactive++;
414
        virStoragePoolObjUnlock(obj);
415 416
    }
    storageDriverUnlock(driver);
417 418

    return nactive;
419 420 421
}

static int
422 423 424
storageConnectListDefinedStoragePools(virConnectPtr conn,
                                      char **const names,
                                      int nnames) {
425
    virStorageDriverStatePtr driver = conn->storagePrivateData;
426 427
    int got = 0;
    size_t i;
428

429 430 431
    if (virConnectListDefinedStoragePoolsEnsureACL(conn) < 0)
        return -1;

432
    storageDriverLock(driver);
433
    for (i = 0; i < driver->pools.count && got < nnames; i++) {
434 435 436 437 438 439
        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);
440 441 442 443
                goto cleanup;
            }
            got++;
        }
444
        virStoragePoolObjUnlock(obj);
445
    }
446
    storageDriverUnlock(driver);
447 448 449
    return got;

 cleanup:
450
    storageDriverUnlock(driver);
451
    for (i = 0; i < got; i++) {
452
        VIR_FREE(names[i]);
453
    }
454
    memset(names, 0, nnames * sizeof(*names));
455 456 457
    return -1;
}

458 459
/* This method is required to be re-entrant / thread safe, so
   uses no driver lock */
460
static char *
461 462 463 464
storageConnectFindStoragePoolSources(virConnectPtr conn,
                                     const char *type,
                                     const char *srcSpec,
                                     unsigned int flags)
465 466 467
{
    int backend_type;
    virStorageBackendPtr backend;
468
    char *ret = NULL;
469

470 471 472
    if (virConnectFindStoragePoolSourcesEnsureACL(conn) < 0)
        return NULL;

473
    backend_type = virStoragePoolTypeFromString(type);
474
    if (backend_type < 0) {
475 476
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
477
        goto cleanup;
478
    }
479 480 481

    backend = virStorageBackendForType(backend_type);
    if (backend == NULL)
482
        goto cleanup;
483

484
    if (!backend->findPoolSources) {
485 486 487
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source "
                         "discovery"), type);
488 489 490 491
        goto cleanup;
    }

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

493 494
cleanup:
    return ret;
495 496 497
}


498
static int storagePoolIsActive(virStoragePoolPtr pool)
499
{
500
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
501 502 503 504
    virStoragePoolObjPtr obj;
    int ret = -1;

    storageDriverLock(driver);
505
    obj = virStoragePoolObjFindByUUID(&driver->pools, pool->uuid);
506 507
    storageDriverUnlock(driver);
    if (!obj) {
508
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
509 510
        goto cleanup;
    }
511 512 513 514

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

515 516 517 518 519 520 521 522
    ret = virStoragePoolObjIsActive(obj);

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

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

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

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

540 541 542 543 544 545 546 547 548
    ret = obj->configFile ? 1 : 0;

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


549
static virStoragePoolPtr
550 551 552
storagePoolCreateXML(virConnectPtr conn,
                     const char *xml,
                     unsigned int flags)
E
Eric Blake 已提交
553
{
554
    virStorageDriverStatePtr driver = conn->storagePrivateData;
555
    virStoragePoolDefPtr def;
556
    virStoragePoolObjPtr pool = NULL;
557
    virStoragePoolPtr ret = NULL;
558 559
    virStorageBackendPtr backend;

E
Eric Blake 已提交
560 561
    virCheckFlags(0, NULL);

562
    storageDriverLock(driver);
563
    if (!(def = virStoragePoolDefParseString(xml)))
564
        goto cleanup;
565

566 567 568
    if (virStoragePoolCreateXMLEnsureACL(conn, def) < 0)
        goto cleanup;

569
    if (virStoragePoolObjIsDuplicate(&driver->pools, def, 1) < 0)
570
        goto cleanup;
571

572 573 574
    if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
        goto cleanup;

575 576
    if ((backend = virStorageBackendForType(def->type)) == NULL)
        goto cleanup;
577

578
    if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
579 580
        goto cleanup;
    def = NULL;
581

582
    if (backend->startPool &&
583 584 585
        backend->startPool(conn, pool) < 0) {
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
586
        goto cleanup;
587
    }
588

589 590 591
    if (backend->refreshPool(conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(conn, pool);
592 593
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
594
        goto cleanup;
595
    }
596
    VIR_INFO("Creating storage pool '%s'", pool->def->name);
597 598
    pool->active = 1;

599 600
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
601

602 603
cleanup:
    virStoragePoolDefFree(def);
604
    if (pool)
605
        virStoragePoolObjUnlock(pool);
606
    storageDriverUnlock(driver);
607 608 609 610
    return ret;
}

static virStoragePoolPtr
611 612 613
storagePoolDefineXML(virConnectPtr conn,
                     const char *xml,
                     unsigned int flags)
E
Eric Blake 已提交
614
{
615
    virStorageDriverStatePtr driver = conn->storagePrivateData;
616
    virStoragePoolDefPtr def;
617
    virStoragePoolObjPtr pool = NULL;
618
    virStoragePoolPtr ret = NULL;
619

E
Eric Blake 已提交
620 621
    virCheckFlags(0, NULL);

622
    storageDriverLock(driver);
623
    if (!(def = virStoragePoolDefParseString(xml)))
624
        goto cleanup;
625

626 627 628
    if (virStoragePoolDefineXMLEnsureACL(conn, def) < 0)
        goto cleanup;

629 630 631
    if (virStoragePoolObjIsDuplicate(&driver->pools, def, 0) < 0)
        goto cleanup;

632 633 634
    if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
        goto cleanup;

635
    if (virStorageBackendForType(def->type) == NULL)
636
        goto cleanup;
637

638
    if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
639
        goto cleanup;
640

641
    if (virStoragePoolObjSaveDef(driver, pool, def) < 0) {
642
        virStoragePoolObjRemove(&driver->pools, pool);
643
        def = NULL;
644
        goto cleanup;
645
    }
646
    def = NULL;
647

648
    VIR_INFO("Defining storage pool '%s'", pool->def->name);
649 650
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
651 652 653

cleanup:
    virStoragePoolDefFree(def);
654 655 656
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
657 658 659 660 661
    return ret;
}

static int
storagePoolUndefine(virStoragePoolPtr obj) {
662 663 664
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
665

666
    storageDriverLock(driver);
667
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
668
    if (!pool) {
669
        virReportError(VIR_ERR_NO_STORAGE_POOL,
670
                       _("no storage pool with matching uuid %s"), obj->uuid);
671
        goto cleanup;
672 673
    }

674 675 676
    if (virStoragePoolUndefineEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

677
    if (virStoragePoolObjIsActive(pool)) {
678
        virReportError(VIR_ERR_OPERATION_INVALID,
679 680
                       _("storage pool '%s' is still active"),
                       pool->def->name);
681
        goto cleanup;
682 683
    }

684
    if (pool->asyncjobs > 0) {
685 686 687
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
                       pool->def->name);
688 689 690
        goto cleanup;
    }

691
    if (virStoragePoolObjDeleteDef(pool) < 0)
692
        goto cleanup;
693

694 695
    if (unlink(pool->autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
        char ebuf[1024];
696
        VIR_ERROR(_("Failed to delete autostart link '%s': %s"),
697
                  pool->autostartLink, virStrerror(errno, ebuf, sizeof(ebuf)));
698
    }
699

700 701
    VIR_FREE(pool->configFile);
    VIR_FREE(pool->autostartLink);
702

703
    VIR_INFO("Undefining storage pool '%s'", pool->def->name);
704
    virStoragePoolObjRemove(&driver->pools, pool);
705
    pool = NULL;
706
    ret = 0;
707

708
cleanup:
709 710 711
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
712
    return ret;
713 714 715
}

static int
716 717
storagePoolCreate(virStoragePoolPtr obj,
                  unsigned int flags)
E
Eric Blake 已提交
718
{
719 720
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
721
    virStorageBackendPtr backend;
722
    int ret = -1;
723

E
Eric Blake 已提交
724 725
    virCheckFlags(0, -1);

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

730
    if (!pool) {
731
        virReportError(VIR_ERR_NO_STORAGE_POOL,
732
                       _("no storage pool with matching uuid %s"), obj->uuid);
733
        goto cleanup;
734 735
    }

736 737 738
    if (virStoragePoolCreateEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

739 740
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
741 742

    if (virStoragePoolObjIsActive(pool)) {
743
        virReportError(VIR_ERR_OPERATION_INVALID,
744 745
                       _("storage pool '%s' is already active"),
                       pool->def->name);
746
        goto cleanup;
747 748 749
    }
    if (backend->startPool &&
        backend->startPool(obj->conn, pool) < 0)
750 751
        goto cleanup;

752 753 754
    if (backend->refreshPool(obj->conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(obj->conn, pool);
755
        goto cleanup;
756 757
    }

758
    VIR_INFO("Starting up storage pool '%s'", pool->def->name);
759
    pool->active = 1;
760
    ret = 0;
761

762
cleanup:
763 764
    if (pool)
        virStoragePoolObjUnlock(pool);
765
    return ret;
766 767 768 769 770
}

static int
storagePoolBuild(virStoragePoolPtr obj,
                 unsigned int flags) {
771 772
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
773
    virStorageBackendPtr backend;
774
    int ret = -1;
775

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

780
    if (!pool) {
781
        virReportError(VIR_ERR_NO_STORAGE_POOL,
782
                       _("no storage pool with matching uuid %s"), obj->uuid);
783
        goto cleanup;
784 785
    }

786 787 788
    if (virStoragePoolBuildEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

789 790
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
791 792

    if (virStoragePoolObjIsActive(pool)) {
793
        virReportError(VIR_ERR_OPERATION_INVALID,
794 795
                       _("storage pool '%s' is already active"),
                       pool->def->name);
796
        goto cleanup;
797 798 799 800
    }

    if (backend->buildPool &&
        backend->buildPool(obj->conn, pool, flags) < 0)
801 802
        goto cleanup;
    ret = 0;
803

804
cleanup:
805 806
    if (pool)
        virStoragePoolObjUnlock(pool);
807
    return ret;
808 809 810 811 812
}


static int
storagePoolDestroy(virStoragePoolPtr obj) {
813 814
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
815
    virStorageBackendPtr backend;
816
    int ret = -1;
817

818
    storageDriverLock(driver);
819
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
820

821
    if (!pool) {
822
        virReportError(VIR_ERR_NO_STORAGE_POOL,
823
                       _("no storage pool with matching uuid %s"), obj->uuid);
824
        goto cleanup;
825 826
    }

827 828 829
    if (virStoragePoolDestroyEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

830 831
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
832 833

    if (!virStoragePoolObjIsActive(pool)) {
834
        virReportError(VIR_ERR_OPERATION_INVALID,
835
                       _("storage pool '%s' is not active"), pool->def->name);
836
        goto cleanup;
837 838
    }

839
    if (pool->asyncjobs > 0) {
840 841 842
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
                       pool->def->name);
843 844 845
        goto cleanup;
    }

846 847
    if (backend->stopPool &&
        backend->stopPool(obj->conn, pool) < 0)
848
        goto cleanup;
849 850 851 852

    virStoragePoolObjClearVols(pool);

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

855
    if (pool->configFile == NULL) {
856
        virStoragePoolObjRemove(&driver->pools, pool);
857
        pool = NULL;
858 859 860 861
    } else if (pool->newDef) {
        virStoragePoolDefFree(pool->def);
        pool->def = pool->newDef;
        pool->newDef = NULL;
862
    }
863
    ret = 0;
864

865
cleanup:
866 867 868
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
869
    return ret;
870 871 872 873 874
}

static int
storagePoolDelete(virStoragePoolPtr obj,
                  unsigned int flags) {
875 876
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
877
    virStorageBackendPtr backend;
878
    int ret = -1;
879

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

884
    if (!pool) {
885
        virReportError(VIR_ERR_NO_STORAGE_POOL,
886
                       _("no storage pool with matching uuid %s"), obj->uuid);
887
        goto cleanup;
888 889
    }

890 891 892
    if (virStoragePoolDeleteEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

893 894
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
895 896

    if (virStoragePoolObjIsActive(pool)) {
897
        virReportError(VIR_ERR_OPERATION_INVALID,
898 899
                       _("storage pool '%s' is still active"),
                       pool->def->name);
900
        goto cleanup;
901 902
    }

903
    if (pool->asyncjobs > 0) {
904 905
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
906 907 908 909
                              pool->def->name);
        goto cleanup;
    }

910
    if (!backend->deletePool) {
911 912
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("pool does not support pool deletion"));
913
        goto cleanup;
914 915
    }
    if (backend->deletePool(obj->conn, pool, flags) < 0)
916
        goto cleanup;
917
    VIR_INFO("Deleting storage pool '%s'", pool->def->name);
918
    ret = 0;
919

920
cleanup:
921 922
    if (pool)
        virStoragePoolObjUnlock(pool);
923
    return ret;
924 925 926 927 928
}


static int
storagePoolRefresh(virStoragePoolPtr obj,
E
Eric Blake 已提交
929 930
                   unsigned int flags)
{
931 932
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
933
    virStorageBackendPtr backend;
934
    int ret = -1;
935

E
Eric Blake 已提交
936 937
    virCheckFlags(0, -1);

938
    storageDriverLock(driver);
939
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
940

941
    if (!pool) {
942
        virReportError(VIR_ERR_NO_STORAGE_POOL,
943
                       _("no storage pool with matching uuid %s"), obj->uuid);
944
        goto cleanup;
945 946
    }

947 948 949
    if (virStoragePoolRefreshEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

950 951
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
952 953

    if (!virStoragePoolObjIsActive(pool)) {
954
        virReportError(VIR_ERR_OPERATION_INVALID,
955
                       _("storage pool '%s' is not active"), pool->def->name);
956
        goto cleanup;
957 958
    }

959
    if (pool->asyncjobs > 0) {
960 961 962
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
                       pool->def->name);
963 964 965
        goto cleanup;
    }

966
    virStoragePoolObjClearVols(pool);
967
    if (backend->refreshPool(obj->conn, pool) < 0) {
968 969 970 971 972
        if (backend->stopPool)
            backend->stopPool(obj->conn, pool);

        pool->active = 0;

973
        if (pool->configFile == NULL) {
974
            virStoragePoolObjRemove(&driver->pools, pool);
975 976
            pool = NULL;
        }
977
        goto cleanup;
978
    }
979
    ret = 0;
980

981
cleanup:
982 983
    if (pool)
        virStoragePoolObjUnlock(pool);
984
    storageDriverUnlock(driver);
985 986 987 988 989 990 991
    return ret;
}


static int
storagePoolGetInfo(virStoragePoolPtr obj,
                   virStoragePoolInfoPtr info) {
992 993 994
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
995

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

1000
    if (!pool) {
1001
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1002
                       _("no storage pool with matching uuid %s"), obj->uuid);
1003
        goto cleanup;
1004 1005
    }

1006 1007 1008
    if (virStoragePoolGetInfoEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1009
    if (virStorageBackendForType(pool->def->type) == NULL)
1010
        goto cleanup;
1011 1012 1013 1014 1015 1016 1017 1018 1019

    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;
1020
    ret = 0;
1021

1022
cleanup:
1023 1024
    if (pool)
        virStoragePoolObjUnlock(pool);
1025
    return ret;
1026 1027 1028
}

static char *
1029
storagePoolGetXMLDesc(virStoragePoolPtr obj,
E
Eric Blake 已提交
1030 1031
                      unsigned int flags)
{
1032 1033
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1034
    virStoragePoolDefPtr def;
1035
    char *ret = NULL;
1036

1037
    virCheckFlags(VIR_STORAGE_XML_INACTIVE, NULL);
E
Eric Blake 已提交
1038

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

1043
    if (!pool) {
1044
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1045
                       _("no storage pool with matching uuid %s"), obj->uuid);
1046
        goto cleanup;
1047 1048
    }

1049 1050 1051
    if (virStoragePoolGetXMLDescEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1052 1053 1054 1055 1056 1057
    if ((flags & VIR_STORAGE_XML_INACTIVE) && pool->newDef)
        def = pool->newDef;
    else
        def = pool->def;

    ret = virStoragePoolDefFormat(def);
1058 1059

cleanup:
1060 1061
    if (pool)
        virStoragePoolObjUnlock(pool);
1062
    return ret;
1063 1064 1065 1066 1067
}

static int
storagePoolGetAutostart(virStoragePoolPtr obj,
                        int *autostart) {
1068 1069 1070
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
1071

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

1076
    if (!pool) {
1077
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1078
                       _("no storage pool with matching uuid %s"), obj->uuid);
1079
        goto cleanup;
1080 1081
    }

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

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

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

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

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

1108
    if (!pool) {
1109
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1110
                       _("no storage pool with matching uuid %s"), obj->uuid);
1111
        goto cleanup;
1112 1113
    }

1114 1115 1116
    if (virStoragePoolSetAutostartEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1117
    if (!pool->configFile) {
1118 1119
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("pool has no config file"));
1120
        goto cleanup;
1121 1122 1123 1124
    }

    autostart = (autostart != 0);

1125 1126
    if (pool->autostart != autostart) {
        if (autostart) {
1127 1128
            if (virFileMakePath(driver->autostartDir) < 0) {
                virReportSystemError(errno,
1129 1130
                                     _("cannot create autostart directory %s"),
                                     driver->autostartDir);
1131 1132
                goto cleanup;
            }
1133

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

1153
cleanup:
1154 1155
    if (pool)
        virStoragePoolObjUnlock(pool);
1156
    storageDriverUnlock(driver);
1157
    return ret;
1158 1159 1160 1161
}


static int
1162
storagePoolNumOfVolumes(virStoragePoolPtr obj) {
1163 1164
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1165 1166
    int ret = -1;
    size_t i;
1167

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

1172
    if (!pool) {
1173
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1174
                       _("no storage pool with matching uuid %s"), obj->uuid);
1175
        goto cleanup;
1176 1177
    }

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

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

1193
cleanup:
1194 1195
    if (pool)
        virStoragePoolObjUnlock(pool);
1196
    return ret;
1197 1198 1199 1200 1201 1202
}

static int
storagePoolListVolumes(virStoragePoolPtr obj,
                       char **const names,
                       int maxnames) {
1203 1204
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1205 1206
    size_t i;
    int n = 0;
1207

1208 1209
    memset(names, 0, maxnames * sizeof(*names));

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

1214
    if (!pool) {
1215
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1216
                       _("no storage pool with matching uuid %s"), obj->uuid);
1217
        goto cleanup;
1218 1219
    }

1220 1221 1222
    if (virStoragePoolListVolumesEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1223
    if (!virStoragePoolObjIsActive(pool)) {
1224
        virReportError(VIR_ERR_OPERATION_INVALID,
1225
                       _("storage pool '%s' is not active"), pool->def->name);
1226
        goto cleanup;
1227 1228
    }

1229
    for (i = 0; i < pool->volumes.count && n < maxnames; i++) {
1230 1231 1232
        if (!virStoragePoolListVolumesCheckACL(obj->conn, pool->def,
                                               pool->volumes.objs[i]))
            continue;
1233
        if (VIR_STRDUP(names[n++], pool->volumes.objs[i]->name) < 0)
1234 1235 1236
            goto cleanup;
    }

1237
    virStoragePoolObjUnlock(pool);
1238
    return n;
1239 1240

 cleanup:
1241 1242
    if (pool)
        virStoragePoolObjUnlock(pool);
1243
    for (n = 0; n < maxnames; n++)
1244
        VIR_FREE(names[n]);
1245

1246
    memset(names, 0, maxnames * sizeof(*names));
1247 1248 1249
    return -1;
}

1250 1251 1252 1253 1254 1255
static int
storagePoolListAllVolumes(virStoragePoolPtr pool,
                          virStorageVolPtr **vols,
                          unsigned int flags) {
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
    virStoragePoolObjPtr obj;
1256
    size_t i;
1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268
    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) {
1269 1270 1271
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching uuid %s"),
                       pool->uuid);
1272 1273 1274
        goto cleanup;
    }

1275 1276 1277
    if (virStoragePoolListAllVolumesEnsureACL(pool->conn, obj->def) < 0)
        goto cleanup;

1278
    if (!virStoragePoolObjIsActive(obj)) {
1279 1280
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), obj->def->name);
1281 1282 1283 1284 1285 1286 1287 1288 1289
        goto cleanup;
    }

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

1290
    if (VIR_ALLOC_N(tmp_vols, obj->volumes.count + 1) < 0)
1291
        goto cleanup;
1292

1293
    for (i = 0; i < obj->volumes.count; i++) {
1294 1295 1296
        if (!virStoragePoolListAllVolumesCheckACL(pool->conn, obj->def,
                                                  obj->volumes.objs[i]))
            continue;
1297 1298
        if (!(vol = virGetStorageVol(pool->conn, obj->def->name,
                                     obj->volumes.objs[i]->name,
1299 1300
                                     obj->volumes.objs[i]->key,
                                     NULL, NULL)))
1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314
            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]);
        }
1315
        VIR_FREE(tmp_vols);
1316 1317 1318 1319 1320 1321 1322
    }

    if (obj)
        virStoragePoolObjUnlock(obj);

    return ret;
}
1323 1324

static virStorageVolPtr
1325 1326
storageVolLookupByName(virStoragePoolPtr obj,
                       const char *name) {
1327 1328
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1329
    virStorageVolDefPtr vol;
1330
    virStorageVolPtr ret = NULL;
1331

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

1336
    if (!pool) {
1337
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1338
                       _("no storage pool with matching uuid %s"), obj->uuid);
1339
        goto cleanup;
1340 1341 1342
    }

    if (!virStoragePoolObjIsActive(pool)) {
1343
        virReportError(VIR_ERR_OPERATION_INVALID,
1344
                       _("storage pool '%s' is not active"), pool->def->name);
1345
        goto cleanup;
1346 1347 1348 1349 1350
    }

    vol = virStorageVolDefFindByName(pool, name);

    if (!vol) {
1351 1352 1353
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       name);
1354
        goto cleanup;
1355 1356
    }

1357 1358 1359
    if (virStorageVolLookupByNameEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

1360 1361
    ret = virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key,
                           NULL, NULL);
1362 1363

cleanup:
1364 1365
    if (pool)
        virStoragePoolObjUnlock(pool);
1366
    return ret;
1367 1368 1369 1370
}


static virStorageVolPtr
1371 1372
storageVolLookupByKey(virConnectPtr conn,
                      const char *key) {
1373
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1374
    size_t i;
1375
    virStorageVolPtr ret = NULL;
1376

1377
    storageDriverLock(driver);
1378
    for (i = 0; i < driver->pools.count && !ret; i++) {
1379
        virStoragePoolObjLock(driver->pools.objs[i]);
1380 1381 1382
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
            virStorageVolDefPtr vol =
                virStorageVolDefFindByKey(driver->pools.objs[i], key);
1383

1384
            if (vol) {
1385 1386
                if (virStorageVolLookupByKeyEnsureACL(conn, driver->pools.objs[i]->def, vol) < 0) {
                    virStoragePoolObjUnlock(driver->pools.objs[i]);
1387
                    goto cleanup;
1388
                }
1389

1390
                ret = virGetStorageVol(conn,
1391 1392
                                       driver->pools.objs[i]->def->name,
                                       vol->name,
1393 1394
                                       vol->key,
                                       NULL, NULL);
1395
            }
1396
        }
1397
        virStoragePoolObjUnlock(driver->pools.objs[i]);
1398 1399
    }

1400
    if (!ret)
1401
        virReportError(VIR_ERR_NO_STORAGE_VOL,
1402
                       _("no storage vol with matching key %s"), key);
1403

1404 1405
cleanup:
    storageDriverUnlock(driver);
1406
    return ret;
1407 1408 1409
}

static virStorageVolPtr
1410 1411
storageVolLookupByPath(virConnectPtr conn,
                       const char *path) {
1412
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1413
    size_t i;
1414
    virStorageVolPtr ret = NULL;
1415 1416 1417 1418 1419
    char *cleanpath;

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

1421
    storageDriverLock(driver);
1422
    for (i = 0; i < driver->pools.count && !ret; i++) {
1423
        virStoragePoolObjLock(driver->pools.objs[i]);
1424
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
1425
            virStorageVolDefPtr vol;
1426 1427
            const char *stable_path;

1428
            stable_path = virStorageBackendStablePath(driver->pools.objs[i],
1429 1430
                                                      cleanpath,
                                                      false);
1431
            if (stable_path == NULL) {
1432 1433 1434 1435 1436
                /* 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);
1437
                virStoragePoolObjUnlock(driver->pools.objs[i]);
1438
                continue;
1439
            }
1440 1441 1442 1443

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

1445
            if (vol) {
1446 1447
                if (virStorageVolLookupByPathEnsureACL(conn, driver->pools.objs[i]->def, vol) < 0) {
                    virStoragePoolObjUnlock(driver->pools.objs[i]);
1448
                    goto cleanup;
1449
                }
1450

1451 1452 1453
                ret = virGetStorageVol(conn,
                                       driver->pools.objs[i]->def->name,
                                       vol->name,
1454 1455
                                       vol->key,
                                       NULL, NULL);
1456
            }
1457
        }
1458
        virStoragePoolObjUnlock(driver->pools.objs[i]);
1459 1460
    }

1461
    if (!ret)
1462
        virReportError(VIR_ERR_NO_STORAGE_VOL,
1463
                       _("no storage vol with matching path %s"), path);
1464

1465
cleanup:
1466
    VIR_FREE(cleanpath);
1467
    storageDriverUnlock(driver);
1468
    return ret;
1469 1470
}

1471
static int storageVolDelete(virStorageVolPtr obj, unsigned int flags);
1472

1473
static virStorageVolPtr
1474 1475 1476
storageVolCreateXML(virStoragePoolPtr obj,
                    const char *xmldesc,
                    unsigned int flags)
E
Eric Blake 已提交
1477
{
1478 1479
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1480
    virStorageBackendPtr backend;
1481 1482
    virStorageVolDefPtr voldef = NULL;
    virStorageVolPtr ret = NULL, volobj = NULL;
1483

1484
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
E
Eric Blake 已提交
1485

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

1490
    if (!pool) {
1491
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1492
                       _("no storage pool with matching uuid %s"), obj->uuid);
1493
        goto cleanup;
1494 1495 1496
    }

    if (!virStoragePoolObjIsActive(pool)) {
1497
        virReportError(VIR_ERR_OPERATION_INVALID,
1498
                       _("storage pool '%s' is not active"), pool->def->name);
1499
        goto cleanup;
1500 1501 1502
    }

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

1505
    voldef = virStorageVolDefParseString(pool->def, xmldesc);
1506
    if (voldef == NULL)
1507
        goto cleanup;
1508

1509 1510 1511
    if (virStorageVolCreateXMLEnsureACL(obj->conn, pool->def, voldef) < 0)
        goto cleanup;

1512
    if (virStorageVolDefFindByName(pool, voldef->name)) {
1513
        virReportError(VIR_ERR_NO_STORAGE_VOL,
1514
                       _("storage vol '%s' already exists"), voldef->name);
1515
        goto cleanup;
1516 1517
    }

1518
    if (VIR_REALLOC_N(pool->volumes.objs,
1519
                      pool->volumes.count+1) < 0)
1520
        goto cleanup;
1521

1522
    if (!backend->createVol) {
1523 1524 1525
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("storage pool does not support volume "
                               "creation"));
1526
        goto cleanup;
1527 1528
    }

1529
    if (backend->createVol(obj->conn, pool, voldef) < 0) {
1530
        goto cleanup;
1531 1532
    }

1533 1534
    pool->volumes.objs[pool->volumes.count++] = voldef;
    volobj = virGetStorageVol(obj->conn, pool->def->name, voldef->name,
1535
                              voldef->key, NULL, NULL);
1536 1537 1538 1539
    if (!volobj) {
        pool->volumes.count--;
        goto cleanup;
    }
1540

1541
    if (backend->buildVol) {
1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560
        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);

1561
        buildret = backend->buildVol(obj->conn, pool, buildvoldef, flags);
1562

1563
        storageDriverLock(driver);
1564
        virStoragePoolObjLock(pool);
1565 1566
        storageDriverUnlock(driver);

1567 1568 1569 1570 1571 1572 1573 1574
        voldef->building = 0;
        pool->asyncjobs--;

        voldef = NULL;
        VIR_FREE(buildvoldef);

        if (buildret < 0) {
            virStoragePoolObjUnlock(pool);
1575
            storageVolDelete(volobj, 0);
1576 1577 1578 1579 1580 1581
            pool = NULL;
            goto cleanup;
        }

    }

1582
    VIR_INFO("Creating volume '%s' in storage pool '%s'",
1583
             volobj->name, pool->def->name);
1584 1585 1586
    ret = volobj;
    volobj = NULL;
    voldef = NULL;
1587

1588
cleanup:
1589
    virObjectUnref(volobj);
1590
    virStorageVolDefFree(voldef);
1591 1592
    if (pool)
        virStoragePoolObjUnlock(pool);
1593
    return ret;
1594 1595
}

1596
static virStorageVolPtr
1597 1598 1599 1600
storageVolCreateXMLFrom(virStoragePoolPtr obj,
                        const char *xmldesc,
                        virStorageVolPtr vobj,
                        unsigned int flags)
E
Eric Blake 已提交
1601
{
1602 1603 1604 1605 1606
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool, origpool = NULL;
    virStorageBackendPtr backend;
    virStorageVolDefPtr origvol = NULL, newvol = NULL;
    virStorageVolPtr ret = NULL, volobj = NULL;
1607
    int buildret;
1608

1609
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
E
Eric Blake 已提交
1610

1611 1612
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1613
    if (pool && STRNEQ(obj->name, vobj->pool)) {
1614
        virStoragePoolObjUnlock(pool);
1615
        origpool = virStoragePoolObjFindByName(&driver->pools, vobj->pool);
1616
        virStoragePoolObjLock(pool);
1617
    }
1618 1619
    storageDriverUnlock(driver);
    if (!pool) {
1620
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1621
                       _("no storage pool with matching uuid %s"), obj->uuid);
1622 1623 1624
        goto cleanup;
    }

1625
    if (STRNEQ(obj->name, vobj->pool) && !origpool) {
1626 1627 1628
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       vobj->pool);
1629 1630 1631 1632
        goto cleanup;
    }

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

1638
    if (origpool && !virStoragePoolObjIsActive(origpool)) {
1639
        virReportError(VIR_ERR_OPERATION_INVALID,
1640 1641
                       _("storage pool '%s' is not active"),
                       origpool->def->name);
1642 1643 1644 1645 1646 1647
        goto cleanup;
    }

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

1648
    origvol = virStorageVolDefFindByName(origpool ? origpool : pool, vobj->name);
1649
    if (!origvol) {
1650 1651 1652
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vobj->name);
1653 1654 1655
        goto cleanup;
    }

1656
    newvol = virStorageVolDefParseString(pool->def, xmldesc);
1657 1658 1659
    if (newvol == NULL)
        goto cleanup;

1660 1661 1662
    if (virStorageVolCreateXMLFromEnsureACL(obj->conn, pool->def, newvol) < 0)
        goto cleanup;

1663
    if (virStorageVolDefFindByName(pool, newvol->name)) {
1664 1665 1666
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("storage volume name '%s' already in use."),
                       newvol->name);
1667 1668 1669 1670 1671 1672 1673
        goto cleanup;
    }

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

1674 1675 1676 1677 1678
    /* 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;

1679
    if (!backend->buildVolFrom) {
1680 1681
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("storage pool does not support volume creation from an existing volume"));
1682 1683 1684 1685
        goto cleanup;
    }

    if (origvol->building) {
1686 1687 1688
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       origvol->name);
1689 1690 1691 1692 1693 1694 1695 1696
        goto cleanup;
    }

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

    if (VIR_REALLOC_N(pool->volumes.objs,
1697
                      pool->volumes.count+1) < 0)
1698 1699 1700 1701 1702 1703 1704 1705 1706
        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,
1707
                              newvol->key, NULL, NULL);
1708 1709 1710 1711 1712 1713 1714

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

1715
    if (origpool) {
1716 1717 1718 1719
        origpool->asyncjobs++;
        virStoragePoolObjUnlock(origpool);
    }

1720
    buildret = backend->buildVolFrom(obj->conn, pool, newvol, origvol, flags);
1721 1722 1723

    storageDriverLock(driver);
    virStoragePoolObjLock(pool);
1724
    if (origpool)
1725 1726 1727 1728 1729 1730 1731 1732
        virStoragePoolObjLock(origpool);
    storageDriverUnlock(driver);

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

1733
    if (origpool) {
1734 1735 1736 1737 1738 1739 1740
        origpool->asyncjobs--;
        virStoragePoolObjUnlock(origpool);
        origpool = NULL;
    }

    if (buildret < 0) {
        virStoragePoolObjUnlock(pool);
1741
        storageVolDelete(volobj, 0);
1742 1743 1744 1745
        pool = NULL;
        goto cleanup;
    }

1746
    VIR_INFO("Creating volume '%s' in storage pool '%s'",
1747
             volobj->name, pool->def->name);
1748 1749 1750 1751
    ret = volobj;
    volobj = NULL;

cleanup:
1752
    virObjectUnref(volobj);
1753 1754 1755
    virStorageVolDefFree(newvol);
    if (pool)
        virStoragePoolObjUnlock(pool);
1756
    if (origpool)
1757 1758 1759 1760
        virStoragePoolObjUnlock(origpool);
    return ret;
}

1761

1762
static int
1763 1764 1765 1766 1767
storageVolDownload(virStorageVolPtr obj,
                   virStreamPtr stream,
                   unsigned long long offset,
                   unsigned long long length,
                   unsigned int flags)
1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780
{
    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) {
1781
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1782 1783
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1784 1785 1786 1787
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1788
        virReportError(VIR_ERR_OPERATION_INVALID,
1789
                       _("storage pool '%s' is not active"), pool->def->name);
1790 1791 1792 1793 1794 1795
        goto out;
    }

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

    if (vol == NULL) {
1796 1797 1798
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1799 1800 1801
        goto out;
    }

1802 1803 1804
    if (virStorageVolDownloadEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

1805
    if (vol->building) {
1806 1807 1808
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1809 1810 1811 1812 1813 1814
        goto out;
    }

    if (virFDStreamOpenFile(stream,
                            vol->target.path,
                            offset, length,
E
Eric Blake 已提交
1815
                            O_RDONLY) < 0)
1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828
        goto out;

    ret = 0;

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}


static int
1829 1830 1831 1832 1833
storageVolUpload(virStorageVolPtr obj,
                 virStreamPtr stream,
                 unsigned long long offset,
                 unsigned long long length,
                 unsigned int flags)
1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846
{
    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) {
1847
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1848 1849
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1850 1851 1852 1853
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1854
        virReportError(VIR_ERR_OPERATION_INVALID,
1855
                       _("storage pool '%s' is not active"), pool->def->name);
1856 1857 1858 1859 1860 1861
        goto out;
    }

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

    if (vol == NULL) {
1862 1863 1864
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1865 1866 1867
        goto out;
    }

1868 1869 1870
    if (virStorageVolUploadEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

1871
    if (vol->building) {
1872 1873 1874
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1875 1876 1877 1878 1879 1880 1881 1882
        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 已提交
1883
                            O_WRONLY) < 0)
1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894
        goto out;

    ret = 0;

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}

1895
static int
1896 1897 1898
storageVolResize(virStorageVolPtr obj,
                 unsigned long long capacity,
                 unsigned int flags)
1899 1900 1901 1902 1903 1904 1905 1906
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStorageBackendPtr backend;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    unsigned long long abs_capacity;
    int ret = -1;

1907
    virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE |
1908 1909
                  VIR_STORAGE_VOL_RESIZE_DELTA |
                  VIR_STORAGE_VOL_RESIZE_SHRINK, -1);
1910 1911 1912 1913 1914 1915

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

    if (!pool) {
1916 1917 1918
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1919 1920 1921 1922
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1923 1924
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->def->name);
1925 1926 1927 1928 1929 1930 1931 1932 1933
        goto out;
    }

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

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

    if (vol == NULL) {
1934 1935 1936
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1937 1938 1939
        goto out;
    }

1940 1941 1942
    if (virStorageVolResizeEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

1943
    if (vol->building) {
1944 1945 1946
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1947 1948
        goto out;
    }
1949

1950 1951 1952 1953 1954 1955 1956 1957
    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) {
1958
        virReportError(VIR_ERR_INVALID_ARG, "%s",
1959 1960
                       _("can't shrink capacity below "
                         "existing allocation"));
1961 1962 1963
        goto out;
    }

1964 1965 1966 1967 1968 1969 1970 1971
    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;
    }

1972
    if (abs_capacity > vol->capacity + pool->def->available) {
1973
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
1974
                       _("Not enough space left on storage pool"));
1975 1976 1977 1978
        goto out;
    }

    if (!backend->resizeVol) {
1979
        virReportError(VIR_ERR_NO_SUPPORT, "%s",
1980 1981
                       _("storage pool does not support changing of "
                         "volume capacity"));
1982 1983 1984 1985 1986 1987
        goto out;
    }

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

O
Osier Yang 已提交
1988 1989
    vol->capacity = abs_capacity;
    ret = 0;
1990 1991 1992 1993 1994 1995 1996

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
1997

1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012
/* 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
2013 2014 2015
storageVolZeroSparseFile(virStorageVolDefPtr vol,
                         off_t size,
                         int fd)
2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031
{
    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 "
2032
                               "path '%s' to %ju bytes"),
E
Eric Blake 已提交
2033
                             vol->target.path, (uintmax_t)size);
2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054
    }

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 已提交
2055
              (uintmax_t)extent_start, (uintmax_t)extent_length);
2056 2057 2058 2059 2060

    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 已提交
2061
                             (uintmax_t)extent_start, vol->target.path);
2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082
        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;
    }

2083 2084 2085 2086 2087 2088 2089 2090
    if (fdatasync(fd) < 0) {
        ret = -errno;
        virReportSystemError(errno,
                             _("cannot sync data to volume with path '%s'"),
                             vol->target.path);
        goto out;
    }

2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101
    VIR_DEBUG("Wrote %zu bytes to volume with path '%s'",
              *bytes_wiped, vol->target.path);

    ret = 0;

out:
    return ret;
}


static int
2102 2103
storageVolWipeInternal(virStorageVolDefPtr def,
                       unsigned int algorithm)
2104 2105 2106 2107 2108
{
    int ret = -1, fd = -1;
    struct stat st;
    char *writebuf = NULL;
    size_t bytes_wiped = 0;
2109
    virCommandPtr cmd = NULL;
2110

2111 2112
    VIR_DEBUG("Wiping volume with path '%s' and algorithm %u",
              def->target.path, algorithm);
2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128

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

2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144
    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 已提交
2145
            alg_char = "schneier";
2146 2147 2148 2149 2150
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7:
            alg_char = "pfitzner7";
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33:
M
Michal Privoznik 已提交
2151
            alg_char = "pfitzner33";
2152 2153 2154 2155 2156
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_RANDOM:
            alg_char = "random";
            break;
        default:
2157 2158 2159
            virReportError(VIR_ERR_INVALID_ARG,
                           _("unsupported algorithm %d"),
                           algorithm);
2160 2161 2162 2163
        }
        cmd = virCommandNew(SCRUB);
        virCommandAddArgList(cmd, "-f", "-p", alg_char,
                             def->target.path, NULL);
2164

2165
        if (virCommandRun(cmd, NULL) < 0)
2166 2167
            goto out;

2168 2169 2170 2171
        ret = 0;
        goto out;
    } else {
        if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) {
2172
            ret = storageVolZeroSparseFile(def, st.st_size, fd);
2173 2174
        } else {

2175
            if (VIR_ALLOC_N(writebuf, st.st_blksize) < 0)
2176 2177 2178 2179 2180 2181 2182 2183 2184 2185
                goto out;

            ret = storageWipeExtent(def,
                                    fd,
                                    0,
                                    def->allocation,
                                    writebuf,
                                    st.st_blksize,
                                    &bytes_wiped);
        }
2186 2187 2188
    }

out:
2189
    virCommandFree(cmd);
2190
    VIR_FREE(writebuf);
2191
    VIR_FORCE_CLOSE(fd);
2192 2193 2194 2195 2196
    return ret;
}


static int
2197 2198 2199
storageVolWipePattern(virStorageVolPtr obj,
                      unsigned int algorithm,
                      unsigned int flags)
2200 2201 2202 2203 2204 2205
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    int ret = -1;

2206
    virCheckFlags(0, -1);
2207

2208
    if (algorithm >= VIR_STORAGE_VOL_WIPE_ALG_LAST) {
2209 2210 2211
        virReportError(VIR_ERR_INVALID_ARG,
                       _("wiping algorithm %d not supported"),
                       algorithm);
2212 2213 2214
        return -1;
    }

2215 2216 2217 2218 2219
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
    storageDriverUnlock(driver);

    if (!pool) {
2220
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2221 2222
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2223 2224 2225 2226
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
2227
        virReportError(VIR_ERR_OPERATION_INVALID,
2228
                       _("storage pool '%s' is not active"), pool->def->name);
2229 2230 2231 2232 2233 2234
        goto out;
    }

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

    if (vol == NULL) {
2235 2236 2237
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2238 2239 2240
        goto out;
    }

2241 2242 2243
    if (virStorageVolWipePatternEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

2244
    if (vol->building) {
2245 2246 2247
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
2248 2249 2250
        goto out;
    }

2251
    if (storageVolWipeInternal(vol, algorithm) == -1) {
2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265
        goto out;
    }

    ret = 0;

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

    return ret;

}

2266
static int
2267 2268
storageVolWipe(virStorageVolPtr obj,
               unsigned int flags)
2269
{
2270
    return storageVolWipePattern(obj, VIR_STORAGE_VOL_WIPE_ALG_ZERO, flags);
2271 2272
}

2273
static int
2274 2275
storageVolDelete(virStorageVolPtr obj,
                 unsigned int flags) {
2276 2277
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2278
    virStorageBackendPtr backend;
2279
    virStorageVolDefPtr vol = NULL;
2280
    size_t i;
2281
    int ret = -1;
2282

2283
    storageDriverLock(driver);
2284
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2285 2286
    storageDriverUnlock(driver);

2287
    if (!pool) {
2288
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2289 2290
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2291
        goto cleanup;
2292 2293 2294
    }

    if (!virStoragePoolObjIsActive(pool)) {
2295
        virReportError(VIR_ERR_OPERATION_INVALID,
2296
                       _("storage pool '%s' is not active"), pool->def->name);
2297
        goto cleanup;
2298 2299 2300
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2301
        goto cleanup;
2302 2303 2304 2305

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

    if (!vol) {
2306 2307 2308
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2309
        goto cleanup;
2310 2311
    }

2312 2313 2314
    if (virStorageVolDeleteEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2315
    if (vol->building) {
2316 2317 2318
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
2319 2320 2321
        goto cleanup;
    }

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

2326
        goto cleanup;
2327 2328
    }

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

2332
    for (i = 0; i < pool->volumes.count; i++) {
2333
        if (pool->volumes.objs[i] == vol) {
2334
            VIR_INFO("Deleting volume '%s' from storage pool '%s'",
2335
                     vol->name, pool->def->name);
2336
            virStorageVolDefFree(vol);
2337
            vol = NULL;
2338 2339 2340 2341 2342 2343 2344 2345 2346 2347

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

2348 2349 2350
            break;
        }
    }
2351
    ret = 0;
2352

2353
cleanup:
2354 2355
    if (pool)
        virStoragePoolObjUnlock(pool);
2356
    return ret;
2357 2358 2359
}

static int
2360 2361
storageVolGetInfo(virStorageVolPtr obj,
                  virStorageVolInfoPtr info) {
2362 2363
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2364 2365
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
2366
    int ret = -1;
2367

2368
    storageDriverLock(driver);
2369
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2370 2371
    storageDriverUnlock(driver);

2372
    if (!pool) {
2373
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2374 2375
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2376
        goto cleanup;
2377 2378 2379
    }

    if (!virStoragePoolObjIsActive(pool)) {
2380
        virReportError(VIR_ERR_OPERATION_INVALID,
2381
                       _("storage pool '%s' is not active"), pool->def->name);
2382
        goto cleanup;
2383 2384 2385 2386 2387
    }

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

    if (!vol) {
2388 2389 2390
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2391
        goto cleanup;
2392 2393
    }

2394 2395 2396
    if (virStorageVolGetInfoEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2397
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2398
        goto cleanup;
2399 2400 2401

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

    memset(info, 0, sizeof(*info));
2405
    info->type = vol->type;
2406 2407
    info->capacity = vol->capacity;
    info->allocation = vol->allocation;
2408
    ret = 0;
2409

2410
cleanup:
2411 2412
    if (pool)
        virStoragePoolObjUnlock(pool);
2413
    return ret;
2414 2415 2416
}

static char *
2417 2418
storageVolGetXMLDesc(virStorageVolPtr obj,
                     unsigned int flags)
E
Eric Blake 已提交
2419
{
2420 2421
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2422 2423
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
2424
    char *ret = NULL;
2425

E
Eric Blake 已提交
2426 2427
    virCheckFlags(0, NULL);

2428
    storageDriverLock(driver);
2429
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2430 2431
    storageDriverUnlock(driver);

2432
    if (!pool) {
2433
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2434 2435
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2436
        goto cleanup;
2437 2438 2439
    }

    if (!virStoragePoolObjIsActive(pool)) {
2440
        virReportError(VIR_ERR_OPERATION_INVALID,
2441
                       _("storage pool '%s' is not active"), pool->def->name);
2442
        goto cleanup;
2443 2444 2445 2446 2447
    }

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

    if (!vol) {
2448 2449 2450
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2451
        goto cleanup;
2452 2453
    }

2454 2455 2456
    if (virStorageVolGetXMLDescEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2457
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2458
        goto cleanup;
2459 2460 2461 2462

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

2464
    ret = virStorageVolDefFormat(pool->def, vol);
2465 2466

cleanup:
2467 2468 2469
    if (pool)
        virStoragePoolObjUnlock(pool);

2470
    return ret;
2471 2472 2473
}

static char *
2474
storageVolGetPath(virStorageVolPtr obj) {
2475
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
2476
    virStoragePoolObjPtr pool;
2477
    virStorageVolDefPtr vol;
2478
    char *ret = NULL;
2479

2480 2481 2482
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
    storageDriverUnlock(driver);
2483
    if (!pool) {
2484
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2485 2486
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2487
        goto cleanup;
2488 2489 2490
    }

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

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

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

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

2508
    ignore_value(VIR_STRDUP(ret, vol->target.path));
2509 2510

cleanup:
2511 2512
    if (pool)
        virStoragePoolObjUnlock(pool);
2513 2514 2515
    return ret;
}

2516
static int
2517 2518 2519
storageConnectListAllStoragePools(virConnectPtr conn,
                                  virStoragePoolPtr **pools,
                                  unsigned int flags)
2520 2521 2522 2523 2524 2525
{
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

2526 2527 2528
    if (virConnectListAllStoragePoolsEnsureACL(conn) < 0)
        goto cleanup;

2529
    storageDriverLock(driver);
2530 2531
    ret = virStoragePoolObjListExport(conn, driver->pools, pools,
                                      virConnectListAllStoragePoolsCheckACL, flags);
2532 2533
    storageDriverUnlock(driver);

2534
cleanup:
2535 2536 2537
    return ret;
}

2538
static virStorageDriver storageDriver = {
2539
    .name = "storage",
2540 2541
    .storageOpen = storageOpen, /* 0.4.0 */
    .storageClose = storageClose, /* 0.4.0 */
2542 2543 2544 2545 2546 2547
    .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 */
2548 2549 2550
    .storagePoolLookupByName = storagePoolLookupByName, /* 0.4.0 */
    .storagePoolLookupByUUID = storagePoolLookupByUUID, /* 0.4.0 */
    .storagePoolLookupByVolume = storagePoolLookupByVolume, /* 0.4.0 */
2551 2552
    .storagePoolCreateXML = storagePoolCreateXML, /* 0.4.0 */
    .storagePoolDefineXML = storagePoolDefineXML, /* 0.4.0 */
2553 2554
    .storagePoolBuild = storagePoolBuild, /* 0.4.0 */
    .storagePoolUndefine = storagePoolUndefine, /* 0.4.0 */
2555
    .storagePoolCreate = storagePoolCreate, /* 0.4.0 */
2556 2557 2558 2559 2560 2561 2562
    .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 */
2563
    .storagePoolNumOfVolumes = storagePoolNumOfVolumes, /* 0.4.0 */
2564 2565 2566
    .storagePoolListVolumes = storagePoolListVolumes, /* 0.4.0 */
    .storagePoolListAllVolumes = storagePoolListAllVolumes, /* 0.10.2 */

2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580
    .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 */
2581 2582 2583

    .storagePoolIsActive = storagePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = storagePoolIsPersistent, /* 0.7.3 */
2584 2585 2586 2587
};


static virStateDriver stateDriver = {
2588
    .name = "Storage",
2589 2590 2591
    .stateInitialize = storageStateInitialize,
    .stateCleanup = storageStateCleanup,
    .stateReload = storageStateReload,
2592 2593 2594 2595 2596 2597 2598
};

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