storage_backend_logical.c 35.3 KB
Newer Older
1
/*
2
 * storage_backend_logical.c: storage backend for logical volume handling
3
 *
4
 * Copyright (C) 2007-2016 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
#include "storage_util.h"
43

44 45
#define VIR_FROM_THIS VIR_FROM_STORAGE

46 47
VIR_LOG_INIT("storage.storage_backend_logical");

48 49 50 51
#define PV_BLANK_SECTOR_SIZE 512


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

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


68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
/*
 * @path: Path to the device
 *
 * Remove the pv device since we're done with it. This ensures a subsequent
 * create won't require special arguments in order for force recreation.
 */
static void
virStorageBackendLogicalRemoveDevice(const char *path)
{
    virCommandPtr cmd = virCommandNewArgList(PVREMOVE, path, NULL);

    if (virCommandRun(cmd, NULL) < 0)
        VIR_INFO("Failed to pvremove logical device '%s'", path);
    virCommandFree(cmd);
}


85 86 87 88 89 90 91 92 93 94 95
/*
 * @path: Path to the device
 *
 * Initialize and pvcreate the device.
 *
 * Returns 0 on success, -1 on failure with error message set
 */
static int
virStorageBackendLogicalInitializeDevice(const char *path)
{
    int fd = -1;
96 97
    char zeros[4 * PV_BLANK_SECTOR_SIZE] = {0};
    off_t size;
98 99 100 101 102 103 104 105 106 107 108 109 110
    int ret = -1;
    virCommandPtr pvcmd = NULL;

    /*
     * 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(path, O_WRONLY)) < 0) {
        virReportSystemError(errno, _("cannot open device '%s'"), path);
        return -1;
    }

111 112 113 114 115 116 117 118
    if ((size = lseek(fd, 0, SEEK_END)) == (off_t)-1) {
        virReportSystemError(errno,
                             _("failed to seek to end of %s"), path);
        goto cleanup;
    }

    if (size < 4 * PV_BLANK_SECTOR_SIZE) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
J
Jiri Denemark 已提交
119
                       _("cannot initialize '%s' detected size='%zd' less "
120
                         "than minimum required='%d"),
J
Jiri Denemark 已提交
121
                         path, (ssize_t) size, 4 * PV_BLANK_SECTOR_SIZE);
122 123 124 125 126 127 128 129
        goto cleanup;
    }
    if ((size = lseek(fd, 0, SEEK_SET)) == (off_t)-1) {
        virReportSystemError(errno,
                             _("failed to seek to start of %s"), path);
        goto cleanup;
    }

130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
    if (safewrite(fd, zeros, sizeof(zeros)) < 0) {
        virReportSystemError(errno, _("cannot clear device header of '%s'"),
                             path);
        goto cleanup;
    }

    if (fsync(fd) < 0) {
        virReportSystemError(errno, _("cannot flush header of device'%s'"),
                             path);
        goto cleanup;
    }

    if (VIR_CLOSE(fd) < 0) {
        virReportSystemError(errno, _("cannot close device '%s'"), path);
        goto cleanup;
    }

    /*
     * Initialize the physical volume because vgcreate is not
     * clever enough todo this for us :-(
     */
    pvcmd = virCommandNewArgList(PVCREATE, path, NULL);
    if (virCommandRun(pvcmd, NULL) < 0)
        goto cleanup;

    ret = 0;

 cleanup:
    VIR_FORCE_CLOSE(fd);
    virCommandFree(pvcmd);

    return ret;
}


165
#define VIR_STORAGE_VOL_LOGICAL_SEGTYPE_STRIPED "striped"
166 167
#define VIR_STORAGE_VOL_LOGICAL_SEGTYPE_MIRROR  "mirror"
#define VIR_STORAGE_VOL_LOGICAL_SEGTYPE_RAID    "raid"
168

169 170 171 172 173
struct virStorageBackendLogicalPoolVolData {
    virStoragePoolObjPtr pool;
    virStorageVolDefPtr vol;
};

174
static int
175 176
virStorageBackendLogicalParseVolExtents(virStorageVolDefPtr vol,
                                        char **const groups)
