storage_backend_logical.c 33.7 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

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
#define VIR_STORAGE_VOL_LOGICAL_SEGTYPE_STRIPED "striped"
68 69
#define VIR_STORAGE_VOL_LOGICAL_SEGTYPE_MIRROR  "mirror"
#define VIR_STORAGE_VOL_LOGICAL_SEGTYPE_RAID    "raid"
70

71 72 73 74 75
struct virStorageBackendLogicalPoolVolData {
    virStoragePoolObjPtr pool;
    virStorageVolDefPtr vol;
};

76
static int
77 78
virStorageBackendLogicalParseVolExtents(virStorageVolDefPtr vol,
                                        char **const groups)
79
{
80
    int nextents, ret = -1;
81 82 83 84 85
    const char *regex_unit = "(\\S+)\\((\\S+)\\)";
    char *regex = NULL;
    regex_t *reg = NULL;
    regmatch_t *vars = NULL;
    char *p = NULL;
86
    size_t i;
87 88
    int err, nvars;
    unsigned long long offset, size, length;
89 90 91
    virStorageVolSourceExtent extent;

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

93 94 95 96 97 98 99
    /* 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
     */
100
    nextents = 1;
101 102 103
    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)) {
104
        if (virStrToLong_i(groups[5], NULL, 10, &nextents) < 0) {
105 106
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("malformed volume extent stripes value"));
107 108 109
            goto cleanup;
        }
    }
110

111
    if (virStrToLong_ull(groups[6], NULL, 10, &length) < 0) {
112 113
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("malformed volume extent length value"));
114 115
        goto cleanup;
    }
116

117
    if (virStrToLong_ull(groups[7], NULL, 10, &size) < 0) {
118 119
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("malformed volume extent size value"));
120 121 122
        goto cleanup;
    }

123 124
    /* Allocate space for 'nextents' regex_unit strings plus a comma for each */
    if (VIR_ALLOC_N(regex, nextents * (strlen(regex_unit) + 1) + 1) < 0)
125
        goto cleanup;
126
    strncat(regex, regex_unit, strlen(regex_unit));
127
    for (i = 1; i < nextents; i++) {
E
Eric Blake 已提交
128
        /* "," is the separator of "devices" field */
129 130 131 132
        strcat(regex, ",");
        strncat(regex, regex_unit, strlen(regex_unit));
    }

133
    if (VIR_ALLOC(reg) < 0)
134
        goto cleanup;
135

136 137 138 139
    /* Each extent has a "path:offset" pair, and vars[0] will
     * be the whole matched string.
     */
    nvars = (nextents * 2) + 1;
140
    if (VIR_ALLOC_N(vars, nvars) < 0)
141 142 143 144 145 146
        goto cleanup;

    err = regcomp(reg, regex, REG_EXTENDED);
    if (err != 0) {
        char error[100];
        regerror(err, reg, error, sizeof(error));
147 148 149
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to compile regex %s"),
                       error);
150
        goto cleanup;
151
    }
152

153 154 155
    err = regexec(reg, groups[3], nvars, vars, 0);
    regfree(reg);
    if (err != 0) {
156 157
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("malformed volume extent devices value"));
158
        goto cleanup;
159 160
    }

161
    p = groups[3];
162

163 164
    /* vars[0] is skipped */
    for (i = 0; i < nextents; i++) {
165 166
        size_t j;
        int len;
167
        char *offset_str = NULL;
168 169 170 171 172

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

173
        if (VIR_STRNDUP(extent.path,
174
                        p + vars[j].rm_so, len) < 0)
175 176 177
            goto cleanup;

        len = vars[j + 1].rm_eo - vars[j + 1].rm_so;
178
        if (VIR_STRNDUP(offset_str, p + vars[j + 1].rm_so, len) < 0)
179 180 181
            goto cleanup;

        if (virStrToLong_ull(offset_str, NULL, 10, &offset) < 0) {
182 183
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("malformed volume extent offset value"));
E
Eric Blake 已提交
184
            VIR_FREE(offset_str);
185 186 187
            goto cleanup;
        }
        VIR_FREE(offset_str);
188 189
        extent.start = offset * size;
        extent.end = (offset * size) + length;
190

191 192 193
        if (VIR_APPEND_ELEMENT(vol->source.extents, vol->source.nextent,
                               extent) < 0)
            goto cleanup;
194 195
    }

196 197 198 199 200 201
    ret = 0;

 cleanup:
    VIR_FREE(regex);
    VIR_FREE(reg);
    VIR_FREE(vars);
202
    VIR_FREE(extent.path);
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
    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;

