storage_driver.c 73.4 KB
Newer Older
1 2 3
/*
 * storage_driver.c: core driver for storage APIs
 *
4
 * Copyright (C) 2006-2012 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
    unsigned int 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 162
        goto out_of_memory;

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

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
out_of_memory:
179
    virReportOOMError();
180 181 182
error:
    VIR_FREE(base);
    storageDriverUnlock(driverState);
183
    storageStateCleanup();
184 185 186 187
    return -1;
}

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

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

    return 0;
}


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

219
    storageDriverLock(driverState);
220 221

    /* free inactive pools */
222 223 224 225
    virStoragePoolObjListFree(&driverState->pools);

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

    return 0;
}



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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return nactive;
359 360 361
}

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

368 369 370
    if (virConnectListStoragePoolsEnsureACL(conn) < 0)
        return -1;

371
    storageDriverLock(driver);
372
    for (i = 0; i < driver->pools.count && got < nnames; i++) {
373
        virStoragePoolObjLock(driver->pools.objs[i]);
374
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
375
            if (VIR_STRDUP(names[got], driver->pools.objs[i]->def->name) < 0) {
376
                virStoragePoolObjUnlock(driver->pools.objs[i]);
377 378 379 380
                goto cleanup;
            }
            got++;
        }
381
        virStoragePoolObjUnlock(driver->pools.objs[i]);
382
    }
383
    storageDriverUnlock(driver);
384 385 386
    return got;

 cleanup:
387
    storageDriverUnlock(driver);
388
    for (i = 0; i < got; i++)
389
        VIR_FREE(names[i]);
390
    memset(names, 0, nnames * sizeof(*names));
391 392 393 394
    return -1;
}

static int
395
storageConnectNumOfDefinedStoragePools(virConnectPtr conn) {
396
    virStorageDriverStatePtr driver = conn->storagePrivateData;
397 398
    unsigned int i, nactive = 0;

399 400 401
    if (virConnectNumOfDefinedStoragePoolsEnsureACL(conn) < 0)
        return -1;

402
    storageDriverLock(driver);
403
    for (i = 0; i < driver->pools.count; i++) {
404
        virStoragePoolObjLock(driver->pools.objs[i]);
405 406
        if (!virStoragePoolObjIsActive(driver->pools.objs[i]))
            nactive++;
407 408 409
        virStoragePoolObjUnlock(driver->pools.objs[i]);
    }
    storageDriverUnlock(driver);
410 411

    return nactive;
412 413 414
}

static int
415 416 417
storageConnectListDefinedStoragePools(virConnectPtr conn,
                                      char **const names,
                                      int nnames) {
418
    virStorageDriverStatePtr driver = conn->storagePrivateData;
419
    int got = 0, i;
420

421 422 423
    if (virConnectListDefinedStoragePoolsEnsureACL(conn) < 0)
        return -1;

424
    storageDriverLock(driver);
425
    for (i = 0; i < driver->pools.count && got < nnames; i++) {
426
        virStoragePoolObjLock(driver->pools.objs[i]);
427
        if (!virStoragePoolObjIsActive(driver->pools.objs[i])) {
428
            if (VIR_STRDUP(names[got], driver->pools.objs[i]->def->name) < 0) {
429
                virStoragePoolObjUnlock(driver->pools.objs[i]);
430 431 432 433
                goto cleanup;
            }
            got++;
        }
434
        virStoragePoolObjUnlock(driver->pools.objs[i]);
435
    }
436
    storageDriverUnlock(driver);
437 438 439
    return got;

 cleanup:
440
    storageDriverUnlock(driver);
441
    for (i = 0; i < got; i++) {
442
        VIR_FREE(names[i]);
443
    }
444
    memset(names, 0, nnames * sizeof(*names));
445 446 447
    return -1;
}

448 449
/* This method is required to be re-entrant / thread safe, so
   uses no driver lock */
450
static char *
451 452 453 454
storageConnectFindStoragePoolSources(virConnectPtr conn,
                                     const char *type,
                                     const char *srcSpec,
                                     unsigned int flags)
455 456 457
{
    int backend_type;
    virStorageBackendPtr backend;
458
    char *ret = NULL;
459

460 461 462
    if (virConnectFindStoragePoolSourcesEnsureACL(conn) < 0)
        return NULL;

463
    backend_type = virStoragePoolTypeFromString(type);
464
    if (backend_type < 0) {
465 466
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unknown storage pool type %s"), type);
467
        goto cleanup;
468
    }
469 470 471

    backend = virStorageBackendForType(backend_type);
    if (backend == NULL)
472
        goto cleanup;
473

474
    if (!backend->findPoolSources) {
475 476 477
        virReportError(VIR_ERR_NO_SUPPORT,
                       _("pool type '%s' does not support source "
                         "discovery"), type);
478 479 480 481
        goto cleanup;
    }

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

483 484
cleanup:
    return ret;
485 486 487
}