177
{
178
    int nextents, ret = -1;
179 180 181 182 183
    const char *regex_unit = "(\\S+)\\((\\S+)\\)";
    char *regex = NULL;
    regex_t *reg = NULL;
    regmatch_t *vars = NULL;
    char *p = NULL;
184
    size_t i;
185 186
    int err, nvars;
    unsigned long long offset, size, length;
187 188 189
    virStorageVolSourceExtent extent;

    memset(&extent, 0, sizeof(extent));
190

191 192 193 194 195 196 197
    /* Assume 1 extent (the regex for 'devices' is "(\\S+)") and only
     * check the 'stripes' field if we have a striped, mirror, or one of
     * the raid (raid1, raid4, raid5*, raid6*, or raid10) segtypes in which
     * case the stripes field will denote the number of lv's within the
     * 'devices' field in order to generate the proper regex to decode
     * the field
     */
198
    nextents = 1;
199 200 201
    if (STREQ(groups[4], VIR_STORAGE_VOL_LOGICAL_SEGTYPE_STRIPED) ||
        STREQ(groups[4], VIR_STORAGE_VOL_LOGICAL_SEGTYPE_MIRROR) ||
        STRPREFIX(groups[4], VIR_STORAGE_VOL_LOGICAL_SEGTYPE_RAID)) {
202
        if (virStrToLong_i(groups[5], NULL, 10, &nextents) < 0) {
203 204
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("malformed volume extent stripes value"));
205 206 207
            goto cleanup;
        }
    }
208

209
    if (virStrToLong_ull(groups[6], NULL, 10, &length) < 0) {
210 211
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("malformed volume extent length value"));
212 213
        goto cleanup;
    }
214

215
    if (virStrToLong_ull(groups[7], NULL, 10, &size) < 0) {
216 217
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("malformed volume extent size value"));
218 219 220
        goto cleanup;
    }

221 222
    /* Allocate space for 'nextents' regex_unit strings plus a comma for each */
    if (VIR_ALLOC_N(regex, nextents * (strlen(regex_unit) + 1) + 1) < 0)
223
        goto cleanup;
J
Ján Tomko 已提交
224
    strcat(regex, regex_unit);
225
    for (i = 1; i < nextents; i++) {
E
Eric Blake 已提交
226
        /* "," is the separator of "devices" field */
227
        strcat(regex, ",");
J
Ján Tomko 已提交
228
        strcat(regex, regex_unit);
229 230
    }

231
    if (VIR_ALLOC(reg) < 0)
232
        goto cleanup;
233

234 235 236 237
    /* Each extent has a "path:offset" pair, and vars[0] will
     * be the whole matched string.
     */
    nvars = (nextents * 2) + 1;
238
    if (VIR_ALLOC_N(vars, nvars) < 0)
239 240 241 242 243 244
        goto cleanup;

    err = regcomp(reg, regex, REG_EXTENDED);
    if (err != 0) {
        char error[100];
        regerror(err, reg, error, sizeof(error));
245 246 247
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to compile regex %s"),
                       error);
248
        goto cleanup;
249
    }
250

251 252 253
    err = regexec(reg, groups[3], nvars, vars, 0);
    regfree(reg);
    if (err != 0) {
254 255
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("malformed volume extent devices value"));
256
        goto cleanup;
257 258
    }

259
    p = groups[3];
260

261 262
    /* vars[0] is skipped */
    for (i = 0; i < nextents; i++) {
263 264
        size_t j;
        int len;
265
        char *offset_str = NULL;
266 267 268 269 270

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

271
        if (VIR_STRNDUP(extent.path,
272
                        p + vars[j].rm_so, len) < 0)
273 274 275
            goto cleanup;

        len = vars[j + 1].rm_eo - vars[j + 1].rm_so;
276
        if (VIR_STRNDUP(offset_str, p + vars[j + 1].rm_so, len) < 0)
277 278 279
            goto cleanup;

        if (virStrToLong_ull(offset_str, NULL, 10, &offset) < 0) {
280 281
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("malformed volume extent offset value"));
E
Eric Blake 已提交
282
            VIR_FREE(offset_str);
283 284 285
            goto cleanup;
        }
        VIR_FREE(offset_str);
286 287
        extent.start = offset * size;
        extent.end = (offset * size) + length;
288

289 290 291
        if (VIR_APPEND_ELEMENT(vol->source.extents, vol->source.nextent,
                               extent) < 0)
            goto cleanup;
292 293
    }

294 295 296 297 298 299
    ret = 0;

 cleanup:
    VIR_FREE(regex);
    VIR_FREE(reg);
    VIR_FREE(vars);
300
    VIR_FREE(extent.path);
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
    return ret;
}


