storage_driver.c 74.3 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 352 353 354
        virStoragePoolObjPtr obj = driver->pools.objs[i];
        virStoragePoolObjLock(obj);
        if (virConnectNumOfStoragePoolsCheckACL(conn, obj->def) &&
            virStoragePoolObjIsActive(obj))
355
            nactive++;
356
        virStoragePoolObjUnlock(obj);
357 358
    }
    storageDriverUnlock(driver);
359 360

    return nactive;
361 362 363
}

static int
364 365 366
storageConnectListStoragePools(virConnectPtr conn,
                               char **const names,
                               int nnames) {
367
    virStorageDriverStatePtr driver = conn->storagePrivateData;
368
    int got = 0, 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
    unsigned int i, nactive = 0;

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

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

    return nactive;
418 419 420
}

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

427 428 429
    if (virConnectListDefinedStoragePoolsEnsureACL(conn) < 0)
        return -1;

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

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

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

468 469 470
    if (virConnectFindStoragePoolSourcesEnsureACL(conn) < 0)
        return NULL;

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

    backend = virStorageBackendForType(backend_type);
    if (backend == NULL)
480
        goto cleanup;
481

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

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

491 492
cleanup:
    return ret;
493 494 495
}


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

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

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

513 514 515 516 517 518 519 520
    ret = virStoragePoolObjIsActive(obj);

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

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

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

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

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

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


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

E
Eric Blake 已提交
558 559
    virCheckFlags(0, NULL);

560
    storageDriverLock(driver);
561
    if (!(def = virStoragePoolDefParseString(xml)))
562
        goto cleanup;
563

564 565 566
    if (virStoragePoolCreateXMLEnsureACL(conn, def) < 0)
        goto cleanup;

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

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

573 574
    if ((backend = virStorageBackendForType(def->type)) == NULL)
        goto cleanup;
575

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

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

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

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

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

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

E
Eric Blake 已提交
618 619
    virCheckFlags(0, NULL);

620
    storageDriverLock(driver);
621
    if (!(def = virStoragePoolDefParseString(xml)))
622
        goto cleanup;
623

624 625 626
    if (virStoragePoolDefineXMLEnsureACL(conn, def) < 0)
        goto cleanup;

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

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

633
    if (virStorageBackendForType(def->type) == NULL)
634
        goto cleanup;
635

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

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

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

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

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

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

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

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

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

689
    if (virStoragePoolObjDeleteDef(pool) < 0)
690
        goto cleanup;
691

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

698 699
    VIR_FREE(pool->configFile);
    VIR_FREE(pool->autostartLink);
700

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

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

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

E
Eric Blake 已提交
722 723
    virCheckFlags(0, -1);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

    virStoragePoolObjClearVols(pool);

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

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

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

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

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

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

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

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

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

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

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

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


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

E
Eric Blake 已提交
934 935
    virCheckFlags(0, -1);

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

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

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

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

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

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

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

        pool->active = 0;

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

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


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

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

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

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

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

    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;
1018
    ret = 0;
1019

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

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

1035
    virCheckFlags(VIR_STORAGE_XML_INACTIVE, NULL);
E
Eric Blake 已提交
1036

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

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

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

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

    ret = virStoragePoolDefFormat(def);
1056 1057

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

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

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

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

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

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

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

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

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

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

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

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

    autostart = (autostart != 0);

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

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

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


static int
1160
storagePoolNumOfVolumes(virStoragePoolPtr obj) {
1161 1162
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1163
    int ret = -1, i;
1164

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

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

1175 1176 1177
    if (virStoragePoolNumOfVolumesEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

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

1190
cleanup:
1191 1192
    if (pool)
        virStoragePoolObjUnlock(pool);
1193
    return ret;
1194 1195 1196 1197 1198 1199
}

static int
storagePoolListVolumes(virStoragePoolPtr obj,
                       char **const names,
                       int maxnames) {
1200 1201
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
1202
    int i, n = 0;
1203

1204 1205
    memset(names, 0, maxnames * sizeof(*names));

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

1210
    if (!pool) {
1211
        virReportError(VIR_ERR_NO_STORAGE_POOL,
1212
                       _("no storage pool with matching uuid %s"), obj->uuid);
1213
        goto cleanup;
1214 1215
    }

1216 1217 1218
    if (virStoragePoolListVolumesEnsureACL(obj->conn, pool->def) < 0)
        goto cleanup;

1219
    if (!virStoragePoolObjIsActive(pool)) {
1220
        virReportError(VIR_ERR_OPERATION_INVALID,
1221
                       _("storage pool '%s' is not active"), pool->def->name);
1222
        goto cleanup;
1223 1224
    }

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

1233
    virStoragePoolObjUnlock(pool);
1234
    return n;
1235 1236

 cleanup:
1237 1238
    if (pool)
        virStoragePoolObjUnlock(pool);
1239
    for (n = 0; n < maxnames; n++)
1240
        VIR_FREE(names[n]);
1241

1242
    memset(names, 0, maxnames * sizeof(*names));
1243 1244 1245
    return -1;
}

1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264
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) {
1265 1266 1267
        virReportError(VIR_ERR_NO_STORAGE_POOL,
                       _("no storage pool with matching uuid %s"),
                       pool->uuid);
1268 1269 1270
        goto cleanup;
    }

