storage_backend_logical.c 27.4 KB
Newer Older
1
/*
2
 * storage_backend_logical.c: storage backend for logical volume handling
3
 *
4
 * Copyright (C) 2007-2014 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17
 * Copyright (C) 2007-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 29 30 31 32 33
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 */

#include <config.h>

#include <sys/wait.h>
#include <sys/stat.h>
#include <stdio.h>
#include <regex.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

34
#include "virerror.h"
35 36
#include "storage_backend_logical.h"
#include "storage_conf.h"
37
#include "vircommand.h"
38
#include "viralloc.h"
39
#include "virlog.h"
E
Eric Blake 已提交
40
#include "virfile.h"
41
#include "virstring.h"
42

43 44
#define VIR_FROM_THIS VIR_FROM_STORAGE

45 46
VIR_LOG_INIT("storage.storage_backend_logical");

47 48 49 50
#define PV_BLANK_SECTOR_SIZE 512


static int
51
virStorageBackendLogicalSetActive(virStoragePoolObjPtr pool,
52 53
                                  int on)
{
54 55 56 57 58 59 60 61 62 63
    int ret;
    virCommandPtr cmd =
        virCommandNewArgList(VGCHANGE,
                             on ? "-aly" : "-aln",
                             pool->def->source.name,
                             NULL);

    ret = virCommandRun(cmd, NULL);
    virCommandFree(cmd);
    return ret;
64 65 66
}


67 68
#define VIR_STORAGE_VOL_LOGICAL_SEGTYPE_STRIPED "striped"

69 70 71 72 73
struct virStorageBackendLogicalPoolVolData {
    virStoragePoolObjPtr pool;
    virStorageVolDefPtr vol;
};

74
static int
75 76
virStorageBackendLogicalMakeVol(char **const groups,
                                void *opaque)
77
{
78 79
    struct virStorageBackendLogicalPoolVolData *data = opaque;
    virStoragePoolObjPtr pool = data->pool;
80
    virStorageVolDefPtr vol = NULL;
81
    bool is_new_vol = false;
82
    unsigned long long offset, size, length;
83 84 85 86 87
    const char *regex_unit = "(\\S+)\\((\\S+)\\)";
    char *regex = NULL;
    regex_t *reg = NULL;
    regmatch_t *vars = NULL;
    char *p = NULL;
88 89
    size_t i;
    int err, nextents, nvars, ret = -1;
O
Osier Yang 已提交
90 91 92 93 94
    const char *attrs = groups[9];

    /* Skip inactive volume */
    if (attrs[4] != 'a')
        return 0;
95

D
Dusty Mabe 已提交
96 97 98 99 100 101 102 103
    /*
     * Skip thin pools(t). These show up in normal lvs output
     * but do not have a corresponding /dev/$vg/$lv device that
     * is created by udev. This breaks assumptions in later code.
     */
    if (attrs[0] == 't')
        return 0;

104
    /* See if we're only looking for a specific volume */
105 106
    if (data->vol != NULL) {
        vol = data->vol;
107 108 109 110 111 112 113 114 115 116
        if (STRNEQ(vol->name, groups[0]))
            return 0;
    }

    /* Or filling in more data on an existing volume */
    if (vol == NULL)
        vol = virStorageVolDefFindByName(pool, groups[0]);

    /* Or a completely new volume */
    if (vol == NULL) {
117
        if (VIR_ALLOC(vol) < 0)
118 119
            return -1;

120
        is_new_vol = true;
121 122
        vol->type = VIR_STORAGE_VOL_BLOCK;

123
        if (VIR_STRDUP(vol->name, groups[0]) < 0)
124
            goto cleanup;
125 126 127 128

    }

    if (vol->target.path == NULL) {
129
        if (virAsprintf(&vol->target.path, "%s/%s",
130
                        pool->def->target.path, vol->name) < 0)
131
            goto cleanup;
132 133
    }

134 135 136 137 138 139 140 141 142
    /* Mark the (s) sparse/snapshot lv, e.g. the lv created using
     * the --virtualsize/-V option. We've already ignored the (t)hin
     * pool definition. In the manner libvirt defines these, the
     * thin pool is hidden to the lvs output, except as the name
     * in brackets [] described for the groups[1] (backingStore).
     */
    if (attrs[0] == 's')
        vol->target.sparse = true;

143 144 145 146 147 148 149
    /* Skips the backingStore of lv created with "--virtualsize",
     * its original device "/dev/$vgname/$lvname_vorigin" is
     * just for lvm internal use, one should never use it.
     *
     * (lvs outputs "[$lvname_vorigin] for field "origin" if the
     *  lv is created with "--virtualsize").
     */
150
    if (groups[1] && STRNEQ(groups[1], "") && (groups[1][0] != '[')) {
151 152 153 154
        if (VIR_ALLOC(vol->target.backingStore) < 0)
            goto cleanup;

        if (virAsprintf(&vol->target.backingStore->path, "%s/%s",
155
                        pool->def->target.path, groups[1]) < 0)
156
            goto cleanup;
157

158
        vol->target.backingStore->format = VIR_STORAGE_POOL_LOGICAL_LVM2;
159 160
    }

161
    if (!vol->key && VIR_STRDUP(vol->key, groups[2]) < 0)
162
        goto cleanup;
163

164
    if (virStorageBackendUpdateVolInfo(vol, false,
165
                                       VIR_STORAGE_VOL_OPEN_DEFAULT) < 0)
166 167 168 169 170
        goto cleanup;

    nextents = 1;
    if (STREQ(groups[4], VIR_STORAGE_VOL_LOGICAL_SEGTYPE_STRIPED)) {
        if (virStrToLong_i(groups[5], NULL, 10, &nextents) < 0) {
171 172
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("malformed volume extent stripes value"));
173 174 175
            goto cleanup;
        }
    }
