storage_backend_logical.c 27.3 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 150
    /* 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").
     */
    if (groups[1] && !STREQ(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, true, 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 482 483 484 485
static int
virStorageBackendLogicalCheckPool(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  virStoragePoolObjPtr pool,
                                  bool *isActive)
{
486
    *isActive = virFileExists(pool->def->target.path);
487 488 489
    return 0;
}

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

    return 0;
}


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

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

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

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

518
    for (i = 0; i < pool->def->source.ndevice; i++) {
519
        virCommandPtr pvcmd;
520 521 522 523 524 525
        /*
         * 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) {
526
            virReportSystemError(errno,
527 528
                                 _("cannot open device '%s'"),
                                 pool->def->source.devices[i].path);
529 530
            goto cleanup;
        }
531
        if (safewrite(fd, zeros, sizeof(zeros)) < 0) {
532
            virReportSystemError(errno,
533 534
                                 _("cannot clear device header of '%s'"),
                                 pool->def->source.devices[i].path);
535 536 537 538 539 540 541
            VIR_FORCE_CLOSE(fd);
            goto cleanup;
        }
        if (fsync(fd) < 0) {
            virReportSystemError(errno,
                                 _("cannot flush header of device'%s'"),
                                 pool->def->source.devices[i].path);
542
            VIR_FORCE_CLOSE(fd);
543 544
            goto cleanup;
        }
545
        if (VIR_CLOSE(fd) < 0) {
546
            virReportSystemError(errno,
547 548
                                 _("cannot close device '%s'"),
                                 pool->def->source.devices[i].path);
549 550 551 552 553 554 555
            goto cleanup;
        }

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

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

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

572
    ret = 0;
573

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


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

601
    virFileWaitForDevices();
602

603
    /* Get list of all logical volumes */
604 605 606 607 608 609 610 611 612 613 614 615
    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);
616 617

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

627 628
    ret = 0;

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

636 637 638 639
/*
 * 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)"
640 641
 */
static int
642
virStorageBackendLogicalStopPool(virConnectPtr conn ATTRIBUTE_UNUSED,
643 644
                                 virStoragePoolObjPtr pool)
{
645
    if (virStorageBackendLogicalSetActive(pool, 0) < 0)
646 647 648 649 650 651
        return -1;

    return 0;
}

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

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

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

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

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


static int
692 693
virStorageBackendLogicalDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
694
                                  virStorageVolDefPtr vol,
695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718
                                  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;
719
 cleanup:
720 721 722 723
    virCommandFree(lvchange_cmd);
    virCommandFree(lvremove_cmd);
    return ret;
}
724 725 726


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

736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753
    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;

    if (vol->target.path != NULL) {
        /* A target path passed to CreateVol has no meaning */
        VIR_FREE(vol->target.path);
    }

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

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

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

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
    if (fchmod(fd, vol->target.perms->mode) < 0) {
793
        virReportSystemError(errno,
794 795
                             _("cannot set file mode '%s'"),
                             vol->target.path);
796
        goto error;
797 798
    }

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

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

    return 0;

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

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

835
    build_func = virStorageBackendGetBuildVolFromFunction(vol, inputvol);
836 837 838
    if (!build_func)
        return -1;

839
    return build_func(conn, pool, vol, inputvol, flags);
840 841
}

842 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 868
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,
                   _("logical volue '%s' is sparse, volume wipe not supported"),
                   vol->target.path);
    return -1;
}
869 870 871 872

virStorageBackend virStorageBackendLogical = {
    .type = VIR_STORAGE_POOL_LOGICAL,

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