static int
virStorageBackendLogicalMakeVol(char **const groups,
                                void *opaque)
{
    struct virStorageBackendLogicalPoolVolData *data = opaque;
    virStoragePoolObjPtr pool = data->pool;
    virStorageVolDefPtr vol = NULL;
    bool is_new_vol = false;
    int ret = -1;
    const char *attrs = groups[9];

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

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

    /* See if we're only looking for a specific volume */
    if (data->vol != NULL) {
        vol = data->vol;
        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) {
        if (VIR_ALLOC(vol) < 0)
            return -1;

        is_new_vol = true;
        vol->type = VIR_STORAGE_VOL_BLOCK;

        if (VIR_STRDUP(vol->name, groups[0]) < 0)
            goto cleanup;

    }

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

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

    /* 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] && STRNEQ(groups[1], "") && (groups[1][0] != '[')) {
        if (VIR_ALLOC(vol->target.backingStore) < 0)
            goto cleanup;

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

        vol->target.backingStore->format = VIR_STORAGE_POOL_LOGICAL_LVM2;
    }

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

    if (virStorageBackendUpdateVolInfo(vol, false,
                                       VIR_STORAGE_VOL_OPEN_DEFAULT, 0) < 0)
        goto cleanup;

    if (virStrToLong_ull(groups[8], NULL, 10, &vol->target.allocation) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("malformed volume allocation value"));
        goto cleanup;
    }

    if (virStorageBackendLogicalParseVolExtents(vol, groups) < 0)
        goto cleanup;

401 402 403
    if (is_new_vol &&
        VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0)
        goto cleanup;
404

405 406
    ret = 0;

407
 cleanup:
408
    if (is_new_vol)
409 410
        virStorageVolDefFree(vol);
    return ret;
411 412
}

413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
#define VIR_STORAGE_VOL_LOGICAL_PREFIX_REGEX "^\\s*"
#define VIR_STORAGE_VOL_LOGICAL_LV_NAME_REGEX "(\\S+)#"
#define VIR_STORAGE_VOL_LOGICAL_ORIGIN_REGEX "(\\S*)#"
#define VIR_STORAGE_VOL_LOGICAL_UUID_REGEX "(\\S+)#"
#define VIR_STORAGE_VOL_LOGICAL_DEVICES_REGEX "(\\S+)#"
#define VIR_STORAGE_VOL_LOGICAL_SEGTYPE_REGEX "(\\S+)#"
#define VIR_STORAGE_VOL_LOGICAL_STRIPES_REGEX "([0-9]+)#"
#define VIR_STORAGE_VOL_LOGICAL_SEG_SIZE_REGEX "(\\S+)#"
#define VIR_STORAGE_VOL_LOGICAL_VG_EXTENT_SIZE_REGEX "([0-9]+)#"
#define VIR_STORAGE_VOL_LOGICAL_SIZE_REGEX "([0-9]+)#"
#define VIR_STORAGE_VOL_LOGICAL_LV_ATTR_REGEX "(\\S+)#"
#define VIR_STORAGE_VOL_LOGICAL_SUFFIX_REGEX "?\\s*$"

#define VIR_STORAGE_VOL_LOGICAL_REGEX_COUNT 10
#define VIR_STORAGE_VOL_LOGICAL_REGEX \
           VIR_STORAGE_VOL_LOGICAL_PREFIX_REGEX \
           VIR_STORAGE_VOL_LOGICAL_LV_NAME_REGEX \
           VIR_STORAGE_VOL_LOGICAL_ORIGIN_REGEX \
           VIR_STORAGE_VOL_LOGICAL_UUID_REGEX \
           VIR_STORAGE_VOL_LOGICAL_DEVICES_REGEX \
           VIR_STORAGE_VOL_LOGICAL_SEGTYPE_REGEX \
           VIR_STORAGE_VOL_LOGICAL_STRIPES_REGEX \
           VIR_STORAGE_VOL_LOGICAL_SEG_SIZE_REGEX \
           VIR_STORAGE_VOL_LOGICAL_VG_EXTENT_SIZE_REGEX \
           VIR_STORAGE_VOL_LOGICAL_SIZE_REGEX \
           VIR_STORAGE_VOL_LOGICAL_LV_ATTR_REGEX \
           VIR_STORAGE_VOL_LOGICAL_SUFFIX_REGEX

441
static int
442
virStorageBackendLogicalFindLVs(virStoragePoolObjPtr pool,
443 444 445
                                virStorageVolDefPtr vol)
{
    /*
446 447
     * # lvs --separator # --noheadings --units b --unbuffered --nosuffix --options \
     * "lv_name,origin,uuid,devices,segtype,stripes,seg_size,vg_extent_size,size,lv_attr" VGNAME
O
Osier Yang 已提交
448
     *
449 450 451 452 453 454
     * RootLV##06UgP5-2rhb-w3Bo-3mdR-WeoL-pytO-SAa2ky#/dev/hda2(0)#linear#1#5234491392#33554432#5234491392#-wi-ao
     * SwapLV##oHviCK-8Ik0-paqS-V20c-nkhY-Bm1e-zgzU0M#/dev/hda2(156)#linear#1#1040187392#33554432#1040187392#-wi-ao
     * Test2##3pg3he-mQsA-5Sui-h0i6-HNmc-Cz7W-QSndcR#/dev/hda2(219)#linear#1#1073741824#33554432#1073741824#owi-a-
     * Test3##UB5hFw-kmlm-LSoX-EI1t-ioVd-h7GL-M0W8Ht#/dev/hda2(251)#linear#1#2181038080#33554432#2181038080#-wi-a-
     * Test3#Test2#UB5hFw-kmlm-LSoX-EI1t-ioVd-h7GL-M0W8Ht#/dev/hda2(187)#linear#1#1040187392#33554432#1040187392#swi-a-
     * test_stripes##fSLSZH-zAS2-yAIb-n4mV-Al9u-HA3V-oo9K1B#/dev/sdc1(10240),/dev/sdd1(0)#striped#2#42949672960#4194304#-wi-a-
455
     *
O
Osier Yang 已提交
456 457
     * Pull out name, origin, & uuid, device, device extent start #,
     * segment size, extent size, size, attrs
458 459
     *
     * NB can be multiple rows per volume if they have many extents
460
     *
461 462
     * NB lvs from some distros (e.g. SLES10 SP2) outputs trailing ","
     * on each line
463 464 465
     *
     * NB Encrypted logical volumes can print ':' in their name, so it is
     *    not a suitable separator (rhbz 470693).
466
     *
467 468
     * NB "devices" field has multiple device paths and "," if the volume is
     *    striped, so "," is not a suitable separator either (rhbz 727474).
469 470
     */
    const char *regexes[] = {
471
        VIR_STORAGE_VOL_LOGICAL_REGEX
472 473
    };
    int vars[] = {
474
        VIR_STORAGE_VOL_LOGICAL_REGEX_COUNT
475
    };
476 477
    int ret = -1;
    virCommandPtr cmd;
478 479 480 481
    struct virStorageBackendLogicalPoolVolData cbdata = {
        .pool = pool,
        .vol = vol,
    };
482 483 484 485 486 487 488

    cmd = virCommandNewArgList(LVS,
                               "--separator", "#",
                               "--noheadings",
                               "--units", "b",
                               "--unbuffered",
                               "--nosuffix",
O
Osier Yang 已提交
489 490
                               "--options",
                               "lv_name,origin,uuid,devices,segtype,stripes,seg_size,vg_extent_size,size,lv_attr",
491 492
                               pool->def->source.name,
                               NULL);
493 494 495 496 497 498
    if (virCommandRunRegex(cmd,
                           1,
                           regexes,
                           vars,
                           virStorageBackendLogicalMakeVol,
                           &cbdata,
499 500
                           "lvs",
                           NULL) < 0)
501
        goto cleanup;
502

503
    ret = 0;
504
 cleanup:
505 506
    virCommandFree(cmd);
    return ret;
507 508 509
}