176 177

    /* Finally fill in extents information */
178
    if (VIR_REALLOC_N(vol->source.extents,
179
                      vol->source.nextent + nextents) < 0)
180
        goto cleanup;
181

182
    if (virStrToLong_ull(groups[6], NULL, 10, &length) < 0) {
183 184
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("malformed volume extent length value"));
185 186 187
        goto cleanup;
    }
    if (virStrToLong_ull(groups[7], NULL, 10, &size) < 0) {
188 189
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("malformed volume extent size value"));
190 191
        goto cleanup;
    }
192
    if (virStrToLong_ull(groups[8], NULL, 10, &vol->target.allocation) < 0) {
193 194
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("malformed volume allocation value"));
195 196
        goto cleanup;
    }
197

E
Eric Blake 已提交
198
    /* Now parse the "devices" field separately */
199 200
    if (VIR_STRDUP(regex, regex_unit) < 0)
        goto cleanup;
201 202

    for (i = 1; i < nextents; i++) {
203
        if (VIR_REALLOC_N(regex, strlen(regex) + strlen(regex_unit) + 2) < 0)
204
            goto cleanup;
E
Eric Blake 已提交
205
        /* "," is the separator of "devices" field */
206 207 208 209
        strcat(regex, ",");
        strncat(regex, regex_unit, strlen(regex_unit));
    }

210
    if (VIR_ALLOC(reg) < 0)
211
        goto cleanup;
212

213 214 215 216
    /* Each extent has a "path:offset" pair, and vars[0] will
     * be the whole matched string.
     */
    nvars = (nextents * 2) + 1;
217
    if (VIR_ALLOC_N(vars, nvars) < 0)
218 219 220 221 222 223
        goto cleanup;

    err = regcomp(reg, regex, REG_EXTENDED);
    if (err != 0) {
        char error[100];
        regerror(err, reg, error, sizeof(error));
224 225 226
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to compile regex %s"),
                       error);
227
        goto cleanup;
228
    }
229

230 231 232
    err = regexec(reg, groups[3], nvars, vars, 0);
    regfree(reg);
    if (err != 0) {
233 234
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("malformed volume extent devices value"));
235
        goto cleanup;
236 237
    }

238
    p = groups[3];
239