1271 1272 1273
    if (virStoragePoolListAllVolumesEnsureACL(pool->conn, obj->def) < 0)
        goto cleanup;

1274
    if (!virStoragePoolObjIsActive(obj)) {
1275 1276
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("storage pool '%s' is not active"), obj->def->name);
1277 1278 1279 1280 1281 1282 1283 1284 1285 1286
        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) {
1287 1288
        virReportOOMError();
        goto cleanup;
1289 1290
    }

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

    if (obj)
        virStoragePoolObjUnlock(obj);

    return ret;
}
1321 1322

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

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

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

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

    vol = virStorageVolDefFindByName(pool, name);

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

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

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

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


static virStorageVolPtr
1369 1370
storageVolLookupByKey(virConnectPtr conn,
                      const char *key) {
1371
    virStorageDriverStatePtr driver = conn->storagePrivateData;
1372
    unsigned int i;
1373
    virStorageVolPtr ret = NULL;
1374

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

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

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

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

1402 1403
cleanup:
    storageDriverUnlock(driver);
1404
    return ret;
1405 1406 1407
}

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

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

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

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

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

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

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

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

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

1469
static int storageVolDelete(virStorageVolPtr obj, unsigned int flags);
1470

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

1482
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
E
Eric Blake 已提交
1483

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

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

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

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

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

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

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

1516 1517
    if (VIR_REALLOC_N(pool->volumes.objs,
                      pool->volumes.count+1) < 0) {
1518
        virReportOOMError();
1519
        goto cleanup;
1520 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
        int buildret;
        virStorageVolDefPtr buildvoldef = NULL;

        if (VIR_ALLOC(buildvoldef) < 0) {
1546
            virReportOOMError();
1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561
            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);

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

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

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

        voldef = NULL;
        VIR_FREE(buildvoldef);

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

    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    if (origvol->building) {
1687 1688 1689
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       origvol->name);
1690 1691 1692 1693 1694 1695 1696 1697 1698
        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) {
1699
        virReportOOMError();
1700 1701 1702 1703 1704 1705 1706 1707 1708 1709
        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,
1710
                              newvol->key, NULL, NULL);
1711 1712 1713 1714 1715 1716 1717

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

1718
    if (origpool) {
1719 1720 1721 1722
        origpool->asyncjobs++;
        virStoragePoolObjUnlock(origpool);
    }

1723
    buildret = backend->buildVolFrom(obj->conn, pool, newvol, origvol, flags);
1724 1725 1726

    storageDriverLock(driver);
    virStoragePoolObjLock(pool);
1727
    if (origpool)
1728 1729 1730 1731 1732 1733 1734 1735
        virStoragePoolObjLock(origpool);
    storageDriverUnlock(driver);

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

1736
    if (origpool) {
1737 1738 1739 1740 1741 1742 1743
        origpool->asyncjobs--;
        virStoragePoolObjUnlock(origpool);
        origpool = NULL;
    }

    if (buildret < 0) {
        virStoragePoolObjUnlock(pool);
1744
        storageVolDelete(volobj, 0);
1745 1746 1747 1748
        pool = NULL;
        goto cleanup;
    }

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

cleanup:
1755
    virObjectUnref(volobj);
1756 1757 1758
    virStorageVolDefFree(newvol);
    if (pool)
        virStoragePoolObjUnlock(pool);
1759
    if (origpool)
1760 1761 1762 1763
        virStoragePoolObjUnlock(origpool);
    return ret;
}

1764

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

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

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

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

1805 1806 1807
    if (virStorageVolDownloadEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

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

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

    ret = 0;

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}


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

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

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

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

1871 1872 1873
    if (virStorageVolUploadEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

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

    ret = 0;

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}

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

1910
    virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE |
1911 1912
                  VIR_STORAGE_VOL_RESIZE_DELTA |
                  VIR_STORAGE_VOL_RESIZE_SHRINK, -1);
1913 1914 1915 1916 1917 1918

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

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

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

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

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

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

1943 1944 1945
    if (virStorageVolResizeEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

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

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

1967 1968 1969 1970 1971 1972 1973 1974
    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;
    }

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

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

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

O
Osier Yang 已提交
1991 1992
    vol->capacity = abs_capacity;
    ret = 0;
1993 1994 1995 1996 1997 1998 1999

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
2000

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

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 已提交
2058
              (uintmax_t)extent_start, (uintmax_t)extent_length);