static int
510 511
virStorageBackendLogicalRefreshPoolFunc(char **const groups,
                                        void *data)
512
{
513
    virStoragePoolObjPtr pool = data;
514 515 516 517 518 519 520 521 522 523
    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;
}


524
static int
525
virStorageBackendLogicalFindPoolSourcesFunc(char **const groups,
526 527
                                            void *data)
{
528 529 530
    virStoragePoolSourceListPtr sourceList = data;
    char *pvname = NULL;
    char *vgname = NULL;
531
    size_t i;
532 533 534
    virStoragePoolSourceDevicePtr dev;
    virStoragePoolSource *thisSource;

535 536 537
    if (VIR_STRDUP(pvname, groups[0]) < 0 ||
        VIR_STRDUP(vgname, groups[1]) < 0)
        goto error;
538 539

    thisSource = NULL;
540
    for (i = 0; i < sourceList->nsources; i++) {
541 542 543 544 545
        if (STREQ(sourceList->sources[i].name, vgname)) {
            thisSource = &sourceList->sources[i];
            break;
        }
    }
546

547
    if (thisSource == NULL) {
548
        if (!(thisSource = virStoragePoolSourceListNewSource(sourceList)))
549
            goto error;
550 551

        thisSource->name = vgname;
552
    }
553 554
    else
        VIR_FREE(vgname);
555

556
    if (VIR_REALLOC_N(thisSource->devices, thisSource->ndevice + 1) != 0)
557
        goto error;
558

559 560
    dev = &thisSource->devices[thisSource->ndevice];
    thisSource->ndevice++;
561
    thisSource->format = VIR_STORAGE_POOL_LOGICAL_LVM2;
562 563 564

    memset(dev, 0, sizeof(*dev));
    dev->path = pvname;
565 566

    return 0;
567

568
 error:
569 570 571 572
    VIR_FREE(pvname);
    VIR_FREE(vgname);

    return -1;
573 574
}