303 304 305
    if (is_new_vol &&
        VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0)
        goto cleanup;
306

307 308
    ret = 0;

309
 cleanup:
310 311 312
    if (is_new_vol && (ret == -1))
        virStorageVolDefFree(vol);
    return ret;
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
#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

343
static int
344
virStorageBackendLogicalFindLVs(virStoragePoolObjPtr pool,
345 346 347
                                virStorageVolDefPtr vol)
{
    /*
348 349
     * # 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 已提交
350
     *
351 352 353 354 355 356
     * 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-
357
     *
O
Osier Yang 已提交
358 359
     * Pull out name, origin, & uuid, device, device extent start #,
     * segment size, extent size, size, attrs
360 361
     *
     * NB can be multiple rows per volume if they have many extents
362
     *
363 364
     * NB lvs from some distros (e.g. SLES10 SP2) outputs trailing ","
     * on each line
365 366 367
     *
     * NB Encrypted logical volumes can print ':' in their name, so it is
     *    not a suitable separator (rhbz 470693).
368
     *
369 370
     * NB "devices" field has multiple device paths and "," if the volume is
     *    striped, so "," is not a suitable separator either (rhbz 727474).
371 372
     */
    const char *regexes[] = {
373
        VIR_STORAGE_VOL_LOGICAL_REGEX
374 375
    };
    int vars[] = {
376
        VIR_STORAGE_VOL_LOGICAL_REGEX_COUNT
377
    };
378 379
    int ret = -1;
    virCommandPtr cmd;
380 381 382 383
    struct virStorageBackendLogicalPoolVolData cbdata = {
        .pool = pool,
        .vol = vol,
    };
384 385 386 387 388 389 390

    cmd = virCommandNewArgList(LVS,
                               "--separator", "#",
                               "--noheadings",
                               "--units", "b",
                               "--unbuffered",
                               "--nosuffix",
O
Osier Yang 已提交
391 392
                               "--options",
                               "lv_name,origin,uuid,devices,segtype,stripes,seg_size,vg_extent_size,size,lv_attr",
393 394
                               pool->def->source.name,
                               NULL);
395 396 397 398 399 400 401
    if (virCommandRunRegex(cmd,
                           1,
                           regexes,
                           vars,
                           virStorageBackendLogicalMakeVol,
                           &cbdata,
                           "lvs") < 0)
402
        goto cleanup;
403

404
    ret = 0;
405
 cleanup:
406 407
    virCommandFree(cmd);
    return ret;
408 409 410
}

static int
411 412
virStorageBackendLogicalRefreshPoolFunc(char **const groups,
                                        void *data)
413
{
414
    virStoragePoolObjPtr pool = data;
415 416 417 418 419 420 421 422 423 424
    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;
}


425
static int
426
virStorageBackendLogicalFindPoolSourcesFunc(char **const groups,
427 428
                                            void *data)
{
429 430 431
    virStoragePoolSourceListPtr sourceList = data;
    char *pvname = NULL;
    char *vgname = NULL;
432
    size_t i;
433 434 435
    virStoragePoolSourceDevicePtr dev;
    virStoragePoolSource *thisSource;

436 437 438
    if (VIR_STRDUP(pvname, groups[0]) < 0 ||
        VIR_STRDUP(vgname, groups[1]) < 0)
        goto error;
439 440

    thisSource = NULL;
441
    for (i = 0; i < sourceList->nsources; i++) {
442 443 444 445 446
        if (STREQ(sourceList->sources[i].name, vgname)) {
            thisSource = &sourceList->sources[i];
            break;
        }
    }
447

448
    if (thisSource == NULL) {
449
        if (!(thisSource = virStoragePoolSourceListNewSource(sourceList)))
450
            goto error;
451 452

        thisSource->name = vgname;
453
    }
454 455
    else
        VIR_FREE(vgname);
456

457
    if (VIR_REALLOC_N(thisSource->devices, thisSource->ndevice + 1) != 0)
458
        goto error;
459

460 461
    dev = &thisSource->devices[thisSource->ndevice];
    thisSource->ndevice++;
462
    thisSource->format = VIR_STORAGE_POOL_LOGICAL_LVM2;
463 464 465

    memset(dev, 0, sizeof(*dev));
    dev->path = pvname;
466 467

    return 0;
468

469
 error:
470 471 472 473
    VIR_FREE(pvname);
    VIR_FREE(vgname);

    return -1;
474 475
}