2059 2060 2061 2062 2063

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

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

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

    ret = 0;

out:
    return ret;
}


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

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

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

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

2168
        if (virCommandRun(cmd, NULL) < 0)
2169 2170
            goto out;

2171 2172 2173 2174
        ret = 0;
        goto out;
    } else {
        if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) {
2175
            ret = storageVolZeroSparseFile(def, st.st_size, fd);
2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190
        } 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);
        }
2191 2192 2193
    }

out:
2194
    virCommandFree(cmd);
2195
    VIR_FREE(writebuf);
2196
    VIR_FORCE_CLOSE(fd);
2197 2198 2199 2200 2201
    return ret;
}


static int
2202 2203 2204
storageVolWipePattern(virStorageVolPtr obj,
                      unsigned int algorithm,
                      unsigned int flags)
2205 2206 2207 2208 2209 2210
{
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool = NULL;
    virStorageVolDefPtr vol = NULL;
    int ret = -1;

2211
    virCheckFlags(0, -1);
2212

2213
    if (algorithm >= VIR_STORAGE_VOL_WIPE_ALG_LAST) {
2214 2215 2216
        virReportError(VIR_ERR_INVALID_ARG,
                       _("wiping algorithm %d not supported"),
                       algorithm);
2217 2218 2219
        return -1;
    }

2220 2221 2222 2223 2224
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
    storageDriverUnlock(driver);

    if (!pool) {
2225
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2226 2227
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2228 2229 2230 2231
        goto out;
    }

    if (!virStoragePoolObjIsActive(pool)) {
2232
        virReportError(VIR_ERR_OPERATION_INVALID,
2233
                       _("storage pool '%s' is not active"), pool->def->name);
2234 2235 2236 2237 2238 2239
        goto out;
    }

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

    if (vol == NULL) {
2240 2241 2242
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2243 2244 2245
        goto out;
    }

2246 2247 2248
    if (virStorageVolWipePatternEnsureACL(obj->conn, pool->def, vol) < 0)
        goto out;

2249
    if (vol->building) {
2250 2251 2252
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
2253 2254 2255
        goto out;
    }

2256
    if (storageVolWipeInternal(vol, algorithm) == -1) {
2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270
        goto out;
    }

    ret = 0;

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

    return ret;

}

2271
static int
2272 2273
storageVolWipe(virStorageVolPtr obj,
               unsigned int flags)
2274
{
2275
    return storageVolWipePattern(obj, VIR_STORAGE_VOL_WIPE_ALG_ZERO, flags);
2276 2277
}

2278
static int
2279 2280
storageVolDelete(virStorageVolPtr obj,
                 unsigned int flags) {
2281 2282
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2283
    virStorageBackendPtr backend;
2284
    virStorageVolDefPtr vol = NULL;
2285
    unsigned int i;
2286
    int ret = -1;
2287

2288
    storageDriverLock(driver);
2289
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2290 2291
    storageDriverUnlock(driver);

2292
    if (!pool) {
2293
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2294 2295
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2296
        goto cleanup;
2297 2298 2299
    }

    if (!virStoragePoolObjIsActive(pool)) {
2300
        virReportError(VIR_ERR_OPERATION_INVALID,
2301
                       _("storage pool '%s' is not active"), pool->def->name);
2302
        goto cleanup;
2303 2304 2305
    }

    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2306
        goto cleanup;
2307 2308 2309 2310

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

    if (!vol) {
2311 2312 2313
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2314
        goto cleanup;
2315 2316
    }

2317 2318 2319
    if (virStorageVolDeleteEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2320
    if (vol->building) {
2321 2322 2323
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("volume '%s' is still being allocated."),
                       vol->name);
2324 2325 2326
        goto cleanup;
    }

2327
    if (!backend->deleteVol) {
2328 2329
        virReportError(VIR_ERR_NO_SUPPORT,
                       "%s", _("storage pool does not support vol deletion"));
2330

2331
        goto cleanup;
2332 2333
    }

2334 2335 2336
    if (backend->deleteVol(obj->conn, pool, vol, flags) < 0)
        goto cleanup;

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

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

2353 2354 2355
            break;
        }
    }
2356
    ret = 0;
2357

2358
cleanup:
2359 2360
    if (pool)
        virStoragePoolObjUnlock(pool);
2361
    return ret;
2362 2363 2364
}