575 576 577 578 579 580 581 582 583 584
/*
 * @sourceList: Pointer to a storage pool source list
 *
 * Use the pvs command to fill the list of pv_name and vg_name associated
 * into the passed sourceList.
 *
 * Returns 0 if successful, -1 and sets error on failure
 */
static int
virStorageBackendLogicalGetPoolSources(virStoragePoolSourceListPtr sourceList)
585 586
{
    /*
587 588 589
     * # pvs --noheadings -o pv_name,vg_name
     *   /dev/sdb
     *   /dev/sdc VolGroup00
590 591
     */
    const char *regexes[] = {
592
        "^\\s*(\\S+)\\s+(\\S+)\\s*$"
593 594
    };
    int vars[] = {
595
        2
596
    };
597
    virCommandPtr cmd;
598
    int ret = -1;
E
Eric Blake 已提交
599

600 601 602 603 604
    /*
     * 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
     */
605 606
    cmd = virCommandNew(VGSCAN);
    if (virCommandRun(cmd, NULL) < 0)
607
        VIR_WARN("Failure when running vgscan to refresh physical volumes");
608
    virCommandFree(cmd);
609

610 611 612
    cmd = virCommandNewArgList(PVS,
                               "--noheadings",
                               "-o", "pv_name,vg_name",
613
                               NULL, NULL);
614 615
    if (virCommandRunRegex(cmd, 1, regexes, vars,
                           virStorageBackendLogicalFindPoolSourcesFunc,
616
                           sourceList, "pvs", NULL) < 0)
617 618 619 620
        goto cleanup;
    ret = 0;

 cleanup:
621
    virCommandFree(cmd);
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
    return ret;
}


static char *
virStorageBackendLogicalFindPoolSources(virConnectPtr conn ATTRIBUTE_UNUSED,
                                        const char *srcSpec ATTRIBUTE_UNUSED,
                                        unsigned int flags)
{
    virStoragePoolSourceList sourceList;
    size_t i;
    char *retval = NULL;

    virCheckFlags(0, NULL);

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

    if (virStorageBackendLogicalGetPoolSources(&sourceList) < 0)
        goto cleanup;
642

643
    retval = virStoragePoolSourceListFormat(&sourceList);
644
    if (retval == NULL) {
645 646
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to get source from sourceList"));
647 648 649 650
        goto cleanup;
    }

 cleanup:
651
    for (i = 0; i < sourceList.nsources; i++)
652
        virStoragePoolSourceClear(&sourceList.sources[i]);
653
    VIR_FREE(sourceList.sources);
654 655 656 657 658

    return retval;
}


659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
/*
 * virStorageBackendLogicalMatchPoolSource
 * @pool: Pointer to the source pool object
 *
 * Search the output generated by a 'pvs --noheadings -o pv_name,vg_name'
 * to match the 'vg_name' with the pool def->source.name and for the list
 * of pool def->source.devices[].
 *
 * Returns true if the volume group name matches the pool's source.name
 * and at least one of the pool's def->source.devices[] matches the
 * list of physical device names listed for the pool. Return false if
 * we cannot find a matching volume group name and if we cannot match
 * the any device list members.
 */
static bool
virStorageBackendLogicalMatchPoolSource(virStoragePoolObjPtr pool)
{
    virStoragePoolSourceList sourceList;
677
    virStoragePoolSource *thisSource = NULL;
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701
    size_t i, j;
    int matchcount = 0;
    bool ret = false;

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

    if (virStorageBackendLogicalGetPoolSources(&sourceList) < 0)
        goto cleanup;

    /* Search the pvs output for this pool's source.name */
    for (i = 0; i < sourceList.nsources; i++) {
        thisSource = &sourceList.sources[i];
        if (STREQ(thisSource->name, pool->def->source.name))
            break;
    }

    if (i == sourceList.nsources) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("cannot find logical volume group name '%s'"),
                       pool->def->source.name);
        goto cleanup;
    }

702 703 704 705 706 707 708 709 710
    /* If the pool has defined source device(s), then let's make sure
     * they match as well; otherwise, matching can only occur on the
     * pool's name.
     */
    if (!pool->def->source.ndevice) {
        ret = true;
        goto cleanup;
    }

