storage_driver.c 74.2 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 1383 1384 1385
            if (vol) {
                if (virStorageVolLookupByKeyEnsureACL(conn, driver->pools.objs[i]->def, vol) < 0)
                    goto cleanup;

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

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

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

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

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

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

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

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

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

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

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

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

1467
static int storageVolDelete(virStorageVolPtr obj, unsigned int flags);
1468

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

1480
    virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
E
Eric Blake 已提交
1481

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

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

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

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

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

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

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

1514 1515
    if (VIR_REALLOC_N(pool->volumes.objs,
                      pool->volumes.count+1) < 0) {
1516
        virReportOOMError();
1517
        goto cleanup;
1518 1519
    }

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

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

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

1539
    if (backend->buildVol) {
1540 1541 1542 1543
        int buildret;
        virStorageVolDefPtr buildvoldef = NULL;

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

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

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

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

        voldef = NULL;
        VIR_FREE(buildvoldef);

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

    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1762

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

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

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

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

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

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

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

    ret = 0;

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}


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

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

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

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

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

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

    ret = 0;

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

out:
    if (pool)
        virStoragePoolObjUnlock(pool);

    return ret;
}
1998

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

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

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

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

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

    ret = 0;

out:
    return ret;
}


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

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

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

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

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

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

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


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

2209
    virCheckFlags(0, -1);
2210

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

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

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

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

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

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

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

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

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

    ret = 0;

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

    return ret;

}

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

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

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

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

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

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

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

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

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

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

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

2329
        goto cleanup;
2330 2331
    }

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

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

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

2351 2352 2353
            break;
        }
    }
2354
    ret = 0;
2355

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

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

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

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

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

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

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

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

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

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

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

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

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

E
Eric Blake 已提交
2429 2430
    virCheckFlags(0, NULL);

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

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

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

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

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

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

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

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

2467
    ret = virStorageVolDefFormat(pool->def, vol);
2468 2469

cleanup:
2470 2471 2472
    if (pool)
        virStoragePoolObjUnlock(pool);

2473
    return ret;
2474 2475 2476
}

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

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

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

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

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

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

2511
    ignore_value(VIR_STRDUP(ret, vol->target.path));
2512 2513

cleanup:
2514 2515
    if (pool)
        virStoragePoolObjUnlock(pool);
2516 2517 2518
    return ret;
}

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

    virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1);

2529 2530 2531
    if (virConnectListAllStoragePoolsEnsureACL(conn) < 0)
        goto cleanup;

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

2537
cleanup:
2538 2539 2540
    return ret;
}

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

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

    .storagePoolIsActive = storagePoolIsActive, /* 0.7.3 */
    .storagePoolIsPersistent = storagePoolIsPersistent, /* 0.7.3 */
2587 2588 2589 2590
};


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

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