240 241
    /* vars[0] is skipped */
    for (i = 0; i < nextents; i++) {
242 243
        size_t j;
        int len;
244
        char *offset_str = NULL;
245 246 247 248 249

        j = (i * 2) + 1;
        len = vars[j].rm_eo - vars[j].rm_so;
        p[vars[j].rm_eo] = '\0';

250 251
        if (VIR_STRNDUP(vol->source.extents[vol->source.nextent].path,
                        p + vars[j].rm_so, len) < 0)
252 253 254
            goto cleanup;

        len = vars[j + 1].rm_eo - vars[j + 1].rm_so;
255
        if (VIR_STRNDUP(offset_str, p + vars[j + 1].rm_so, len) < 0)
256 257 258
            goto cleanup;

        if (virStrToLong_ull(offset_str, NULL, 10, &offset) < 0) {
259 260
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("malformed volume extent offset value"));
E
Eric Blake 已提交
261
            VIR_FREE(offset_str);
262 263 264 265 266 267 268 269 270 271
            goto cleanup;
        }

        VIR_FREE(offset_str);

        vol->source.extents[vol->source.nextent].start = offset * size;
        vol->source.extents[vol->source.nextent].end = (offset * size) + length;
        vol->source.nextent++;
    }

272 273 274
    if (is_new_vol &&
        VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0)
        goto cleanup;
275

276 277
    ret = 0;

278
 cleanup:
279
    VIR_FREE(regex);
280
    VIR_FREE(reg);
281 282 283 284
    VIR_FREE(vars);
    if (is_new_vol && (ret == -1))
        virStorageVolDefFree(vol);
    return ret;
285 286 287
}

static int
288
virStorageBackendLogicalFindLVs(virStoragePoolObjPtr pool,
289 290 291
                                virStorageVolDefPtr vol)
{
    /*
O
Osier Yang 已提交
292 293 294 295 296 297 298 299
     * # lvs --separator , --noheadings --units b --unbuffered --nosuffix --options \
     * "lv_name,origin,uuid,devices,seg_size,vg_extent_size,size,lv_attr" VGNAME
     *
     * RootLV,,06UgP5-2rhb-w3Bo-3mdR-WeoL-pytO-SAa2ky,/dev/hda2(0),5234491392,33554432,5234491392,-wi-ao
     * SwapLV,,oHviCK-8Ik0-paqS-V20c-nkhY-Bm1e-zgzU0M,/dev/hda2(156),1040187392,33554432,1040187392,-wi-ao
     * Test2,,3pg3he-mQsA-5Sui-h0i6-HNmc-Cz7W-QSndcR,/dev/hda2(219),1073741824,33554432,1073741824,owi-a-
     * Test3,,UB5hFw-kmlm-LSoX-EI1t-ioVd-h7GL-M0W8Ht,/dev/hda2(251),2181038080,33554432,2181038080,-wi-a-
     * Test3,Test2,UB5hFw-kmlm-LSoX-EI1t-ioVd-h7GL-M0W8Ht,/dev/hda2(187),1040187392,33554432,1040187392,swi-a-
300
     *
O
Osier Yang 已提交
301 302
     * Pull out name, origin, & uuid, device, device extent start #,
     * segment size, extent size, size, attrs
303 304
     *
     * NB can be multiple rows per volume if they have many extents
305
     *
306 307 308 309
     * NB lvs from some distros (e.g. SLES10 SP2) outputs trailing "," on each line
     *
     * NB Encrypted logical volumes can print ':' in their name, so it is
     *    not a suitable separator (rhbz 470693).
310 311
     * NB "devices" field has multiple device paths and "," if the volume is
     *    striped, so "," is not a suitable separator either (rhbz 727474).
312 313
     */
    const char *regexes[] = {
O
Osier Yang 已提交
314
       "^\\s*(\\S+)#(\\S*)#(\\S+)#(\\S+)#(\\S+)#([0-9]+)#(\\S+)#([0-9]+)#([0-9]+)#(\\S+)#?\\s*$"
315 316
    };
    int vars[] = {
O
Osier Yang 已提交
317
        10
318
    };
319 320
    int ret = -1;
    virCommandPtr cmd;
321 322 323 324
    struct virStorageBackendLogicalPoolVolData cbdata = {
        .pool = pool,
        .vol = vol,
    };
325 326 327 328 329 330 331

    cmd = virCommandNewArgList(LVS,
                               "--separator", "#",
                               "--noheadings",
                               "--units", "b",
                               "--unbuffered",
                               "--nosuffix",
O
Osier Yang 已提交
332 333
                               "--options",
                               "lv_name,origin,uuid,devices,segtype,stripes,seg_size,vg_extent_size,size,lv_attr",
334 335
                               pool->def->source.name,
                               NULL);
336 337 338 339 340 341 342
    if (virCommandRunRegex(cmd,
                           1,
                           regexes,
                           vars,
                           virStorageBackendLogicalMakeVol,
                           &cbdata,
                           "lvs") < 0)
343
        goto cleanup;
344

345
    ret = 0;
346
 cleanup:
347 348
    virCommandFree(cmd);
    return ret;
349 350 351
}