711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750
    /* Let's make sure the pool's device(s) match what the pvs output has
     * for volume group devices.
     */
    for (i = 0; i < pool->def->source.ndevice; i++) {
        for (j = 0; j < thisSource->ndevice; j++) {
            if (STREQ(pool->def->source.devices[i].path,
                      thisSource->devices[j].path))
                matchcount++;
        }
    }

    /* If we didn't find any matches, then this pool has listed (a) source
     * device path(s) that don't/doesn't match what was created for the pool
     */
    if (matchcount == 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("cannot find any matching source devices for logical "
                         "volume group '%s'"), pool->def->source.name);
        goto cleanup;
    }

    /* Either there's more devices in the pool source device list or there's
     * more devices in the pvs output. Could easily happen if someone decides
     * to 'add' to or 'remove' from the volume group outside of libvirt's
     * knowledge. Rather than fail on that, provide a warning and move on.
     */
    if (matchcount != pool->def->source.ndevice)
        VIR_WARN("pool device list count doesn't match pvs device list count");

    ret = true;

 cleanup:
    for (i = 0; i < sourceList.nsources; i++)
        virStoragePoolSourceClear(&sourceList.sources[i]);
    VIR_FREE(sourceList.sources);

    return ret;
}


751
static int
752
virStorageBackendLogicalCheckPool(virStoragePoolObjPtr pool,
753 754
                                  bool *isActive)
{
755 756 757 758 759
    /* If we can find the target.path as well as ensure that the
     * pool's def source
     */
    *isActive = virFileExists(pool->def->target.path) &&
                virStorageBackendLogicalMatchPoolSource(pool);
760 761 762
    return 0;
}

763
static int
764
virStorageBackendLogicalStartPool(virConnectPtr conn ATTRIBUTE_UNUSED,
765 766
                                  virStoragePoolObjPtr pool)
{
767 768 769 770 771
    /* Let's make sure that the pool's name matches the pvs output and
     * that the pool's source devices match the pvs output.
     */
    if (!virStorageBackendLogicalMatchPoolSource(pool) ||
        virStorageBackendLogicalSetActive(pool, 1) < 0)
772 773 774 775 776 777 778
        return -1;

    return 0;
}


static int
779
virStorageBackendLogicalBuildPool(virConnectPtr conn ATTRIBUTE_UNUSED,
780
                                  virStoragePoolObjPtr pool,
E
Eric Blake 已提交
781
                                  unsigned int flags)
782
{
783
    virCommandPtr vgcmd = NULL;
784
    int ret = -1;
785 786 787 788
    size_t i = 0;

    virCheckFlags(VIR_STORAGE_POOL_BUILD_OVERWRITE |
                  VIR_STORAGE_POOL_BUILD_NO_OVERWRITE, ret);
789

790 791 792
    VIR_EXCLUSIVE_FLAGS_GOTO(VIR_STORAGE_POOL_BUILD_OVERWRITE,
                             VIR_STORAGE_POOL_BUILD_NO_OVERWRITE,
                             cleanup);
E
Eric Blake 已提交
793

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

796
    for (i = 0; i < pool->def->source.ndevice; i++) {
797
        const char *path = pool->def->source.devices[i].path;
798

799 800 801 802 803 804 805
        /* The blkid FS and Part probing code doesn't know "lvm2" (this
         * pool's only format type), but it does know "LVM2_member", so
         * we'll pass that here */
        if (!(flags & VIR_STORAGE_POOL_BUILD_OVERWRITE) &&
            !virStorageBackendDeviceIsEmpty(path, "LVM2_member", true))
            goto cleanup;

806
        if (virStorageBackendLogicalInitializeDevice(path) < 0)
807 808
            goto cleanup;

809
        virCommandAddArg(vgcmd, path);
810
    }
811 812

    /* Now create the volume group itself */
813
    if (virCommandRun(vgcmd, NULL) < 0)
814 815
        goto cleanup;

816
    ret = 0;
817

818
 cleanup:
819
    virCommandFree(vgcmd);
820 821 822 823 824 825 826 827 828

    /* On any failure, run through the devices that had pvcreate run in
     * in order to run pvremove on the device; otherwise, subsequent build
     * will fail if a pvcreate had been run already. */
    if (ret < 0) {
        size_t j;
        for (j = 0; j < i; j++)
            virStorageBackendLogicalRemoveDevice(pool->def->source.devices[j].path);
    }
829
    return ret;
830 831 832 833
}