488
static int storagePoolIsActive(virStoragePoolPtr pool)
489
{
490
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
491 492 493 494
    virStoragePoolObjPtr obj;
    int ret = -1;

    storageDriverLock(driver);
495
    obj = virStoragePoolObjFindByUUID(&driver->pools, pool->uuid);
496 497
    storageDriverUnlock(driver);
    if (!obj) {
498
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
499 500
        goto cleanup;
    }
501 502 503 504

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

505 506 507 508 509 510 511 512
    ret = virStoragePoolObjIsActive(obj);

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

513
static int storagePoolIsPersistent(virStoragePoolPtr pool)
514
{
515
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
516 517 518 519
    virStoragePoolObjPtr obj;
    int ret = -1;

    storageDriverLock(driver);
520
    obj = virStoragePoolObjFindByUUID(&driver->pools, pool->uuid);
521 522
    storageDriverUnlock(driver);
    if (!obj) {
523
        virReportError(VIR_ERR_NO_STORAGE_POOL, NULL);
524 525
        goto cleanup;
    }
526 527 528 529

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

530 531 532 533 534 535 536 537 538
    ret = obj->configFile ? 1 : 0;

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


539
static virStoragePoolPtr
540 541 542
storagePoolCreateXML(virConnectPtr conn,
                     const char *xml,
                     unsigned int flags)
E
Eric Blake 已提交
543
{
544
    virStorageDriverStatePtr driver = conn->storagePrivateData;
545
    virStoragePoolDefPtr def;
546
    virStoragePoolObjPtr pool = NULL;
547
    virStoragePoolPtr ret = NULL;
548 549
    virStorageBackendPtr backend;

E
Eric Blake 已提交
550 551
    virCheckFlags(0, NULL);

552
    storageDriverLock(driver);
553
    if (!(def = virStoragePoolDefParseString(xml)))
554
        goto cleanup;
555

556 557 558
    if (virStoragePoolCreateXMLEnsureACL(conn, def) < 0)
        goto cleanup;

559
    if (virStoragePoolObjIsDuplicate(&driver->pools, def, 1) < 0)
560
        goto cleanup;
561

562 563 564
    if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
        goto cleanup;

565 566
    if ((backend = virStorageBackendForType(def->type)) == NULL)
        goto cleanup;
567

568
    if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
569 570
        goto cleanup;
    def = NULL;
571

572
    if (backend->startPool &&
573 574 575
        backend->startPool(conn, pool) < 0) {
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
576
        goto cleanup;
577
    }
578

579 580 581
    if (backend->refreshPool(conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(conn, pool);
582 583
        virStoragePoolObjRemove(&driver->pools, pool);
        pool = NULL;
584
        goto cleanup;
585
    }
586
    VIR_INFO("Creating storage pool '%s'", pool->def->name);
587 588
    pool->active = 1;

589 590
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
591

592 593
cleanup:
    virStoragePoolDefFree(def);
594
    if (pool)
595
        virStoragePoolObjUnlock(pool);
596
    storageDriverUnlock(driver);
597 598 599 600
    return ret;
}

static virStoragePoolPtr
601 602 603
storagePoolDefineXML(virConnectPtr conn,
                     const char *xml,
                     unsigned int flags)
E
Eric Blake 已提交
604
{
605
    virStorageDriverStatePtr driver = conn->storagePrivateData;
606
    virStoragePoolDefPtr def;
607
    virStoragePoolObjPtr pool = NULL;
608
    virStoragePoolPtr ret = NULL;
609

E
Eric Blake 已提交
610 611
    virCheckFlags(0, NULL);

612
    storageDriverLock(driver);
613
    if (!(def = virStoragePoolDefParseString(xml)))
614
        goto cleanup;
615

616 617 618
    if (virStoragePoolDefineXMLEnsureACL(conn, def) < 0)
        goto cleanup;

619 620 621
    if (virStoragePoolObjIsDuplicate(&driver->pools, def, 0) < 0)
        goto cleanup;

622 623 624
    if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
        goto cleanup;

625
    if (virStorageBackendForType(def->type) == NULL)
626
        goto cleanup;
627

628
    if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
629
        goto cleanup;
630

631
    if (virStoragePoolObjSaveDef(driver, pool, def) < 0) {
632
        virStoragePoolObjRemove(&driver->pools, pool);
633
        def = NULL;
634
        goto cleanup;
635
    }
636
    def = NULL;
637

638
    VIR_INFO("Defining storage pool '%s'", pool->def->name);
639 640
    ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid,
                            NULL, NULL);
641 642 643

cleanup:
    virStoragePoolDefFree(def);
644 645 646
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
647 648 649 650 651
    return ret;
}

static int
storagePoolUndefine(virStoragePoolPtr obj) {
652 653 654
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
655

656
    storageDriverLock(driver);
657
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
658
    if (!pool) {
659
        virReportError(VIR_ERR_NO_STORAGE_POOL,
660
                       _("no storage pool with matching uuid %s"), obj->uuid);
661
        goto cleanup;
662 663
    }

664 665 666
    if (virStoragePoolUndefineEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

667
    if (virStoragePoolObjIsActive(pool)) {
668
        virReportError(VIR_ERR_OPERATION_INVALID,
669 670
                       _("storage pool '%s' is still active"),
                       pool->def->name);
671
        goto cleanup;
672 673
    }

674
    if (pool->asyncjobs > 0) {
675 676 677
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
                       pool->def->name);
678 679 680
        goto cleanup;
    }

681
    if (virStoragePoolObjDeleteDef(pool) < 0)
682
        goto cleanup;
683

684 685
    if (unlink(pool->autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
        char ebuf[1024];
686
        VIR_ERROR(_("Failed to delete autostart link '%s': %s"),
687
                  pool->autostartLink, virStrerror(errno, ebuf, sizeof(ebuf)));
688
    }
689

690 691
    VIR_FREE(pool->configFile);
    VIR_FREE(pool->autostartLink);
692

693
    VIR_INFO("Undefining storage pool '%s'", pool->def->name);
694
    virStoragePoolObjRemove(&driver->pools, pool);
695
    pool = NULL;
696
    ret = 0;
697

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

static int
706 707
storagePoolCreate(virStoragePoolPtr obj,
                  unsigned int flags)
E
Eric Blake 已提交
708
{
709 710
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
711
    virStorageBackendPtr backend;
712
    int ret = -1;
713

E
Eric Blake 已提交
714 715
    virCheckFlags(0, -1);

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

720
    if (!pool) {
721
        virReportError(VIR_ERR_NO_STORAGE_POOL,
722
                       _("no storage pool with matching uuid %s"), obj->uuid);
723
        goto cleanup;
724 725
    }

726 727 728
    if (virStoragePoolCreateEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

729 730
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
731 732

    if (virStoragePoolObjIsActive(pool)) {
733
        virReportError(VIR_ERR_OPERATION_INVALID,
734 735
                       _("storage pool '%s' is already active"),
                       pool->def->name);
736
        goto cleanup;
737 738 739
    }
    if (backend->startPool &&
        backend->startPool(obj->conn, pool) < 0)
740 741
        goto cleanup;

742 743 744
    if (backend->refreshPool(obj->conn, pool) < 0) {
        if (backend->stopPool)
            backend->stopPool(obj->conn, pool);
745
        goto cleanup;
746 747
    }

748
    VIR_INFO("Starting up storage pool '%s'", pool->def->name);
749
    pool->active = 1;
750
    ret = 0;
751

752
cleanup:
753 754
    if (pool)
        virStoragePoolObjUnlock(pool);
755
    return ret;
756 757 758 759 760
}

static int
storagePoolBuild(virStoragePoolPtr obj,
                 unsigned int flags) {
761 762
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
763
    virStorageBackendPtr backend;
764
    int ret = -1;
765

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

770
    if (!pool) {
771
        virReportError(VIR_ERR_NO_STORAGE_POOL,
772
                       _("no storage pool with matching uuid %s"), obj->uuid);
773
        goto cleanup;
774 775
    }

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

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

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

    if (backend->buildPool &&
        backend->buildPool(obj->conn, pool, flags) < 0)
791 792
        goto cleanup;
    ret = 0;
793

794
cleanup:
795 796
    if (pool)
        virStoragePoolObjUnlock(pool);
797
    return ret;
798 799 800 801 802
}


static int
storagePoolDestroy(virStoragePoolPtr obj) {
803 804
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
805
    virStorageBackendPtr backend;
806
    int ret = -1;
807

808
    storageDriverLock(driver);
809
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
810

811
    if (!pool) {
812
        virReportError(VIR_ERR_NO_STORAGE_POOL,
813
                       _("no storage pool with matching uuid %s"), obj->uuid);
814
        goto cleanup;
815 816
    }

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

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

    if (!virStoragePoolObjIsActive(pool)) {
824
        virReportError(VIR_ERR_OPERATION_INVALID,
825
                       _("storage pool '%s' is not active"), pool->def->name);
826
        goto cleanup;
827 828
    }

829
    if (pool->asyncjobs > 0) {
830 831 832
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
                       pool->def->name);
833 834 835
        goto cleanup;
    }

836 837
    if (backend->stopPool &&
        backend->stopPool(obj->conn, pool) < 0)
838
        goto cleanup;
839 840 841 842

    virStoragePoolObjClearVols(pool);

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

845
    if (pool->configFile == NULL) {
846
        virStoragePoolObjRemove(&driver->pools, pool);
847
        pool = NULL;
848 849 850 851
    } else if (pool->newDef) {
        virStoragePoolDefFree(pool->def);
        pool->def = pool->newDef;
        pool->newDef = NULL;
852
    }
853
    ret = 0;
854

855
cleanup:
856 857 858
    if (pool)
        virStoragePoolObjUnlock(pool);
    storageDriverUnlock(driver);
859
    return ret;
860 861 862 863 864
}

static int
storagePoolDelete(virStoragePoolPtr obj,
                  unsigned int flags) {
865 866
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
867
    virStorageBackendPtr backend;
868
    int ret = -1;
869

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

874
    if (!pool) {
875
        virReportError(VIR_ERR_NO_STORAGE_POOL,
876
                       _("no storage pool with matching uuid %s"), obj->uuid);
877
        goto cleanup;
878 879
    }

880 881 882
    if (virStoragePoolDeleteEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

883 884
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
885 886

    if (virStoragePoolObjIsActive(pool)) {
887
        virReportError(VIR_ERR_OPERATION_INVALID,
888 889
                       _("storage pool '%s' is still active"),
                       pool->def->name);
890
        goto cleanup;
891 892
    }

893
    if (pool->asyncjobs > 0) {
894 895
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
896 897 898 899
                              pool->def->name);
        goto cleanup;
    }

900
    if (!backend->deletePool) {
901 902
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("pool does not support pool deletion"));
903
        goto cleanup;
904 905
    }
    if (backend->deletePool(obj->conn, pool, flags) < 0)
906
        goto cleanup;
907
    VIR_INFO("Deleting storage pool '%s'", pool->def->name);
908
    ret = 0;
909

910
cleanup:
911 912
    if (pool)
        virStoragePoolObjUnlock(pool);
913
    return ret;
914 915 916 917 918
}


static int
storagePoolRefresh(virStoragePoolPtr obj,
E
Eric Blake 已提交
919 920
                   unsigned int flags)
{
921 922
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
923
    virStorageBackendPtr backend;
924
    int ret = -1;
925

E
Eric Blake 已提交
926 927
    virCheckFlags(0, -1);

928
    storageDriverLock(driver);
929
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
930

931
    if (!pool) {
932
        virReportError(VIR_ERR_NO_STORAGE_POOL,
933
                       _("no storage pool with matching uuid %s"), obj->uuid);
934
        goto cleanup;
935 936
    }

937 938 939
    if (virStoragePoolRefreshEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

940 941
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
        goto cleanup;
942 943

    if (!virStoragePoolObjIsActive(pool)) {
944
        virReportError(VIR_ERR_OPERATION_INVALID,
945
                       _("storage pool '%s' is not active"), pool->def->name);
946
        goto cleanup;
947 948
    }

949
    if (pool->asyncjobs > 0) {
950 951 952
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("pool '%s' has asynchronous jobs running."),
                       pool->def->name);
953 954 955
        goto cleanup;
    }

956
    virStoragePoolObjClearVols(pool);
957
    if (backend->refreshPool(obj->conn, pool) < 0) {
958 959 960 961 962
        if (backend->stopPool)
            backend->stopPool(obj->conn, pool);

        pool->active = 0;

963
        if (pool->configFile == NULL) {
964
            virStoragePoolObjRemove(&driver->pools, pool);
965 966
            pool = NULL;
        }
967
        goto cleanup;
968
    }
969
    ret = 0;
970

971
cleanup:
972 973
    if (pool)
        virStoragePoolObjUnlock(pool);
974
    storageDriverUnlock(driver);
975 976 977 978 979 980 981
    return ret;
}


static int
storagePoolGetInfo(virStoragePoolPtr obj,
                   virStoragePoolInfoPtr info) {
982 983 984
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
985

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

990
    if (!pool) {
991
        virReportError(VIR_ERR_NO_STORAGE_POOL,
992
                       _("no storage pool with matching uuid %s"), obj->uuid);
993
        goto cleanup;
994 995
    }

996 997 998
    if (virStoragePoolGetInfoEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

999
    if (virStorageBackendForType(pool->def->type) == NULL)
1000
        goto cleanup;
1001 1002 1003 1004 1005 1006 1007 1008 1009

    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;
1010
    ret = 0;
1011

1012
cleanup:
1013 1014
    if (pool)
        virStoragePoolObjUnlock(pool);
1015
    return ret;
1016 1017 1018
}

static char *
1019
storagePoolGetXMLDesc(virStoragePoolPtr obj,
E
Eric Blake 已提交
1020 1021
                      unsigned int flags)
{
1022 1023
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1024
    virStoragePoolDefPtr def;
1025
    char *ret = NULL;
1026

1027
    virCheckFlags(VIR_STORAGE_XML_INACTIVE, NULL);
E
Eric Blake 已提交
1028

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

1033
    if (!pool) {
1034
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1035
                       _("no storage pool with matching uuid %s"), obj->uuid);
1036
        goto cleanup;
1037 1038
    }

1039 1040 1041
    if (virStoragePoolGetXMLDescEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1042 1043 1044 1045 1046 1047
    if ((flags & VIR_STORAGE_XML_INACTIVE) && pool->newDef)
        def = pool->newDef;
    else
        def = pool->def;

    ret = virStoragePoolDefFormat(def);
1048 1049

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

static int
storagePoolGetAutostart(virStoragePoolPtr obj,
                        int *autostart) {
1058 1059 1060
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
1061

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

1066
    if (!pool) {
1067
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1068
                       _("no storage pool with matching uuid %s"), obj->uuid);
1069
        goto cleanup;
1070 1071
    }

1072 1073 1074
    if (virStoragePoolGetAutostartEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1075 1076 1077 1078 1079
    if (!pool->configFile) {
        *autostart = 0;
    } else {
        *autostart = pool->autostart;
    }
1080
    ret = 0;
1081

1082
cleanup:
1083 1084
    if (pool)
        virStoragePoolObjUnlock(pool);
1085
    return ret;
1086 1087 1088 1089 1090
}

static int
storagePoolSetAutostart(virStoragePoolPtr obj,
                        int autostart) {
1091 1092 1093
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
1094

1095
    storageDriverLock(driver);
1096
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1097

1098
    if (!pool) {
1099
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1100
                       _("no storage pool with matching uuid %s"), obj->uuid);
1101
        goto cleanup;
1102 1103
    }

1104 1105 1106
    if (virStoragePoolSetAutostartEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1107
    if (!pool->configFile) {
1108 1109
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("pool has no config file"));
1110
        goto cleanup;
1111 1112 1113 1114
    }

    autostart = (autostart != 0);

1115 1116
    if (pool->autostart != autostart) {
        if (autostart) {
1117 1118
            if (virFileMakePath(driver->autostartDir) < 0) {
                virReportSystemError(errno,
1119 1120
                                     _("cannot create autostart directory %s"),
                                     driver->autostartDir);
1121 1122
                goto cleanup;
            }
1123

1124
            if (symlink(pool->configFile, pool->autostartLink) < 0) {
1125
                virReportSystemError(errno,
1126 1127
                                     _("Failed to create symlink '%s' to '%s'"),
                                     pool->autostartLink, pool->configFile);
1128 1129 1130 1131 1132
                goto cleanup;
            }
        } else {
            if (unlink(pool->autostartLink) < 0 &&
                errno != ENOENT && errno != ENOTDIR) {
1133
                virReportSystemError(errno,
1134 1135
                                     _("Failed to delete symlink '%s'"),
                                     pool->autostartLink);
1136 1137
                goto cleanup;
            }
1138
        }
1139
        pool->autostart = autostart;
1140
    }
1141
    ret = 0;
1142

1143
cleanup:
1144 1145
    if (pool)
        virStoragePoolObjUnlock(pool);
1146
    storageDriverUnlock(driver);
1147
    return ret;
1148 1149 1150 1151
}


static int
1152
storagePoolNumOfVolumes(virStoragePoolPtr obj) {
1153 1154 1155
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
    int ret = -1;
1156

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

1161
    if (!pool) {
1162
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1163
                       _("no storage pool with matching uuid %s"), obj->uuid);
1164
        goto cleanup;
1165 1166
    }

1167 1168 1169
    if (virStoragePoolNumOfVolumesEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1170
    if (!virStoragePoolObjIsActive(pool)) {
1171
        virReportError(VIR_ERR_OPERATION_INVALID,
1172
                       _("storage pool '%s' is not active"), pool->def->name);
1173
        goto cleanup;
1174
    }
1175
    ret = pool->volumes.count;
1176

1177
cleanup:
1178 1179
    if (pool)
        virStoragePoolObjUnlock(pool);
1180
    return ret;
1181 1182 1183 1184 1185 1186
}

static int
storagePoolListVolumes(virStoragePoolPtr obj,
                       char **const names,
                       int maxnames) {
1187 1188
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1189
    int i, n = 0;
1190

1191 1192
    memset(names, 0, maxnames * sizeof(*names));

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

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

1203 1204 1205
    if (virStoragePoolListVolumesEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1206
    if (!virStoragePoolObjIsActive(pool)) {
1207
        virReportError(VIR_ERR_OPERATION_INVALID,
1208
                       _("storage pool '%s' is not active"), pool->def->name);
1209
        goto cleanup;
1210 1211
    }

1212
    for (i = 0; i < pool->volumes.count && n < maxnames; i++) {
1213
        if (VIR_STRDUP(names[n++], pool->volumes.objs[i]->name) < 0)
1214 1215 1216
            goto cleanup;
    }

1217
    virStoragePoolObjUnlock(pool);
1218
    return n;
1219 1220

 cleanup:
1221 1222
    if (pool)
        virStoragePoolObjUnlock(pool);
1223
    for (n = 0; n < maxnames; n++)
1224
        VIR_FREE(names[n]);
1225

1226
    memset(names, 0, maxnames * sizeof(*names));
1227 1228 1229
    return -1;
}

1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248
static int
storagePoolListAllVolumes(virStoragePoolPtr pool,
                          virStorageVolPtr **vols,
                          unsigned int flags) {
    virStorageDriverStatePtr driver = pool->conn->storagePrivateData;
    virStoragePoolObjPtr obj;
    int i;
    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) {
1249 1250 1251
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching uuid %s"),
                       pool->uuid);
1252 1253 1254
        goto cleanup;
    }

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

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

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

    if (VIR_ALLOC_N(tmp_vols, obj->volumes.count + 1) < 0) {
         virReportOOMError();
         goto cleanup;
    }

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

    if (obj)
        virStoragePoolObjUnlock(obj);

    return ret;
}
1302 1303

static virStorageVolPtr
1304 1305
storageVolLookupByName(virStoragePoolPtr obj,
                       const char *name) {
1306 1307
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1308
    virStorageVolDefPtr vol;
1309
    virStorageVolPtr ret = NULL;
1310

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

1315
    if (!pool) {
1316
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1317
                       _("no storage pool with matching uuid %s"), obj->uuid);
1318
        goto cleanup;
1319 1320 1321
    }

    if (!virStoragePoolObjIsActive(pool)) {
1322
        virReportError(VIR_ERR_OPERATION_INVALID,
1323
                       _("storage pool '%s' is not active"), pool->def->name);
1324
        goto cleanup;
1325 1326 1327 1328 1329
    }

    vol = virStorageVolDefFindByName(pool, name);

    if (!vol) {
1330 1331 1332
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       name);
1333
        goto cleanup;
1334 1335
    }

1336 1337 1338
    if (virStorageVolLookupByNameEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

1339 1340
    ret = virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key,
                           NULL, NULL);
1341 1342

cleanup:
1343 1344
    if (pool)
        virStoragePoolObjUnlock(pool);
1345
    return ret;
1346 1347 1348 1349
}


static virStorageVolPtr
1350 1351
storageVolLookupByKey(virConnectPtr conn,
                      const char *key) {
1352
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1353
    unsigned int i;
1354
    virStorageVolPtr ret = NULL;
1355

1356
    storageDriverLock(driver);
1357
    for (i = 0; i < driver->pools.count && !ret; i++) {
1358
        virStoragePoolObjLock(driver->pools.objs[i]);
1359 1360 1361
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
            virStorageVolDefPtr vol =
                virStorageVolDefFindByKey(driver->pools.objs[i], key);
1362

1363 1364 1365 1366
            if (vol) {
                if (virStorageVolLookupByKeyEnsureACL(conn, driver->pools.objs[i]->def, vol) < 0)
                    goto cleanup;

1367
                ret = virGetStorageVol(conn,
1368 1369
                                       driver->pools.objs[i]->def->name,
                                       vol->name,
1370 1371
                                       vol->key,
                                       NULL, NULL);
1372 1373
                goto cleanup;
            }
1374
        }
1375
        virStoragePoolObjUnlock(driver->pools.objs[i]);
1376 1377
    }

1378
    if (!ret)
1379
        virReportError(VIR_ERR_NO_STORAGE_VOL,
1380
                       _("no storage vol with matching key %s"), key);
1381

1382 1383
cleanup:
    storageDriverUnlock(driver);
1384
    return ret;
1385 1386 1387
}