static int
352 353
virStorageBackendLogicalRefreshPoolFunc(char **const groups,
                                        void *data)
354
{
355
    virStoragePoolObjPtr pool = data;
356 357 358 359 360 361 362 363 364 365
    if (virStrToLong_ull(groups[0], NULL, 10, &pool->def->capacity) < 0)
        return -1;
    if (virStrToLong_ull(groups[1], NULL, 10, &pool->def->available) < 0)
        return -1;
    pool->def->allocation = pool->def->capacity - pool->def->available;

    return 0;
}


366
static int
367
virStorageBackendLogicalFindPoolSourcesFunc(char **const groups,
368 369
                                            void *data)
{
370 371 372
    virStoragePoolSourceListPtr sourceList = data;
    char *pvname = NULL;
    char *vgname = NULL;
373
    size_t i;
374 375 376
    virStoragePoolSourceDevicePtr dev;
    virStoragePoolSource *thisSource;

377 378 379
    if (VIR_STRDUP(pvname, groups[0]) < 0 ||
        VIR_STRDUP(vgname, groups[1]) < 0)
        goto error;
380 381

    thisSource = NULL;
382
    for (i = 0; i < sourceList->nsources; i++) {
383 384 385 386 387
        if (STREQ(sourceList->sources[i].name, vgname)) {
            thisSource = &sourceList->sources[i];
            break;
        }
    }
388

389
    if (thisSource == NULL) {
390
        if (!(thisSource = virStoragePoolSourceListNewSource(sourceList)))
391
            goto error;
392 393

        thisSource->name = vgname;
394
    }
395 396
    else
        VIR_FREE(vgname);
397

398
    if (VIR_REALLOC_N(thisSource->devices, thisSource->ndevice + 1) != 0)
399
        goto error;
400

401 402
    dev = &thisSource->devices[thisSource->ndevice];
    thisSource->ndevice++;
403
    thisSource->format = VIR_STORAGE_POOL_LOGICAL_LVM2;
404 405 406

    memset(dev, 0, sizeof(*dev));
    dev->path = pvname;
407 408

    return 0;
409

410
 error:
411 412 413 414
    VIR_FREE(pvname);
    VIR_FREE(vgname);

    return -1;
415 416 417
}

static char *
418
virStorageBackendLogicalFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
419
                                        const char *srcSpec ATTRIBUTE_UNUSED,
E
Eric Blake 已提交
420
                                        unsigned int flags)