476 477 478 479 480 481 482 483 484 485
/*
 * @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)
486 487
{
    /*
488 489 490
     * # pvs --noheadings -o pv_name,vg_name
     *   /dev/sdb
     *   /dev/sdc VolGroup00
491 492
     */
    const char *regexes[] = {
493
        "^\\s*(\\S+)\\s+(\\S+)\\s*$"
494 495
    };
    int vars[] = {
496
        2
497
    };
498
    virCommandPtr cmd;
499
    int ret = -1;
E
Eric Blake 已提交
500

501 502 503 504 505
    /*
     * 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
     */
506 507
    cmd = virCommandNew(VGSCAN);
    if (virCommandRun(cmd, NULL) < 0)
508
        VIR_WARN("Failure when running vgscan to refresh physical volumes");
509
    virCommandFree(cmd);
510

511 512 513 514
    cmd = virCommandNewArgList(PVS,
                               "--noheadings",
                               "-o", "pv_name,vg_name",
                               NULL);
515 516
    if (virCommandRunRegex(cmd, 1, regexes, vars,
                           virStorageBackendLogicalFindPoolSourcesFunc,
517 518 519 520 521
                           sourceList, "pvs") < 0)
        goto cleanup;
    ret = 0;

 cleanup:
522
    virCommandFree(cmd);
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542
    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;
543

544
    retval = virStoragePoolSourceListFormat(&sourceList);
545
    if (retval == NULL) {
546 547
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to get source from sourceList"));
548 549 550 551
        goto cleanup;
    }

 cleanup:
552
    for (i = 0; i < sourceList.nsources; i++)
553
        virStoragePoolSourceClear(&sourceList.sources[i]);
554
    VIR_FREE(sourceList.sources);
555 556 557 558 559

    return retval;
}


560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
/*
 * 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;
    virStoragePoolSource *thisSource;
    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;
    }

603 604 605 606 607 608 609 610 611
    /* 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;
    }

612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
    /* 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;
}


652
static int
653
virStorageBackendLogicalCheckPool(virStoragePoolObjPtr pool,
654 655
                                  bool *isActive)
{
656 657 658 659 660
    /* 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);
661 662 663
    return 0;
}

664
static int
665
virStorageBackendLogicalStartPool(virConnectPtr conn ATTRIBUTE_UNUSED,
666 667
                                  virStoragePoolObjPtr pool)
{
668 669 670 671 672
    /* 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)
673 674 675 676 677 678 679
        return -1;

    return 0;
}


static int
680
virStorageBackendLogicalBuildPool(virConnectPtr conn ATTRIBUTE_UNUSED,
681
                                  virStoragePoolObjPtr pool,
E
Eric Blake 已提交
682
                                  unsigned int flags)
683
{
684 685
    virCommandPtr vgcmd;
    int fd;
686
    char zeros[PV_BLANK_SECTOR_SIZE];
687 688
    int ret = -1;
    size_t i;
689

E
Eric Blake 已提交
690 691
    virCheckFlags(0, -1);

692 693
    memset(zeros, 0, sizeof(zeros));

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

696
    for (i = 0; i < pool->def->source.ndevice; i++) {
697
        virCommandPtr pvcmd;
698 699 700 701 702 703
        /*
         * 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) {
704
            virReportSystemError(errno,
705 706
                                 _("cannot open device '%s'"),
                                 pool->def->source.devices[i].path);
707 708
            goto cleanup;
        }
709
        if (safewrite(fd, zeros, sizeof(zeros)) < 0) {
710
            virReportSystemError(errno,
711 712
                                 _("cannot clear device header of '%s'"),
                                 pool->def->source.devices[i].path);
713 714 715 716 717 718 719
            VIR_FORCE_CLOSE(fd);
            goto cleanup;
        }
        if (fsync(fd) < 0) {
            virReportSystemError(errno,
                                 _("cannot flush header of device'%s'"),
                                 pool->def->source.devices[i].path);
720
            VIR_FORCE_CLOSE(fd);
721 722
            goto cleanup;
        }
723
        if (VIR_CLOSE(fd) < 0) {
724
            virReportSystemError(errno,
725 726
                                 _("cannot close device '%s'"),
                                 pool->def->source.devices[i].path);
727 728 729 730 731 732 733
            goto cleanup;
        }

        /*
         * Initialize the physical volume because vgcreate is not
         * clever enough todo this for us :-(
         */
734 735 736 737 738
        pvcmd = virCommandNewArgList(PVCREATE,
                                     pool->def->source.devices[i].path,
                                     NULL);
        if (virCommandRun(pvcmd, NULL) < 0) {
            virCommandFree(pvcmd);
739
            goto cleanup;
740 741
        }
        virCommandFree(pvcmd);
742

743 744
        virCommandAddArg(vgcmd, pool->def->source.devices[i].path);
    }