static int
834
virStorageBackendLogicalRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
835 836 837 838 839 840 841
                                    virStoragePoolObjPtr pool)
{
    /*
     *  # vgs --separator : --noheadings --units b --unbuffered --nosuffix --options "vg_size,vg_free" VGNAME
     *    10603200512:4328521728
     *
     * Pull out size & free
842 843
     *
     * NB vgs from some distros (e.g. SLES10 SP2) outputs trailing ":" on each line
844 845
     */
    const char *regexes[] = {
846
        "^\\s*(\\S+):([0-9]+):?\\s*$"
847 848 849 850
    };
    int vars[] = {
        2
    };
851 852
    virCommandPtr cmd = NULL;
    int ret = -1;
853

J
John Ferlan 已提交
854
    virWaitForDevices();
855

856
    /* Get list of all logical volumes */
857 858 859 860 861 862 863 864 865 866 867 868
    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);
869 870

    /* Now get basic volgrp metadata */
871 872 873 874 875 876
    if (virCommandRunRegex(cmd,
                           1,
                           regexes,
                           vars,
                           virStorageBackendLogicalRefreshPoolFunc,
                           pool,
877 878
                           "vgs",
                           NULL) < 0)
879
        goto cleanup;
880

881 882
    ret = 0;

883
 cleanup:
884 885 886 887
    virCommandFree(cmd);
    if (ret < 0)
        virStoragePoolObjClearVols(pool);
    return ret;
888 889
}

890 891 892 893
/*
 * 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)"
894 895
 */
static int
896
virStorageBackendLogicalStopPool(virConnectPtr conn ATTRIBUTE_UNUSED,
897 898
                                 virStoragePoolObjPtr pool)
{
899
    if (virStorageBackendLogicalSetActive(pool, 0) < 0)
900 901 902 903 904 905
        return -1;

    return 0;
}

static int
906
virStorageBackendLogicalDeletePool(virConnectPtr conn ATTRIBUTE_UNUSED,
907
                                   virStoragePoolObjPtr pool,
E
Eric Blake 已提交
908
                                   unsigned int flags)
909
{
910 911 912
    virCommandPtr cmd = NULL;
    size_t i;
    int ret = -1;
913

E
Eric Blake 已提交
914 915
    virCheckFlags(0, -1);

916
    /* first remove the volume group */
917 918 919 920 921
    cmd = virCommandNewArgList(VGREMOVE,
                               "-f", pool->def->source.name,
                               NULL);
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;
922

923
    /* now remove the pv devices and clear them out */
924 925 926
    for (i = 0; i < pool->def->source.ndevice; i++)
        virStorageBackendLogicalRemoveDevice(pool->def->source.devices[i].path);

927
    ret = 0;
928

929
 cleanup:
930 931
    virCommandFree(cmd);
    return ret;
932 933 934 935
}


static int
936 937
virStorageBackendLogicalDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
938
                                  virStorageVolDefPtr vol,
939 940 941 942 943 944 945 946 947
                                  unsigned int flags)
{
    int ret = -1;

    virCommandPtr lvchange_cmd = NULL;
    virCommandPtr lvremove_cmd = NULL;

    virCheckFlags(0, -1);

J
John Ferlan 已提交
948
    virWaitForDevices();
949 950 951 952 953 954 955 956 957 958 959 960 961 962

    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;
963
 cleanup:
964 965 966 967
    virCommandFree(lvchange_cmd);
    virCommandFree(lvremove_cmd);
    return ret;
}
968 969 970


static int
971 972 973
virStorageBackendLogicalCreateVol(virConnectPtr conn,
                                  virStoragePoolObjPtr pool,
                                  virStorageVolDefPtr vol)