421 422
{
    /*
423 424 425
     * # pvs --noheadings -o pv_name,vg_name
     *   /dev/sdb
     *   /dev/sdc VolGroup00
426 427
     */
    const char *regexes[] = {
428
        "^\\s*(\\S+)\\s+(\\S+)\\s*$"
429 430
    };
    int vars[] = {
431
        2
432
    };
433
    virCommandPtr cmd;
434
    char *retval = NULL;
435
    virStoragePoolSourceList sourceList;
436
    size_t i;
437

E
Eric Blake 已提交
438 439
    virCheckFlags(0, NULL);

440 441 442 443 444
    /*
     * NOTE: ignoring errors here; this is just to "touch" any logical volumes
     * that might be hanging around, so if this fails for some reason, the
     * worst that happens is that scanning doesn't pick everything up
     */
445 446
    cmd = virCommandNew(VGSCAN);
    if (virCommandRun(cmd, NULL) < 0)
447
        VIR_WARN("Failure when running vgscan to refresh physical volumes");
448
    virCommandFree(cmd);
449

450
    memset(&sourceList, 0, sizeof(sourceList));
451 452
    sourceList.type = VIR_STORAGE_POOL_LOGICAL;

453 454 455 456
    cmd = virCommandNewArgList(PVS,
                               "--noheadings",
                               "-o", "pv_name,vg_name",
                               NULL);
457 458 459
    if (virCommandRunRegex(cmd, 1, regexes, vars,
                           virStorageBackendLogicalFindPoolSourcesFunc,
                           &sourceList, "pvs") < 0) {
460
        virCommandFree(cmd);
461
        return NULL;
462 463
    }
    virCommandFree(cmd);
464

465
    retval = virStoragePoolSourceListFormat(&sourceList);
466
    if (retval == NULL) {
467 468
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to get source from sourceList"));
469 470 471 472
        goto cleanup;
    }

 cleanup:
473
    for (i = 0; i < sourceList.nsources; i++)
474
        virStoragePoolSourceClear(&sourceList.sources[i]);
475
    VIR_FREE(sourceList.sources);
476 477 478 479 480

    return retval;
}


481
static int
482
virStorageBackendLogicalCheckPool(virStoragePoolObjPtr pool,
483 484
                                  bool *isActive)
{
485
    *isActive = virFileExists(pool->def->target.path);
486 487 488
    return 0;
}

489
static int
490
virStorageBackendLogicalStartPool(virConnectPtr conn ATTRIBUTE_UNUSED,
491 492
                                  virStoragePoolObjPtr pool)
{
493
    if (virStorageBackendLogicalSetActive(pool, 1) < 0)
494 495 496 497 498 499 500
        return -1;

    return 0;
}


static int
501
virStorageBackendLogicalBuildPool(virConnectPtr conn ATTRIBUTE_UNUSED,
502
                                  virStoragePoolObjPtr pool,
E
Eric Blake 已提交
503
                                  unsigned int flags)
504
{
505 506
    virCommandPtr vgcmd;
    int fd;
507
    char zeros[PV_BLANK_SECTOR_SIZE];
508 509
    int ret = -1;
    size_t i;
510

E
Eric Blake 已提交
511 512
    virCheckFlags(0, -1);

513 514
    memset(zeros, 0, sizeof(zeros));

515
    vgcmd = virCommandNewArgList(VGCREATE, pool->def->source.name, NULL);
516

517
    for (i = 0; i < pool->def->source.ndevice; i++) {
518
        virCommandPtr pvcmd;
519 520 521 522 523 524
        /*
         * LVM requires that the first sector is blanked if using
         * a whole disk as a PV. So we just blank them out regardless
         * rather than trying to figure out if we're a disk or partition
         */
        if ((fd = open(pool->def->source.devices[i].path, O_WRONLY)) < 0) {
525
            virReportSystemError(errno,
526 527
                                 _("cannot open device '%s'"),
                                 pool->def->source.devices[i].path);
528 529
            goto cleanup;
        }
530
        if (safewrite(fd, zeros, sizeof(zeros)) < 0) {
531
            virReportSystemError(errno,
532 533
                                 _("cannot clear device header of '%s'"),
                                 pool->def->source.devices[i].path);
534 535 536 537 538 539 540
            VIR_FORCE_CLOSE(fd);
            goto cleanup;
        }
        if (fsync(fd) < 0) {
            virReportSystemError(errno,
                                 _("cannot flush header of device'%s'"),
                                 pool->def->source.devices[i].path);
541
            VIR_FORCE_CLOSE(fd);
542 543
            goto cleanup;
        }
544
        if (VIR_CLOSE(fd) < 0) {
545
            virReportSystemError(errno,
546 547
                                 _("cannot close device '%s'"),
                                 pool->def->source.devices[i].path);
548 549 550 551 552 553 554
            goto cleanup;
        }

        /*
         * Initialize the physical volume because vgcreate is not
         * clever enough todo this for us :-(
         */
555 556 557 558 559
        pvcmd = virCommandNewArgList(PVCREATE,
                                     pool->def->source.devices[i].path,
                                     NULL);
        if (virCommandRun(pvcmd, NULL) < 0) {
            virCommandFree(pvcmd);
560
            goto cleanup;
561 562
        }
        virCommandFree(pvcmd);
563

564 565
        virCommandAddArg(vgcmd, pool->def->source.devices[i].path);
    }
566 567

    /* Now create the volume group itself */
568
    if (virCommandRun(vgcmd, NULL) < 0)
569 570
        goto cleanup;

571
    ret = 0;
572

573
 cleanup:
574 575
    virCommandFree(vgcmd);
    return ret;
576 577 578 579
}