static virStorageVolPtr
1388 1389
storageVolLookupByPath(virConnectPtr conn,
                       const char *path) {
1390
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1391
    unsigned int i;
1392
    virStorageVolPtr ret = NULL;
1393 1394 1395 1396 1397
    char *cleanpath;

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

1399
    storageDriverLock(driver);
1400
    for (i = 0; i < driver->pools.count && !ret; i++) {
1401
        virStoragePoolObjLock(driver->pools.objs[i]);
1402
        if (virStoragePoolObjIsActive(driver->pools.objs[i])) {
1403
            virStorageVolDefPtr vol;
1404 1405
            const char *stable_path;

1406
            stable_path = virStorageBackendStablePath(driver->pools.objs[i],
1407 1408
                                                      cleanpath,
                                                      false);
1409
            if (stable_path == NULL) {
1410 1411 1412 1413 1414
                /* 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);
1415
                virStoragePoolObjUnlock(driver->pools.objs[i]);
1416
                continue;
1417
            }
1418 1419 1420 1421

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

1423 1424 1425 1426
            if (vol) {
                if (virStorageVolLookupByPathEnsureACL(conn, driver->pools.objs[i]->def, vol) < 0)
                    goto cleanup;

1427 1428 1429
                ret = virGetStorageVol(conn,
                                       driver->pools.objs[i]->def->name,
                                       vol->name,
1430 1431
                                       vol->key,
                                       NULL, NULL);
1432 1433
                goto cleanup;
            }
1434
        }
1435
        virStoragePoolObjUnlock(driver->pools.objs[i]);
1436 1437
    }

1438
    if (!ret)
1439
        virReportError(VIR_ERR_NO_STORAGE_VOL,
1440
                       _("no storage vol with matching path %s"), path);
1441

1442
cleanup:
1443
    VIR_FREE(cleanpath);
1444
    storageDriverUnlock(driver);
1445
    return ret;
1446 1447
}

1448
static int storageVolDelete(virStorageVolPtr obj, unsigned int flags);
1449

1450
static virStorageVolPtr
1451 1452 1453
storageVolCreateXML(virStoragePoolPtr obj,
                    const char *xmldesc,
                    unsigned int flags)
E
Eric Blake 已提交
1454
{
1455 1456
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1457
    virStorageBackendPtr backend;
1458 1459
    virStorageVolDefPtr voldef = NULL;
    virStorageVolPtr ret = NULL, volobj = NULL;
1460

1461
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
E
Eric Blake 已提交
1462

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

1467
    if (!pool) {
1468
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1469
                       _("no storage pool with matching uuid %s"), obj->uuid);
1470
        goto cleanup;
1471 1472 1473
    }

    if (!virStoragePoolObjIsActive(pool)) {
1474
        virReportError(VIR_ERR_OPERATION_INVALID,
1475
                       _("storage pool '%s' is not active"), pool->def->name);
1476
        goto cleanup;
1477 1478 1479
    }

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

1482
    voldef = virStorageVolDefParseString(pool->def, xmldesc);
1483
    if (voldef == NULL)
1484
        goto cleanup;
1485

1486 1487 1488
    if (virStorageVolCreateXMLEnsureACL(obj->conn, pool->def, voldef) < 0)
        goto cleanup;

1489
    if (virStorageVolDefFindByName(pool, voldef->name)) {
1490
        virReportError(VIR_ERR_NO_STORAGE_VOL,
1491
                       _("storage vol '%s' already exists"), voldef->name);
1492
        goto cleanup;
1493 1494
    }

1495 1496
    if (VIR_REALLOC_N(pool->volumes.objs,
                      pool->volumes.count+1) < 0) {
1497
        virReportOOMError();
1498
        goto cleanup;
1499 1500
    }

1501
    if (!backend->createVol) {
1502 1503 1504
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("storage pool does not support volume "
                               "creation"));
1505
        goto cleanup;
1506 1507
    }

1508
    if (backend->createVol(obj->conn, pool, voldef) < 0) {
1509
        goto cleanup;
1510 1511
    }

1512 1513
    pool->volumes.objs[pool->volumes.count++] = voldef;
    volobj = virGetStorageVol(obj->conn, pool->def->name, voldef->name,
1514
                              voldef->key, NULL, NULL);
1515 1516 1517 1518
    if (!volobj) {
        pool->volumes.count--;
        goto cleanup;
    }
1519

1520
    if (backend->buildVol) {
1521 1522 1523 1524
        int buildret;
        virStorageVolDefPtr buildvoldef = NULL;

        if (VIR_ALLOC(buildvoldef) < 0) {
1525
            virReportOOMError();
1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540
            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);

1541
        buildret = backend->buildVol(obj->conn, pool, buildvoldef, flags);
1542

1543
        storageDriverLock(driver);
1544
        virStoragePoolObjLock(pool);
1545 1546
        storageDriverUnlock(driver);

1547 1548 1549 1550 1551 1552 1553 1554
        voldef->building = 0;
        pool->asyncjobs--;

        voldef = NULL;
        VIR_FREE(buildvoldef);

        if (buildret < 0) {
            virStoragePoolObjUnlock(pool);
1555
            storageVolDelete(volobj, 0);
1556 1557 1558 1559 1560 1561
            pool = NULL;
            goto cleanup;
        }

    }

1562
    VIR_INFO("Creating volume '%s' in storage pool '%s'",
1563
             volobj->name, pool->def->name);
1564 1565 1566
    ret = volobj;
    volobj = NULL;
    voldef = NULL;
1567

1568
cleanup:
1569
    virObjectUnref(volobj);
1570
    virStorageVolDefFree(voldef);
1571 1572
    if (pool)
        virStoragePoolObjUnlock(pool);
1573
    return ret;
1574 1575
}

1576
static virStorageVolPtr
1577 1578 1579 1580
storageVolCreateXMLFrom(virStoragePoolPtr obj,
                        const char *xmldesc,
                        virStorageVolPtr vobj,
                        unsigned int flags)
E
Eric Blake 已提交
1581
{
1582 1583 1584 1585 1586
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool, origpool = NULL;
    virStorageBackendPtr backend;
    virStorageVolDefPtr origvol = NULL, newvol = NULL;
    virStorageVolPtr ret = NULL, volobj = NULL;
1587
    int buildret;
1588

1589
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
E
Eric Blake 已提交
1590

1591 1592
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
1593
    if (pool && STRNEQ(obj->name, vobj->pool)) {
1594
        virStoragePoolObjUnlock(pool);
1595
        origpool = virStoragePoolObjFindByName(&driver->pools, vobj->pool);
1596
        virStoragePoolObjLock(pool);
1597
    }
1598 1599
    storageDriverUnlock(driver);
    if (!pool) {
1600
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1601
                       _("no storage pool with matching uuid %s"), obj->uuid);
1602 1603 1604
        goto cleanup;
    }

1605
    if (STRNEQ(obj->name, vobj->pool) && !origpool) {
1606 1607 1608
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       vobj->pool);
1609 1610 1611 1612
        goto cleanup;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1613
        virReportError(VIR_ERR_OPERATION_INVALID,
1614
                       _("storage pool '%s' is not active"), pool->def->name);
1615 1616 1617
        goto cleanup;
    }

1618
    if (origpool && !virStoragePoolObjIsActive(origpool)) {
1619
        virReportError(VIR_ERR_OPERATION_INVALID,
1620 1621
                       _("storage pool '%s' is not active"),
                       origpool->def->name);
1622 1623 1624 1625 1626 1627
        goto cleanup;
    }

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

1628
    origvol = virStorageVolDefFindByName(origpool ? origpool : pool, vobj->name);
1629
    if (!origvol) {
1630 1631 1632
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       vobj->name);
1633 1634 1635
        goto cleanup;
    }

1636
    newvol = virStorageVolDefParseString(pool->def, xmldesc);
1637 1638 1639
    if (newvol == NULL)
        goto cleanup;

1640 1641 1642
    if (virStorageVolCreateXMLFromEnsureACL(obj->conn, pool->def, newvol) < 0)
        goto cleanup;

1643
    if (virStorageVolDefFindByName(pool, newvol->name)) {
1644 1645 1646
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("storage volume name '%s' already in use."),
                       newvol->name);
1647 1648 1649 1650 1651 1652 1653
        goto cleanup;
    }

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

1654 1655 1656 1657 1658
    /* 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;

1659
    if (!backend->buildVolFrom) {
1660 1661
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("storage pool does not support volume creation from an existing volume"));
1662 1663 1664 1665
        goto cleanup;
    }

    if (origvol->building) {
1666 1667 1668
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       origvol->name);
1669 1670 1671 1672 1673 1674 1675 1676 1677
        goto cleanup;
    }

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

    if (VIR_REALLOC_N(pool->volumes.objs,
                      pool->volumes.count+1) < 0) {
1678
        virReportOOMError();
1679 1680 1681 1682 1683 1684 1685 1686 1687 1688
        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,
1689
                              newvol->key, NULL, NULL);
1690 1691 1692 1693 1694 1695 1696

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

1697
    if (origpool) {
1698 1699 1700 1701
        origpool->asyncjobs++;
        virStoragePoolObjUnlock(origpool);
    }

1702
    buildret = backend->buildVolFrom(obj->conn, pool, newvol, origvol, flags);
1703 1704 1705

    storageDriverLock(driver);
    virStoragePoolObjLock(pool);
1706
    if (origpool)
1707 1708 1709 1710 1711 1712 1713 1714
        virStoragePoolObjLock(origpool);
    storageDriverUnlock(driver);

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

1715
    if (origpool) {
1716 1717 1718 1719 1720 1721 1722
        origpool->asyncjobs--;
        virStoragePoolObjUnlock(origpool);
        origpool = NULL;
    }

    if (buildret < 0) {
        virStoragePoolObjUnlock(pool);
1723
        storageVolDelete(volobj, 0);
1724 1725 1726 1727
        pool = NULL;
        goto cleanup;
    }

1728
    VIR_INFO("Creating volume '%s' in storage pool '%s'",
1729
             volobj->name, pool->def->name);
1730 1731 1732 1733
    ret = volobj;
    volobj = NULL;

cleanup:
1734
    virObjectUnref(volobj);
1735 1736 1737
    virStorageVolDefFree(newvol);
    if (pool)
        virStoragePoolObjUnlock(pool);
1738
    if (origpool)
1739 1740 1741 1742
        virStoragePoolObjUnlock(origpool);
    return ret;
}

1743

1744
static int
1745 1746 1747 1748 1749
storageVolDownload(virStorageVolPtr obj,
                   virStreamPtr stream,
                   unsigned long long offset,
                   unsigned long long length,
                   unsigned int flags)
1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762
{
    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) {
1763
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1764 1765
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1766 1767 1768 1769
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1770
        virReportError(VIR_ERR_OPERATION_INVALID,
1771
                       _("storage pool '%s' is not active"), pool->def->name);
1772 1773 1774 1775 1776 1777
        goto out;
    }

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

    if (vol == NULL) {
1778 1779 1780
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1781 1782 1783
        goto out;
    }

1784 1785 1786
    if (virStorageVolDownloadEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

1787
    if (vol->building) {
1788 1789 1790
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1791 1792 1793 1794 1795 1796
        goto out;
    }

    if (virFDStreamOpenFile(stream,
                            vol->target.path,
                            offset, length,
E
Eric Blake 已提交
1797
                            O_RDONLY) < 0)
1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810
        goto out;

    ret = 0;

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}


static int
1811 1812 1813 1814 1815
storageVolUpload(virStorageVolPtr obj,
                 virStreamPtr stream,
                 unsigned long long offset,
                 unsigned long long length,
                 unsigned int flags)
1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828
{
    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) {
1829
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1830 1831
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1832 1833 1834 1835
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1836
        virReportError(VIR_ERR_OPERATION_INVALID,
1837
                       _("storage pool '%s' is not active"), pool->def->name);
1838 1839 1840 1841 1842 1843
        goto out;
    }

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

    if (vol == NULL) {
1844 1845 1846
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1847 1848 1849
        goto out;
    }

1850 1851 1852
    if (virStorageVolUploadEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

1853
    if (vol->building) {
1854 1855 1856
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1857 1858 1859 1860 1861 1862 1863 1864
        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 已提交
1865
                            O_WRONLY) < 0)
1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876
        goto out;

    ret = 0;

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}

1877
static int
1878 1879 1880
storageVolResize(virStorageVolPtr obj,
                 unsigned long long capacity,
                 unsigned int flags)
1881 1882 1883 1884 1885 1886 1887 1888
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStorageBackendPtr backend;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    unsigned long long abs_capacity;
    int ret = -1;

1889
    virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE |
1890 1891
                  VIR_STORAGE_VOL_RESIZE_DELTA |
                  VIR_STORAGE_VOL_RESIZE_SHRINK, -1);
1892 1893 1894 1895 1896 1897

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

    if (!pool) {
1898 1899 1900
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
1901 1902 1903 1904
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
1905 1906
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), pool->def->name);
1907 1908 1909 1910 1911 1912 1913 1914 1915
        goto out;
    }

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

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

    if (vol == NULL) {
1916 1917 1918
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
1919 1920 1921
        goto out;
    }

1922 1923 1924
    if (virStorageVolResizeEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

1925
    if (vol->building) {
1926 1927 1928
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
1929 1930
        goto out;
    }
1931

1932 1933 1934 1935 1936 1937 1938 1939
    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) {
1940
        virReportError(VIR_ERR_INVALID_ARG, "%s",
1941 1942
                       _("can't shrink capacity below "
                         "existing allocation"));
1943 1944 1945
        goto out;
    }

1946 1947 1948 1949 1950 1951 1952 1953
    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;
    }

1954
    if (abs_capacity > vol->capacity + pool->def->available) {
1955
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
1956
                       _("Not enough space left on storage pool"));
1957 1958 1959 1960
        goto out;
    }

    if (!backend->resizeVol) {
1961
        virReportError(VIR_ERR_NO_SUPPORT, "%s",
1962 1963
                       _("storage pool does not support changing of "
                         "volume capacity"));
1964 1965 1966 1967 1968 1969
        goto out;
    }

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

O
Osier Yang 已提交
1970 1971
    vol->capacity = abs_capacity;
    ret = 0;
1972 1973 1974 1975 1976 1977 1978

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
1979

1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994
/* 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
1995 1996 1997
storageVolZeroSparseFile(virStorageVolDefPtr vol,
                         off_t size,
                         int fd)
1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
{
    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 "
2014
                               "path '%s' to %ju bytes"),
E
Eric Blake 已提交
2015
                             vol->target.path, (uintmax_t)size);
2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036
    }

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 已提交
2037
              (uintmax_t)extent_start, (uintmax_t)extent_length);
2038 2039 2040 2041 2042

    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 已提交
2043
                             (uintmax_t)extent_start, vol->target.path);
2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064
        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;
    }

2065 2066 2067 2068 2069 2070 2071 2072
    if (fdatasync(fd) < 0) {
        ret = -errno;
        virReportSystemError(errno,
                             _("cannot sync data to volume with path '%s'"),
                             vol->target.path);
        goto out;
    }

2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083
    VIR_DEBUG("Wrote %zu bytes to volume with path '%s'",
              *bytes_wiped, vol->target.path);

    ret = 0;

out:
    return ret;
}


static int
2084 2085
storageVolWipeInternal(virStorageVolDefPtr def,
                       unsigned int algorithm)
2086 2087 2088 2089 2090
{
    int ret = -1, fd = -1;
    struct stat st;
    char *writebuf = NULL;
    size_t bytes_wiped = 0;
2091
    virCommandPtr cmd = NULL;
2092

2093 2094
    VIR_DEBUG("Wiping volume with path '%s' and algorithm %u",
              def->target.path, algorithm);
2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110

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

2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126
    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 已提交
2127
            alg_char = "schneier";
2128 2129 2130 2131 2132
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7:
            alg_char = "pfitzner7";
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33:
M
Michal Privoznik 已提交
2133
            alg_char = "pfitzner33";
2134 2135 2136 2137 2138
            break;
        case VIR_STORAGE_VOL_WIPE_ALG_RANDOM:
            alg_char = "random";
            break;
        default:
2139 2140 2141
            virReportError(VIR_ERR_INVALID_ARG,
                           _("unsupported algorithm %d"),
                           algorithm);
2142 2143 2144 2145
        }
        cmd = virCommandNew(SCRUB);
        virCommandAddArgList(cmd, "-f", "-p", alg_char,
                             def->target.path, NULL);
2146

2147
        if (virCommandRun(cmd, NULL) < 0)
2148 2149
            goto out;

2150 2151 2152 2153
        ret = 0;
        goto out;
    } else {
        if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) {
2154
            ret = storageVolZeroSparseFile(def, st.st_size, fd);
2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169
        } else {

            if (VIR_ALLOC_N(writebuf, st.st_blksize) != 0) {
                virReportOOMError();
                goto out;
            }

            ret = storageWipeExtent(def,
                                    fd,
                                    0,
                                    def->allocation,
                                    writebuf,
                                    st.st_blksize,
                                    &bytes_wiped);
        }
2170 2171 2172
    }

out:
2173
    virCommandFree(cmd);
2174
    VIR_FREE(writebuf);
2175
    VIR_FORCE_CLOSE(fd);
2176 2177 2178 2179 2180
    return ret;
}


static int
2181 2182 2183
storageVolWipePattern(virStorageVolPtr obj,
                      unsigned int algorithm,
                      unsigned int flags)
2184 2185 2186 2187 2188 2189
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    int ret = -1;

2190
    virCheckFlags(0, -1);
2191

2192
    if (algorithm >= VIR_STORAGE_VOL_WIPE_ALG_LAST) {
2193 2194 2195
        virReportError(VIR_ERR_INVALID_ARG,
                       _("wiping algorithm %d not supported"),
                       algorithm);
2196 2197 2198
        return -1;
    }

2199 2200 2201 2202 2203
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
    storageDriverUnlock(driver);

    if (!pool) {
2204
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2205 2206
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2207 2208 2209 2210
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
2211
        virReportError(VIR_ERR_OPERATION_INVALID,
2212
                       _("storage pool '%s' is not active"), pool->def->name);
2213 2214 2215 2216 2217 2218
        goto out;
    }

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

    if (vol == NULL) {
2219 2220 2221
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2222 2223 2224
        goto out;
    }

2225 2226 2227
    if (virStorageVolWipePatternEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

2228
    if (vol->building) {
2229 2230 2231
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
2232 2233 2234
        goto out;
    }

2235
    if (storageVolWipeInternal(vol, algorithm) == -1) {
2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249
        goto out;
    }

    ret = 0;

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

    return ret;

}

2250
static int
2251 2252
storageVolWipe(virStorageVolPtr obj,
               unsigned int flags)
2253
{
2254
    return storageVolWipePattern(obj, VIR_STORAGE_VOL_WIPE_ALG_ZERO, flags);
2255 2256
}

2257
static int
2258 2259
storageVolDelete(virStorageVolPtr obj,
                 unsigned int flags) {
2260 2261
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2262
    virStorageBackendPtr backend;
2263
    virStorageVolDefPtr vol = NULL;
2264
    unsigned int i;
2265
    int ret = -1;
2266

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

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

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

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2285
        goto cleanup;
2286 2287 2288 2289

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

    if (!vol) {
2290 2291 2292
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2293
        goto cleanup;
2294 2295
    }

2296 2297 2298
    if (virStorageVolDeleteEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2299
    if (vol->building) {
2300 2301 2302
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
2303 2304 2305
        goto cleanup;
    }

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

2310
        goto cleanup;
2311 2312
    }

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

2316
    for (i = 0; i < pool->volumes.count; i++) {
2317
        if (pool->volumes.objs[i] == vol) {
2318
            VIR_INFO("Deleting volume '%s' from storage pool '%s'",
2319
                     vol->name, pool->def->name);
2320
            virStorageVolDefFree(vol);
2321
            vol = NULL;
2322 2323 2324 2325 2326 2327 2328 2329 2330 2331

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

2332 2333 2334
            break;
        }
    }
2335
    ret = 0;
2336

2337
cleanup:
2338 2339
    if (pool)
        virStoragePoolObjUnlock(pool);
2340
    return ret;
2341 2342 2343
}

static int
2344 2345
storageVolGetInfo(virStorageVolPtr obj,
                  virStorageVolInfoPtr info) {
2346 2347
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2348 2349
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
2350
    int ret = -1;
2351

2352
    storageDriverLock(driver);
2353
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2354 2355
    storageDriverUnlock(driver);

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

    if (!virStoragePoolObjIsActive(pool)) {
2364
        virReportError(VIR_ERR_OPERATION_INVALID,
2365
                       _("storage pool '%s' is not active"), pool->def->name);
2366
        goto cleanup;
2367 2368 2369 2370 2371
    }

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

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

2378 2379 2380
    if (virStorageVolGetInfoEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2381
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2382
        goto cleanup;
2383 2384 2385

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

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

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

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

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

2412
    storageDriverLock(driver);
2413
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2414 2415
    storageDriverUnlock(driver);

2416
    if (!pool) {
2417
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2418 2419
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2420
        goto cleanup;
2421 2422 2423
    }

    if (!virStoragePoolObjIsActive(pool)) {
2424
        virReportError(VIR_ERR_OPERATION_INVALID,
2425
                       _("storage pool '%s' is not active"), pool->def->name);
2426
        goto cleanup;
2427 2428 2429 2430 2431
    }

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

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

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

2441
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2442
        goto cleanup;
2443 2444 2445 2446

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

2448
    ret = virStorageVolDefFormat(pool->def, vol);
2449 2450

cleanup:
2451 2452 2453
    if (pool)
        virStoragePoolObjUnlock(pool);

2454
    return ret;
2455 2456 2457
}

static char *
2458
storageVolGetPath(virStorageVolPtr obj) {
2459
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
2460
    virStoragePoolObjPtr pool;
2461
    virStorageVolDefPtr vol;
2462
    char *ret = NULL;
2463

2464 2465 2466
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
    storageDriverUnlock(driver);
2467
    if (!pool) {
2468
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2469 2470
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2471
        goto cleanup;
2472 2473 2474
    }

    if (!virStoragePoolObjIsActive(pool)) {
2475
        virReportError(VIR_ERR_OPERATION_INVALID,
2476
                       _("storage pool '%s' is not active"), pool->def->name);
2477
        goto cleanup;
2478 2479 2480 2481 2482
    }

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

    if (!vol) {
2483 2484 2485
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2486
        goto cleanup;
2487 2488
    }

2489 2490 2491
    if (virStorageVolGetPathEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2492
    ignore_value(VIR_STRDUP(ret, vol->target.path));
2493 2494

cleanup:
2495 2496
    if (pool)
        virStoragePoolObjUnlock(pool);
2497 2498 2499
    return ret;
}

2500
static int
2501 2502 2503
storageConnectListAllStoragePools(virConnectPtr conn,
                                  virStoragePoolPtr **pools,
                                  unsigned int flags)
2504 2505 2506 2507 2508 2509
{
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

2510 2511 2512
    if (virConnectListAllStoragePoolsEnsureACL(conn) < 0)
        goto cleanup;

2513 2514 2515 2516
    storageDriverLock(driver);
    ret = virStoragePoolList(conn, driver->pools, pools, flags);
    storageDriverUnlock(driver);

2517
cleanup:
2518 2519 2520
    return ret;
}

2521
static virStorageDriver storageDriver = {
2522
    .name = "storage",
2523 2524
    .storageOpen = storageOpen, /* 0.4.0 */
    .storageClose = storageClose, /* 0.4.0 */
2525 2526 2527 2528 2529 2530
    .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 */
2531 2532 2533
    .storagePoolLookupByName = storagePoolLookupByName, /* 0.4.0 */
    .storagePoolLookupByUUID = storagePoolLookupByUUID, /* 0.4.0 */
    .storagePoolLookupByVolume = storagePoolLookupByVolume, /* 0.4.0 */
2534 2535
    .storagePoolCreateXML = storagePoolCreateXML, /* 0.4.0 */
    .storagePoolDefineXML = storagePoolDefineXML, /* 0.4.0 */
2536 2537
    .storagePoolBuild = storagePoolBuild, /* 0.4.0 */
    .storagePoolUndefine = storagePoolUndefine, /* 0.4.0 */
2538
    .storagePoolCreate = storagePoolCreate, /* 0.4.0 */
2539 2540 2541 2542 2543 2544 2545
    .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 */
2546
    .storagePoolNumOfVolumes = storagePoolNumOfVolumes, /* 0.4.0 */
2547 2548 2549
    .storagePoolListVolumes = storagePoolListVolumes, /* 0.4.0 */
    .storagePoolListAllVolumes = storagePoolListAllVolumes, /* 0.10.2 */

2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563
    .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 */
2564 2565 2566

    .storagePoolIsActive = storagePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = storagePoolIsPersistent, /* 0.7.3 */
2567 2568 2569 2570
};


static virStateDriver stateDriver = {
2571
    .name = "Storage",
2572 2573 2574
    .stateInitialize = storageStateInitialize,
    .stateCleanup = storageStateCleanup,
    .stateReload = storageStateReload,
2575 2576 2577 2578 2579 2580 2581
};

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