974
{
975
    int fd = -1;
976
    virCommandPtr cmd = NULL;
977
    virErrorPtr err;
978
    struct stat sb;
979
    bool created = false;
980

981 982 983 984 985 986 987 988 989
    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;

990
    VIR_FREE(vol->target.path);
991 992 993 994
    if (virAsprintf(&vol->target.path, "%s/%s",
                    pool->def->target.path,
                    vol->name) == -1)
        return -1;
995

996 997 998 999
    cmd = virCommandNewArgList(LVCREATE,
                               "--name", vol->name,
                               NULL);
    virCommandAddArg(cmd, "-L");
1000
    if (vol->target.capacity != vol->target.allocation) {
1001
        virCommandAddArgFormat(cmd, "%lluK",
1002 1003
                               VIR_DIV_UP(vol->target.allocation
                                          ? vol->target.allocation : 1, 1024));
1004
        virCommandAddArgList(cmd, "--type", "snapshot", NULL);
1005
        virCommandAddArg(cmd, "--virtualsize");
1006
        vol->target.sparse = true;
1007
    }
1008 1009
    virCommandAddArgFormat(cmd, "%lluK", VIR_DIV_UP(vol->target.capacity,
                                                    1024));
1010 1011
    if (vol->target.backingStore)
        virCommandAddArgList(cmd, "-s", vol->target.backingStore->path, NULL);
1012 1013 1014 1015
    else
        virCommandAddArg(cmd, pool->def->source.name);

    if (virCommandRun(cmd, NULL) < 0)
1016
        goto error;
1017

1018
    created = true;
1019 1020 1021
    virCommandFree(cmd);
    cmd = NULL;

1022 1023
    if ((fd = virStorageBackendVolOpen(vol->target.path, &sb,
                                       VIR_STORAGE_VOL_OPEN_DEFAULT)) < 0)
1024
        goto error;
1025 1026

    /* We can only chown/grp if root */
1027
    if (geteuid() == 0) {
1028
        if (fchown(fd, vol->target.perms->uid, vol->target.perms->gid) < 0) {
1029
            virReportSystemError(errno,
1030 1031
                                 _("cannot set file owner '%s'"),
                                 vol->target.path);
1032
            goto error;
1033 1034
        }
    }
1035 1036 1037
    if (fchmod(fd, (vol->target.perms->mode == (mode_t) -1 ?
                    VIR_STORAGE_DEFAULT_VOL_PERM_MODE :
                    vol->target.perms->mode)) < 0) {
1038
        virReportSystemError(errno,
1039 1040
                             _("cannot set file mode '%s'"),
                             vol->target.path);
1041
        goto error;
1042 1043
    }

1044
    if (VIR_CLOSE(fd) < 0) {
1045
        virReportSystemError(errno,
1046 1047
                             _("cannot close file '%s'"),
                             vol->target.path);
1048
        goto error;
1049 1050 1051
    }

    /* Fill in data about this new vol */
1052
    if (virStorageBackendLogicalFindLVs(pool, vol) < 0) {
1053
        virReportSystemError(errno,
1054 1055
                             _("cannot find newly created volume '%s'"),
                             vol->target.path);
1056
        goto error;
1057 1058 1059 1060
    }

    return 0;

1061
 error:
1062
    err = virSaveLastError();
1063
    VIR_FORCE_CLOSE(fd);
1064 1065
    if (created)
        virStorageBackendLogicalDeleteVol(conn, pool, vol, 0);
1066
    virCommandFree(cmd);
1067
    virSetError(err);
1068
    virFreeError(err);
1069 1070 1071
    return -1;
}

1072 1073
static int
virStorageBackendLogicalBuildVolFrom(virConnectPtr conn,
1074
                                     virStoragePoolObjPtr pool,
1075 1076 1077 1078 1079 1080
                                     virStorageVolDefPtr vol,
                                     virStorageVolDefPtr inputvol,
                                     unsigned int flags)
{
    virStorageBackendBuildVolFrom build_func;

1081
    build_func = virStorageBackendGetBuildVolFromFunction(vol, inputvol);
1082 1083 1084
    if (!build_func)
        return -1;

1085
    return build_func(conn, pool, vol, inputvol, flags);
1086 1087
}

1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
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 已提交
1111 1112
                   _("logical volume '%s' is sparse, volume wipe "
                     "not supported"),
1113 1114 1115
                   vol->target.path);
    return -1;
}
1116 1117 1118 1119

virStorageBackend virStorageBackendLogical = {
    .type = VIR_STORAGE_POOL_LOGICAL,

1120
    .findPoolSources = virStorageBackendLogicalFindPoolSources,
1121
    .checkPool = virStorageBackendLogicalCheckPool,
1122 1123 1124 1125 1126
    .startPool = virStorageBackendLogicalStartPool,
    .buildPool = virStorageBackendLogicalBuildPool,
    .refreshPool = virStorageBackendLogicalRefreshPool,
    .stopPool = virStorageBackendLogicalStopPool,
    .deletePool = virStorageBackendLogicalDeletePool,
1127
    .buildVol = NULL,
1128
    .buildVolFrom = virStorageBackendLogicalBuildVolFrom,
1129 1130
    .createVol = virStorageBackendLogicalCreateVol,
    .deleteVol = virStorageBackendLogicalDeleteVol,
1131 1132
    .uploadVol = virStorageBackendVolUploadLocal,
    .downloadVol = virStorageBackendVolDownloadLocal,
1133
    .wipeVol = virStorageBackendLogicalVolWipe,
1134
};
1135 1136 1137 1138 1139 1140 1141


int
virStorageBackendLogicalRegister(void)
{
    return virStorageBackendRegister(&virStorageBackendLogical);
}