static int
580
virStorageBackendLogicalRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
581 582 583 584 585 586 587
                                    virStoragePoolObjPtr pool)
{
    /*
     *  # vgs --separator : --noheadings --units b --unbuffered --nosuffix --options "vg_size,vg_free" VGNAME
     *    10603200512:4328521728
     *
     * Pull out size & free
588 589
     *
     * NB vgs from some distros (e.g. SLES10 SP2) outputs trailing ":" on each line
590 591
     */
    const char *regexes[] = {
592
        "^\\s*(\\S+):([0-9]+):?\\s*$"
593 594 595 596
    };
    int vars[] = {
        2
    };
597 598
    virCommandPtr cmd = NULL;
    int ret = -1;
599

600
    virFileWaitForDevices();
601

602
    /* Get list of all logical volumes */
603 604 605 606 607 608 609 610 611 612 613 614
    if (virStorageBackendLogicalFindLVs(pool, NULL) < 0)
        goto cleanup;

    cmd = virCommandNewArgList(VGS,
                               "--separator", ":",
                               "--noheadings",
                               "--units", "b",
                               "--unbuffered",
                               "--nosuffix",
                               "--options", "vg_size,vg_free",
                               pool->def->source.name,
                               NULL);
615 616

    /* Now get basic volgrp metadata */
617 618 619 620 621 622 623
    if (virCommandRunRegex(cmd,
                           1,
                           regexes,
                           vars,
                           virStorageBackendLogicalRefreshPoolFunc,
                           pool,
                           "vgs") < 0)
624
        goto cleanup;
625

626 627
    ret = 0;

628
 cleanup:
629 630 631 632
    virCommandFree(cmd);
    if (ret < 0)
        virStoragePoolObjClearVols(pool);
    return ret;
633 634
}

635 636 637 638
/*
 * This is actually relatively safe; if you happen to try to "stop" the
 * pool that your / is on, for instance, you will get failure like:
 * "Can't deactivate volume group "VolGroup00" with 3 open logical volume(s)"
639 640
 */
static int
641
virStorageBackendLogicalStopPool(virConnectPtr conn ATTRIBUTE_UNUSED,
642 643
                                 virStoragePoolObjPtr pool)
{
644
    if (virStorageBackendLogicalSetActive(pool, 0) < 0)
645 646 647 648 649 650
        return -1;

    return 0;
}

static int
651
virStorageBackendLogicalDeletePool(virConnectPtr conn ATTRIBUTE_UNUSED,
652
                                   virStoragePoolObjPtr pool,
E
Eric Blake 已提交
653
                                   unsigned int flags)
654
{
655 656 657
    virCommandPtr cmd = NULL;
    size_t i;
    int ret = -1;
658

E
Eric Blake 已提交
659 660
    virCheckFlags(0, -1);

661
    /* first remove the volume group */
662 663 664 665 666 667
    cmd = virCommandNewArgList(VGREMOVE,
                               "-f", pool->def->source.name,
                               NULL);
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;
    virCommandFree(cmd);
668
    cmd = NULL;
669

670
    /* now remove the pv devices and clear them out */
671
    ret = 0;
672
    for (i = 0; i < pool->def->source.ndevice; i++) {
673 674 675 676 677
        cmd = virCommandNewArgList(PVREMOVE,
                                   pool->def->source.devices[i].path,
                                   NULL);
        if (virCommandRun(cmd, NULL) < 0) {
            ret = -1;
678 679
            break;
        }
680 681
        virCommandFree(cmd);
        cmd = NULL;
682
    }
683

684
 cleanup:
685 686
    virCommandFree(cmd);
    return ret;
687 688 689 690
}