745 746

    /* Now create the volume group itself */
747
    if (virCommandRun(vgcmd, NULL) < 0)
748 749
        goto cleanup;

750
    ret = 0;
751

752
 cleanup:
753 754
    virCommandFree(vgcmd);
    return ret;
755 756 757 758
}


static int
759
virStorageBackendLogicalRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
760 761 762 763 764 765 766
                                    virStoragePoolObjPtr pool)
{
    /*
     *  # vgs --separator : --noheadings --units b --unbuffered --nosuffix --options "vg_size,vg_free" VGNAME
     *    10603200512:4328521728
     *
     * Pull out size & free
767 768
     *
     * NB vgs from some distros (e.g. SLES10 SP2) outputs trailing ":" on each line
769 770
     */
    const char *regexes[] = {
771
        "^\\s*(\\S+):([0-9]+):?\\s*$"
772 773 774 775
    };
    int vars[] = {
        2
    };
776 777
    virCommandPtr cmd = NULL;
    int ret = -1;
778

779
    virFileWaitForDevices();
780

781
    /* Get list of all logical volumes */
782 783 784 785 786 787 788 789 790 791 792 793
    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);
794 795

    /* Now get basic volgrp metadata */
796 797 798 799 800 801 802
    if (virCommandRunRegex(cmd,
                           1,
                           regexes,
                           vars,
                           virStorageBackendLogicalRefreshPoolFunc,
                           pool,
                           "vgs") < 0)
803
        goto cleanup;
804

805 806
    ret = 0;

807
 cleanup:
808 809 810 811
    virCommandFree(cmd);
    if (ret < 0)
        virStoragePoolObjClearVols(pool);
    return ret;
812 813
}

814 815 816 817
/*
 * 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)"
818 819
 */
static int
820
virStorageBackendLogicalStopPool(virConnectPtr conn ATTRIBUTE_UNUSED,
821 822
                                 virStoragePoolObjPtr pool)
{
823
    if (virStorageBackendLogicalSetActive(pool, 0) < 0)
824 825 826 827 828 829
        return -1;

    return 0;
}

static int
830
virStorageBackendLogicalDeletePool(virConnectPtr conn ATTRIBUTE_UNUSED,
831
                                   virStoragePoolObjPtr pool,
E
Eric Blake 已提交
832
                                   unsigned int flags)
833
{
834 835 836
    virCommandPtr cmd = NULL;
    size_t i;
    int ret = -1;
837

E
Eric Blake 已提交
838 839
    virCheckFlags(0, -1);

840
    /* first remove the volume group */
841 842 843 844 845 846
    cmd = virCommandNewArgList(VGREMOVE,
                               "-f", pool->def->source.name,
                               NULL);
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;
    virCommandFree(cmd);
847
    cmd = NULL;
848

849
    /* now remove the pv devices and clear them out */
850
    ret = 0;
851
    for (i = 0; i < pool->def->source.ndevice; i++) {
852 853 854 855 856
        cmd = virCommandNewArgList(PVREMOVE,
                                   pool->def->source.devices[i].path,
                                   NULL);
        if (virCommandRun(cmd, NULL) < 0) {
            ret = -1;
857 858
            break;
        }
859 860
        virCommandFree(cmd);
        cmd = NULL;
861
    }
862

863
 cleanup:
864 865
    virCommandFree(cmd);
    return ret;
866 867 868 869
}


static int
870 871
virStorageBackendLogicalDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
872
                                  virStorageVolDefPtr vol,
873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896
                                  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;
897
 cleanup:
898 899 900 901
    virCommandFree(lvchange_cmd);
    virCommandFree(lvremove_cmd);
    return ret;
}
902 903 904


static int
905 906 907
virStorageBackendLogicalCreateVol(virConnectPtr conn,
                                  virStoragePoolObjPtr pool,
                                  virStorageVolDefPtr vol)