static int
2365 2366
storageVolGetInfo(virStorageVolPtr obj,
                  virStorageVolInfoPtr info) {
2367 2368
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2369 2370
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
2371
    int ret = -1;
2372

2373
    storageDriverLock(driver);
2374
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2375 2376
    storageDriverUnlock(driver);

2377
    if (!pool) {
2378
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2379 2380
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2381
        goto cleanup;
2382 2383 2384
    }

    if (!virStoragePoolObjIsActive(pool)) {
2385
        virReportError(VIR_ERR_OPERATION_INVALID,
2386
                       _("storage pool '%s' is not active"), pool->def->name);
2387
        goto cleanup;
2388 2389 2390 2391 2392
    }

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

    if (!vol) {
2393 2394 2395
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2396
        goto cleanup;
2397 2398
    }

2399 2400 2401
    if (virStorageVolGetInfoEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2402
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2403
        goto cleanup;
2404 2405 2406

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

    memset(info, 0, sizeof(*info));
2410
    info->type = vol->type;
2411 2412
    info->capacity = vol->capacity;
    info->allocation = vol->allocation;
2413
    ret = 0;
2414

2415
cleanup:
2416 2417
    if (pool)
        virStoragePoolObjUnlock(pool);
2418
    return ret;
2419 2420 2421
}

static char *
2422 2423
storageVolGetXMLDesc(virStorageVolPtr obj,
                     unsigned int flags)
E
Eric Blake 已提交
2424
{
2425 2426
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
    virStoragePoolObjPtr pool;
2427 2428
    virStorageBackendPtr backend;
    virStorageVolDefPtr vol;
2429
    char *ret = NULL;
2430

E
Eric Blake 已提交
2431 2432
    virCheckFlags(0, NULL);

2433
    storageDriverLock(driver);
2434
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
2435 2436
    storageDriverUnlock(driver);

2437
    if (!pool) {
2438
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2439 2440
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2441
        goto cleanup;
2442 2443 2444
    }

    if (!virStoragePoolObjIsActive(pool)) {
2445
        virReportError(VIR_ERR_OPERATION_INVALID,
2446
                       _("storage pool '%s' is not active"), pool->def->name);
2447
        goto cleanup;
2448 2449 2450 2451 2452
    }

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

    if (!vol) {
2453 2454 2455
        virReportError(VIR_ERR_NO_STORAGE_VOL,
                       _("no storage vol with matching name '%s'"),
                       obj->name);
2456
        goto cleanup;
2457 2458
    }

2459 2460 2461
    if (virStorageVolGetXMLDescEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2462
    if ((backend = virStorageBackendForType(pool->def->type)) == NULL)
2463
        goto cleanup;
2464 2465 2466 2467

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

2469
    ret = virStorageVolDefFormat(pool->def, vol);
2470 2471

cleanup:
2472 2473 2474
    if (pool)
        virStoragePoolObjUnlock(pool);

2475
    return ret;
2476 2477 2478
}

static char *
2479
storageVolGetPath(virStorageVolPtr obj) {
2480
    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
2481
    virStoragePoolObjPtr pool;
2482
    virStorageVolDefPtr vol;
2483
    char *ret = NULL;
2484

2485 2486 2487
    storageDriverLock(driver);
    pool = virStoragePoolObjFindByName(&driver->pools, obj->pool);
    storageDriverUnlock(driver);
2488
    if (!pool) {
2489
        virReportError(VIR_ERR_NO_STORAGE_POOL,
2490 2491
                       _("no storage pool with matching name '%s'"),
                       obj->pool);
2492
        goto cleanup;
2493 2494 2495
    }

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

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

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

2510 2511 2512
    if (virStorageVolGetPathEnsureACL(obj->conn, pool->def, vol) < 0)
        goto cleanup;

2513
    ignore_value(VIR_STRDUP(ret, vol->target.path));
2514 2515

cleanup:
2516 2517
    if (pool)
        virStoragePoolObjUnlock(pool);
2518 2519 2520
    return ret;
}

2521
static int
2522 2523 2524
storageConnectListAllStoragePools(virConnectPtr conn,
                                  virStoragePoolPtr **pools,
                                  unsigned int flags)
2525 2526 2527 2528 2529 2530
{
    virStorageDriverStatePtr driver = conn->storagePrivateData;
    int ret = -1;

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

2531 2532 2533
    if (virConnectListAllStoragePoolsEnsureACL(conn) < 0)
        goto cleanup;

2534
    storageDriverLock(driver);
2535 2536
    ret = virStoragePoolObjListExport(conn, driver->pools, pools,
                                      virConnectListAllStoragePoolsCheckACL, flags);
2537 2538
    storageDriverUnlock(driver);

2539
cleanup:
2540 2541 2542
    return ret;
}

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

2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585
    .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 */
2586 2587 2588

    .storagePoolIsActive = storagePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = storagePoolIsPersistent, /* 0.7.3 */
2589 2590 2591 2592
};


static virStateDriver stateDriver = {
2593
    .name = "Storage",
2594 2595 2596
    .stateInitialize = storageStateInitialize,
    .stateCleanup = storageStateCleanup,
    .stateReload = storageStateReload,
2597 2598 2599 2600 2601 2602 2603
};

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