static int
691 692
virStorageBackendLogicalDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
693
                                  virStorageVolDefPtr vol,
694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717
                                  unsigned int flags)
{
    int ret = -1;

    virCommandPtr lvchange_cmd = NULL;
    virCommandPtr lvremove_cmd = NULL;

    virCheckFlags(0, -1);

    virFileWaitForDevices();

    lvchange_cmd = virCommandNewArgList(LVCHANGE, "-aln", vol->target.path, NULL);
    lvremove_cmd = virCommandNewArgList(LVREMOVE, "-f", vol->target.path, NULL);

    if (virCommandRun(lvremove_cmd, NULL) < 0) {
        if (virCommandRun(lvchange_cmd, NULL) < 0) {
            goto cleanup;
        } else {
            if (virCommandRun(lvremove_cmd, NULL) < 0)
                goto cleanup;
        }
    }

    ret = 0;
718
 cleanup:
719 720 721 722
    virCommandFree(lvchange_cmd);
    virCommandFree(lvremove_cmd);
    return ret;
}
723 724 725


static int
726 727 728
virStorageBackendLogicalCreateVol(virConnectPtr conn,
                                  virStoragePoolObjPtr pool,
                                  virStorageVolDefPtr vol)
729
{
730
    int fd = -1;
731
    virCommandPtr cmd = NULL;
732
    virErrorPtr err;
733
    struct stat sb;
734
    bool created = false;
735

736 737 738 739 740 741 742 743 744
    if (vol->target.encryption != NULL) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       "%s", _("storage pool does not support encrypted "
                               "volumes"));
        return -1;
    }

    vol->type = VIR_STORAGE_VOL_BLOCK;

745 746
    /* A target path passed to CreateVol has no meaning */
    VIR_FREE(vol->target.path);
747 748 749 750 751

    if (virAsprintf(&vol->target.path, "%s/%s",
                    pool->def->target.path,
                    vol->name) == -1)
        return -1;
752

753 754 755 756
    cmd = virCommandNewArgList(LVCREATE,
                               "--name", vol->name,
                               NULL);
    virCommandAddArg(cmd, "-L");
757
    if (vol->target.capacity != vol->target.allocation) {
758
        virCommandAddArgFormat(cmd, "%lluK",
759 760
                               VIR_DIV_UP(vol->target.allocation
                                          ? vol->target.allocation : 1, 1024));
761
        virCommandAddArgList(cmd, "--type", "snapshot", NULL);
762
        virCommandAddArg(cmd, "--virtualsize");
763
        vol->target.sparse = true;
764
    }
765 766
    virCommandAddArgFormat(cmd, "%lluK", VIR_DIV_UP(vol->target.capacity,
                                                    1024));
767 768
    if (vol->target.backingStore)
        virCommandAddArgList(cmd, "-s", vol->target.backingStore->path, NULL);
769 770 771 772
    else
        virCommandAddArg(cmd, pool->def->source.name);

    if (virCommandRun(cmd, NULL) < 0)
773
        goto error;
774

775
    created = true;
776 777 778
    virCommandFree(cmd);
    cmd = NULL;

779 780
    if ((fd = virStorageBackendVolOpen(vol->target.path, &sb,
                                       VIR_STORAGE_VOL_OPEN_DEFAULT)) < 0)
781
        goto error;
782 783

    /* We can only chown/grp if root */
784
    if (geteuid() == 0) {
785
        if (fchown(fd, vol->target.perms->uid, vol->target.perms->gid) < 0) {
786
            virReportSystemError(errno,
787 788
                                 _("cannot set file owner '%s'"),
                                 vol->target.path);
789
            goto error;
790 791
        }
    }