908
{
909
    int fd = -1;
910
    virCommandPtr cmd = NULL;
911
    virErrorPtr err;
912
    struct stat sb;
913
    bool created = false;
914

915 916 917 918 919 920 921 922 923
    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;

924 925
    /* A target path passed to CreateVol has no meaning */
    VIR_FREE(vol->target.path);
926 927 928 929 930

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

932 933 934 935
    cmd = virCommandNewArgList(LVCREATE,
                               "--name", vol->name,
                               NULL);
    virCommandAddArg(cmd, "-L");
936
    if (vol->target.capacity != vol->target.allocation) {
937
        virCommandAddArgFormat(cmd, "%lluK",
938 939
                               VIR_DIV_UP(vol->target.allocation
                                          ? vol->target.allocation : 1, 1024));
940
        virCommandAddArgList(cmd, "--type", "snapshot", NULL);
941
        virCommandAddArg(cmd, "--virtualsize");
942
        vol->target.sparse = true;
943
    }
944 945
    virCommandAddArgFormat(cmd, "%lluK", VIR_DIV_UP(vol->target.capacity,
                                                    1024));
946 947
    if (vol->target.backingStore)
        virCommandAddArgList(cmd, "-s", vol->target.backingStore->path, NULL);
948 949 950 951
    else
        virCommandAddArg(cmd, pool->def->source.name);

    if (virCommandRun(cmd, NULL) < 0)
952
        goto error;
953

954
    created = true;
955 956 957
    virCommandFree(cmd);
    cmd = NULL;

958 959
    if ((fd = virStorageBackendVolOpen(vol->target.path, &sb,
                                       VIR_STORAGE_VOL_OPEN_DEFAULT)) < 0)
960
        goto error;
961 962

    /* We can only chown/grp if root */
963
    if (geteuid() == 0) {
964
        if (fchown(fd, vol->target.perms->uid, vol->target.perms->gid) < 0) {
965
            virReportSystemError(errno,
966 967
                                 _("cannot set file owner '%s'"),
                                 vol->target.path);
968
            goto error;
969 970
        }
    }
971 972 973
    if (fchmod(fd, (vol->target.perms->mode == (mode_t) -1 ?
                    VIR_STORAGE_DEFAULT_VOL_PERM_MODE :
                    vol->target.perms->mode)) < 0) {
974
        virReportSystemError(errno,
975 976
                             _("cannot set file mode '%s'"),
                             vol->target.path);
977
        goto error;
978 979
    }

980
    if (VIR_CLOSE(fd) < 0) {
981
        virReportSystemError(errno,
982 983
                             _("cannot close file '%s'"),
                             vol->target.path);
984
        goto error;
985 986 987
    }

    /* Fill in data about this new vol */
988
    if (virStorageBackendLogicalFindLVs(pool, vol) < 0) {
989
        virReportSystemError(errno,
990 991
                             _("cannot find newly created volume '%s'"),
                             vol->target.path);
992
        goto error;
993 994 995 996
    }

    return 0;

997
 error:
998
    err = virSaveLastError();
999
    VIR_FORCE_CLOSE(fd);
1000 1001
    if (created)
        virStorageBackendLogicalDeleteVol(conn, pool, vol, 0);
1002
    virCommandFree(cmd);
1003
    virSetError(err);
1004
    virFreeError(err);
1005 1006 1007
    return -1;
}

1008 1009
static int
virStorageBackendLogicalBuildVolFrom(virConnectPtr conn,
1010
                                     virStoragePoolObjPtr pool,
1011 1012 1013 1014 1015 1016
                                     virStorageVolDefPtr vol,
                                     virStorageVolDefPtr inputvol,
                                     unsigned int flags)
{
    virStorageBackendBuildVolFrom build_func;

1017
    build_func = virStorageBackendGetBuildVolFromFunction(vol, inputvol);
1018 1019 1020
    if (!build_func)
        return -1;

1021
    return build_func(conn, pool, vol, inputvol, flags);
1022 1023
}

1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
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 已提交
1047 1048
                   _("logical volume '%s' is sparse, volume wipe "
                     "not supported"),
1049 1050 1051
                   vol->target.path);
    return -1;
}
1052 1053 1054 1055

virStorageBackend virStorageBackendLogical = {
    .type = VIR_STORAGE_POOL_LOGICAL,

1056
    .findPoolSources = virStorageBackendLogicalFindPoolSources,
1057
    .checkPool = virStorageBackendLogicalCheckPool,
1058 1059 1060 1061 1062
    .startPool = virStorageBackendLogicalStartPool,
    .buildPool = virStorageBackendLogicalBuildPool,
    .refreshPool = virStorageBackendLogicalRefreshPool,
    .stopPool = virStorageBackendLogicalStopPool,
    .deletePool = virStorageBackendLogicalDeletePool,
1063
    .buildVol = NULL,
1064
    .buildVolFrom = virStorageBackendLogicalBuildVolFrom,
1065 1066
    .createVol = virStorageBackendLogicalCreateVol,
    .deleteVol = virStorageBackendLogicalDeleteVol,
1067 1068
    .uploadVol = virStorageBackendVolUploadLocal,
    .downloadVol = virStorageBackendVolDownloadLocal,
1069
    .wipeVol = virStorageBackendLogicalVolWipe,
1070
};