792 793 794
    if (fchmod(fd, (vol->target.perms->mode == (mode_t) -1 ?
                    VIR_STORAGE_DEFAULT_VOL_PERM_MODE :
                    vol->target.perms->mode)) < 0) {
795
        virReportSystemError(errno,
796 797
                             _("cannot set file mode '%s'"),
                             vol->target.path);
798
        goto error;
799 800
    }

801
    if (VIR_CLOSE(fd) < 0) {
802
        virReportSystemError(errno,
803 804
                             _("cannot close file '%s'"),
                             vol->target.path);
805
        goto error;
806 807 808
    }

    /* Fill in data about this new vol */
809
    if (virStorageBackendLogicalFindLVs(pool, vol) < 0) {
810
        virReportSystemError(errno,
811 812
                             _("cannot find newly created volume '%s'"),
                             vol->target.path);
813
        goto error;
814 815 816 817
    }

    return 0;

818
 error:
819
    err = virSaveLastError();
820
    VIR_FORCE_CLOSE(fd);
821 822
    if (created)
        virStorageBackendLogicalDeleteVol(conn, pool, vol, 0);
823
    virCommandFree(cmd);
824
    virSetError(err);
825
    virFreeError(err);
826 827 828
    return -1;
}

829 830
static int
virStorageBackendLogicalBuildVolFrom(virConnectPtr conn,
831
                                     virStoragePoolObjPtr pool,
832 833 834 835 836 837
                                     virStorageVolDefPtr vol,
                                     virStorageVolDefPtr inputvol,
                                     unsigned int flags)
{
    virStorageBackendBuildVolFrom build_func;

838
    build_func = virStorageBackendGetBuildVolFromFunction(vol, inputvol);
839 840 841
    if (!build_func)
        return -1;

842
    return build_func(conn, pool, vol, inputvol, flags);
843 844
}

845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
static int
virStorageBackendLogicalVolWipe(virConnectPtr conn,
                                virStoragePoolObjPtr pool,
                                virStorageVolDefPtr vol,
                                unsigned int algorithm,
                                unsigned int flags)
{
    if (!vol->target.sparse)
        return virStorageBackendVolWipeLocal(conn, pool, vol, algorithm, flags);

    /* The wiping algorithms will write something to the logical volume.
     * Writing to a sparse logical volume causes it to be filled resulting
     * in the volume becoming INACTIVE because there is some amount of
     * metadata contained within the sparse lv. Choosing to only write
     * a wipe pattern to the already written portion lv based on what
     * 'lvs' shows in the "Data%" column/field for the sparse lv was
     * considered. However, there is no guarantee that sparse lv could
     * grow or shrink outside of libvirt's knowledge and thus still render
     * the volume INACTIVE. Until there is some sort of wipe function
     * implemented by lvm for one of these sparse lv, we'll just return
     * unsupported.
     */
    virReportError(VIR_ERR_NO_SUPPORT,
J
John Ferlan 已提交
868 869
                   _("logical volume '%s' is sparse, volume wipe "
                     "not supported"),
870 871 872
                   vol->target.path);
    return -1;
}
873 874 875 876

virStorageBackend virStorageBackendLogical = {
    .type = VIR_STORAGE_POOL_LOGICAL,

877
    .findPoolSources = virStorageBackendLogicalFindPoolSources,
878
    .checkPool = virStorageBackendLogicalCheckPool,
879 880 881 882 883
    .startPool = virStorageBackendLogicalStartPool,
    .buildPool = virStorageBackendLogicalBuildPool,
    .refreshPool = virStorageBackendLogicalRefreshPool,
    .stopPool = virStorageBackendLogicalStopPool,
    .deletePool = virStorageBackendLogicalDeletePool,
884
    .buildVol = NULL,
885
    .buildVolFrom = virStorageBackendLogicalBuildVolFrom,
886 887
    .createVol = virStorageBackendLogicalCreateVol,
    .deleteVol = virStorageBackendLogicalDeleteVol,
888 889
    .uploadVol = virStorageBackendVolUploadLocal,
    .downloadVol = virStorageBackendVolDownloadLocal,
890
    .wipeVol = virStorageBackendLogicalVolWipe,
891
};