storage_backend_disk.c 35.0 KB
Newer Older
1 2 3
/*
 * storage_backend_disk.c: storage backend for disk handling
 *
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
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 */

#include <config.h>
25
#include <unistd.h>
26

27
#include "dirname.h"
28
#include "virerror.h"
29
#include "virlog.h"
30
#include "storage_backend_disk.h"
31
#include "storage_util.h"
32
#include "viralloc.h"
33
#include "vircommand.h"
34
#include "virfile.h"
35
#include "configmake.h"
36
#include "virstring.h"
37

38 39
#define VIR_FROM_THIS VIR_FROM_STORAGE

40 41
VIR_LOG_INIT("storage.storage_backend_disk");

42 43
#define SECTOR_SIZE 512

44 45 46 47 48 49 50 51 52 53 54
static bool
virStorageVolPartFindExtended(virStorageVolDefPtr def,
                              const void *opaque ATTRIBUTE_UNUSED)
{
    if (def->source.partType == VIR_STORAGE_VOL_DISK_TYPE_EXTENDED)
        return true;

    return false;
}


55
static int
56
virStorageBackendDiskMakeDataVol(virStoragePoolObjPtr pool,
57 58 59
                                 char **const groups,
                                 virStorageVolDefPtr vol)
{
60
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
61
    char *tmp, *devpath, *partname;
62
    bool addVol = false;
63 64 65 66 67 68 69 70

    /* Prepended path will be same for all partitions, so we can
     * strip the path to form a reasonable pool-unique name
     */
    if ((tmp = strrchr(groups[0], '/')))
        partname = tmp + 1;
    else
        partname = groups[0];
71 72

    if (vol == NULL) {
73 74 75
        /* This is typically a reload/restart/refresh path where
         * we're discovering the existing partitions for the pool
         */
76
        addVol = true;
77
        if (VIR_ALLOC(vol) < 0)
78
            return -1;
79 80
        if (VIR_STRDUP(vol->name, partname) < 0)
            goto error;
81 82 83
    }

    if (vol->target.path == NULL) {
84
        if (VIR_STRDUP(devpath, groups[0]) < 0)
85
            goto error;
86 87 88 89 90 91 92

        /* Now figure out the stable path
         *
         * XXX this method is O(N) because it scans the pool target
         * dir every time its run. Should figure out a more efficient
         * way of doing this...
         */
93
        vol->target.path = virStorageBackendStablePath(pool, devpath, true);
94
        VIR_FREE(devpath);
95
        if (vol->target.path == NULL)
96
            goto error;
97 98
    }

99 100 101 102 103 104 105 106
    /* Enforce provided vol->name is the same as what parted created.
     * We do this after filling target.path so that we have a chance at
     * deleting the partition with this failure from CreateVol path
     */
    if (STRNEQ(vol->name, partname)) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid partition name '%s', expected '%s'"),
                       vol->name, partname);
107 108 109 110 111 112 113 114

        /* Let's see if by chance parthelper created a name that won't be
         * found later when we try to delete. We tell parthelper to add a 'p'
         * to the output via the part_separator flag, but if devmapper has
         * user_friendly_names set, the creation won't happen that way, thus
         * our deletion will fail because the name we generated is wrong.
         * Check for our conditions and see if the generated name is the
         * same as StablePath returns and has the 'p' in it */
115
        if (def->source.devices[0].part_separator == VIR_TRISTATE_BOOL_YES &&
116 117 118 119 120 121 122 123 124 125 126 127 128
            !virIsDevMapperDevice(vol->target.path) &&
            STREQ(groups[0], vol->target.path) &&
            (tmp = strrchr(groups[0], 'p'))) {

            /* If we remove the 'p' from groups[0] and the resulting
             * device is a devmapper device, then we know parthelper
             * was told to create the wrong name based on the results.
             * So just remove the 'p' from the vol->target.path too. */
            memmove(tmp, tmp + 1, strlen(tmp));
            if (virIsDevMapperDevice(groups[0]) &&
                (tmp = strrchr(vol->target.path, 'p')))
                memmove(tmp, tmp + 1, strlen(tmp));
        }
129
        goto error;
130 131
    }

132 133
    if (vol->key == NULL) {
        /* XXX base off a unique key of the underlying disk */
134
        if (VIR_STRDUP(vol->key, vol->target.path) < 0)
135
            goto error;
136 137 138
    }

    if (vol->source.extents == NULL) {
139
        if (VIR_ALLOC(vol->source.extents) < 0)
140
            goto error;
141 142 143 144
        vol->source.nextent = 1;

        if (virStrToLong_ull(groups[3], NULL, 10,
                             &vol->source.extents[0].start) < 0) {
145 146
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("cannot parse device start location"));
147
            goto error;
148 149 150 151
        }

        if (virStrToLong_ull(groups[4], NULL, 10,
                             &vol->source.extents[0].end) < 0) {
152 153
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("cannot parse device end location"));
154
            goto error;
155 156
        }

157
        if (VIR_STRDUP(vol->source.extents[0].path,
158
                       def->source.devices[0].path) < 0)
159
            goto error;
160 161
    }

162
    /* set partition type */
E
Eric Blake 已提交
163
    if (STREQ(groups[1], "normal"))
164
       vol->source.partType = VIR_STORAGE_VOL_DISK_TYPE_PRIMARY;
E
Eric Blake 已提交
165
    else if (STREQ(groups[1], "logical"))
166
       vol->source.partType = VIR_STORAGE_VOL_DISK_TYPE_LOGICAL;
E
Eric Blake 已提交
167
    else if (STREQ(groups[1], "extended"))
168
       vol->source.partType = VIR_STORAGE_VOL_DISK_TYPE_EXTENDED;
169
    else
170
       vol->source.partType = VIR_STORAGE_VOL_DISK_TYPE_NONE;
171

172 173
    vol->type = VIR_STORAGE_VOL_BLOCK;

174 175 176 177 178 179 180 181 182 183
    /* Refresh allocation/capacity/perms
     *
     * For an extended partition, virStorageBackendUpdateVolInfo will
     * return incorrect values for allocation and capacity, so use the
     * extent information captured above instead.
     *
     * Also once a logical partition exists or another primary partition
     * after an extended partition is created an open on the extended
     * partition will fail, so pass the NOERROR flag and only error if a
     * -1 was returned indicating some other error than an open error.
184 185 186 187 188 189 190 191
     *
     * NB: A small window exists in some cases where the just created
     * partition disappears, but then reappears. Since we were given
     * vol->target.path from parthelper, let's just be sure that any
     * kernel magic that occurs as a result of parthelper doesn't cause
     * us to fail with some sort of ENOENT failure since that would be
     * quite "unexpected". So rather than just fail, let's use the
     * virWaitForDevices to ensure everything has settled properly.
192
     */
193
    virWaitForDevices();
194
    if (vol->source.partType == VIR_STORAGE_VOL_DISK_TYPE_EXTENDED) {
195
        if (virStorageBackendUpdateVolInfo(vol, false,
196
                                           VIR_STORAGE_VOL_OPEN_DEFAULT |
197 198
                                           VIR_STORAGE_VOL_OPEN_NOERROR,
                                           0) == -1)
199
            goto error;
200 201
        vol->target.allocation = 0;
        vol->target.capacity =
202 203
            (vol->source.extents[0].end - vol->source.extents[0].start);
    } else {
204
        if (virStorageBackendUpdateVolInfo(vol, false,
205
                                           VIR_STORAGE_VOL_OPEN_DEFAULT, 0) < 0)
206
            goto error;
207
    }
208

209 210 211 212 213 214
    /* Now that we've updated @vol enough, let's add it to the pool
     * if it's not already there so that the subsequent pool search
     * pool def adjustments will work properly */
    if (addVol && virStoragePoolObjAddVol(pool, vol) < 0)
        goto error;

215 216
    /* Find the extended partition and increase the allocation value */
    if (vol->source.partType == VIR_STORAGE_VOL_DISK_TYPE_LOGICAL) {
217
        virStorageVolDefPtr voldef;
218

219 220 221 222 223
        voldef = virStoragePoolObjSearchVolume(pool,
                                               virStorageVolPartFindExtended,
                                               NULL);
        if (voldef)
            voldef->target.allocation += vol->target.allocation;
224 225
    }

226
    if (STRNEQ(groups[2], "metadata"))
227 228 229
        def->allocation += vol->target.allocation;
    if (vol->source.extents[0].end > def->capacity)
        def->capacity = vol->source.extents[0].end;
230 231

    return 0;
232 233 234 235 236

 error:
    if (addVol)
        virStorageVolDefFree(vol);
    return -1;
237 238 239
}

static int
240
virStorageBackendDiskMakeFreeExtent(virStoragePoolObjPtr pool,
241 242
                                    char **const groups)
{
243 244
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
    virStoragePoolSourceDevicePtr dev = &def->source.devices[0];
245

246 247
    if (VIR_REALLOC_N(dev->freeExtents,
                      dev->nfreeExtent + 1) < 0)
248 249 250
        return -1;

    memset(dev->freeExtents +
251 252
           dev->nfreeExtent, 0,
           sizeof(dev->freeExtents[0]));
253

254
    /* set type of free area */
E
Eric Blake 已提交
255
    if (STREQ(groups[1], "logical")) {
256 257 258 259 260 261
        dev->freeExtents[dev->nfreeExtent].type = VIR_STORAGE_FREE_LOGICAL;
    } else {
        dev->freeExtents[dev->nfreeExtent].type = VIR_STORAGE_FREE_NORMAL;
    }


262 263 264 265 266 267 268 269
    if (virStrToLong_ull(groups[3], NULL, 10,
                         &dev->freeExtents[dev->nfreeExtent].start) < 0)
        return -1; /* Don't bother to re-alloc freeExtents - it'll be free'd shortly */

    if (virStrToLong_ull(groups[4], NULL, 10,
                         &dev->freeExtents[dev->nfreeExtent].end) < 0)
        return -1; /* Don't bother to re-alloc freeExtents - it'll be free'd shortly */

270
    /* first block reported as free, even if it is not */
271
    if (dev->freeExtents[dev->nfreeExtent].start == 0)
272 273
        dev->freeExtents[dev->nfreeExtent].start = SECTOR_SIZE;

274 275 276 277
    def->available += (dev->freeExtents[dev->nfreeExtent].end -
                       dev->freeExtents[dev->nfreeExtent].start);
    if (dev->freeExtents[dev->nfreeExtent].end > def->capacity)
        def->capacity = dev->freeExtents[dev->nfreeExtent].end;
278 279 280 281 282 283 284

    dev->nfreeExtent++;

    return 0;
}


285 286 287 288 289
struct virStorageBackendDiskPoolVolData {
    virStoragePoolObjPtr pool;
    virStorageVolDefPtr vol;
};

290
static int
291
virStorageBackendDiskMakeVol(size_t ntok ATTRIBUTE_UNUSED,
292
                             char **const groups,
293
                             void *opaque)
294
{
295 296
    struct virStorageBackendDiskPoolVolData *data = opaque;
    virStoragePoolObjPtr pool = data->pool;
297 298 299 300 301 302 303 304 305 306 307 308
    /*
     * Ignore normal+metadata, and logical+metadata partitions
     * since they're basically internal book-keeping regions
     * we have no control over. Do keep extended+metadata though
     * because that's the MS-DOS extended partition region we
     * need to be able to view/create/delete
     */
    if ((STREQ(groups[1], "normal") ||
         STREQ(groups[1], "logical")) &&
        STREQ(groups[2], "metadata"))
        return 0;

R
Richard W.M. Jones 已提交
309
    /* Remaining data / metadata parts get turn into volumes... */
310 311
    if (STREQ(groups[2], "metadata") ||
        STREQ(groups[2], "data")) {
312
        virStorageVolDefPtr vol = data->vol;
313 314 315 316 317 318 319 320 321 322 323 324

        if (vol) {
            /* We're searching for a specific vol only */
            if (vol->key) {
                if (STRNEQ(vol->key, groups[0]))
                    return 0;
            } else if (virStorageVolDefFindByKey(pool, groups[0]) != NULL) {
                /* If no key, the volume must be newly created. If groups[0]
                 * isn't already a volume, assume it's the path we want */
                return 0;
            }
        }
325

326
        return virStorageBackendDiskMakeDataVol(pool, groups, vol);
327 328
    } else if (STREQ(groups[2], "free")) {
        /* ....or free space extents */
329
        return virStorageBackendDiskMakeFreeExtent(pool, groups);
330
    } else {
R
Richard W.M. Jones 已提交
331
        /* This code path should never happen unless someone changed
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
         * libvirt_parthelper forgot to change this code */
        return -1;
    }
}

/* To get a list of partitions we run an external helper
 * tool which then uses parted APIs. This is because
 * parted's API is not compatible with libvirt's license
 * but we really really want to use parted because the
 * other options all suck :-)
 *
 * All the other storage backends run an external tool for
 * listing volumes so this really isn't too much of a pain,
 * and we can even ensure the output is friendly.
 */
static int
348
virStorageBackendDiskReadPartitions(virStoragePoolObjPtr pool,
349 350 351 352 353 354 355 356 357
                                    virStorageVolDefPtr vol)
{
    /*
     *  # libvirt_parthelper DEVICE
     * /dev/sda1      normal       data        32256    106928128    106896384
     * /dev/sda2      normal       data    106928640 100027629568  99920701440
     * -              normal   metadata 100027630080 100030242304      2612736
     *
     */
358

359
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
360 361
    char *parthelper_path;
    virCommandPtr cmd;
362 363 364 365
    struct virStorageBackendDiskPoolVolData cbdata = {
        .pool = pool,
        .vol = vol,
    };
366
    int ret;
367

368
    if (!(parthelper_path = virFileFindResource("libvirt_parthelper",
369
                                                abs_topbuilddir "/src",
370 371 372 373
                                                LIBEXECDIR)))
        return -1;

    cmd = virCommandNewArgList(parthelper_path,
374
                               def->source.devices[0].path,
375 376
                               NULL);

377
    /* Check for the presence of the part_separator='yes'. Pass this
378
     * along to the libvirt_parthelper as option '-p'. This will cause
379 380 381
     * libvirt_parthelper to append the "p" partition separator to
     * the generated device name for a source device which ends with
     * a non-numeric value (e.g. mpatha would generate mpathap#).
382
     */
383
    if (def->source.devices[0].part_separator == VIR_TRISTATE_BOOL_YES)
384 385
        virCommandAddArg(cmd, "-p");

386 387 388 389
    /* If a volume is passed, virStorageBackendDiskMakeVol only updates the
     * pool allocation for that single volume.
     */
    if (!vol)
390 391
        def->allocation = 0;
    def->capacity = def->available = 0;
392

393 394 395 396
    ret = virCommandRunNul(cmd,
                           6,
                           virStorageBackendDiskMakeVol,
                           &cbdata);
397
    virCommandFree(cmd);
398
    VIR_FREE(parthelper_path);
399
    return ret;
400 401
}

402
static int
403
virStorageBackendDiskMakePoolGeometry(size_t ntok ATTRIBUTE_UNUSED,
404
                                      char **const groups,
405
                                      void *data)
406
{
407
    virStoragePoolObjPtr pool = data;
408 409
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
    virStoragePoolSourceDevicePtr device = &(def->source.devices[0]);
P
Peter Krempa 已提交
410 411 412 413 414 415 416
    if (virStrToLong_i(groups[0], NULL, 0, &device->geometry.cylinders) < 0 ||
        virStrToLong_i(groups[1], NULL, 0, &device->geometry.heads) < 0 ||
        virStrToLong_i(groups[2], NULL, 0, &device->geometry.sectors) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Failed to create disk pool geometry"));
        return -1;
    }
417

P
Peter Krempa 已提交
418
    return 0;
419 420 421
}

static int
422
virStorageBackendDiskReadGeometry(virStoragePoolObjPtr pool)
423
{
424
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
425 426 427 428 429
    char *parthelper_path;
    virCommandPtr cmd;
    int ret;

    if (!(parthelper_path = virFileFindResource("libvirt_parthelper",
430
                                                abs_topbuilddir "/src",
431 432 433 434
                                                LIBEXECDIR)))
        return -1;

    cmd = virCommandNewArgList(parthelper_path,
435 436 437
                               def->source.devices[0].path,
                               "-g",
                               NULL);
438

439 440 441 442
    ret = virCommandRunNul(cmd,
                           3,
                           virStorageBackendDiskMakePoolGeometry,
                           pool);
443
    virCommandFree(cmd);
444
    VIR_FREE(parthelper_path);
445
    return ret;
446
}
447 448

static int
449
virStorageBackendDiskRefreshPool(virStoragePoolObjPtr pool)
450
{
451 452 453 454
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);

    VIR_FREE(def->source.devices[0].freeExtents);
    def->source.devices[0].nfreeExtent = 0;
455

J
John Ferlan 已提交
456
    virWaitForDevices();
457

458
    if (!virFileExists(def->source.devices[0].path)) {
459 460
        virReportError(VIR_ERR_INVALID_ARG,
                       _("device path '%s' doesn't exist"),
461
                       def->source.devices[0].path);
462 463 464
        return -1;
    }

465
    if (virStorageBackendDiskReadGeometry(pool) != 0)
466 467
        return -1;

468
    return virStorageBackendDiskReadPartitions(pool, NULL);
469 470 471
}


472
static int
473
virStorageBackendDiskStartPool(virStoragePoolObjPtr pool)
474
{
475
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
476
    const char *format;
477
    const char *path = def->source.devices[0].path;
478

J
John Ferlan 已提交
479
    virWaitForDevices();
480

481
    if (!virFileExists(path)) {
482
        virReportError(VIR_ERR_INVALID_ARG,
483
                       _("device path '%s' doesn't exist"), path);
484 485 486
        return -1;
    }

487 488 489
    if (def->source.format == VIR_STORAGE_POOL_DISK_UNKNOWN)
        def->source.format = VIR_STORAGE_POOL_DISK_DOS;
    format = virStoragePoolFormatDiskTypeToString(def->source.format);
490
    if (!virStorageBackendDeviceIsEmpty(path, format, false))
491 492 493 494 495 496
        return -1;

    return 0;
}


497 498 499 500
/**
 * Write a new partition table header
 */
static int
501
virStorageBackendDiskBuildPool(virStoragePoolObjPtr pool,
E
Eric Blake 已提交
502
                               unsigned int flags)
503
{
504 505
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
    int format = def->source.format;
506
    const char *fmt;
507 508
    bool ok_to_mklabel = false;
    int ret = -1;
509
    virCommandPtr cmd = NULL;
510

511 512
    virCheckFlags(VIR_STORAGE_POOL_BUILD_OVERWRITE |
                  VIR_STORAGE_POOL_BUILD_NO_OVERWRITE, ret);
E
Eric Blake 已提交
513

514 515 516
    VIR_EXCLUSIVE_FLAGS_GOTO(VIR_STORAGE_POOL_BUILD_OVERWRITE,
                             VIR_STORAGE_POOL_BUILD_NO_OVERWRITE,
                             error);
517

518 519
    fmt = virStoragePoolFormatDiskTypeToString(format);
    if (flags & VIR_STORAGE_POOL_BUILD_OVERWRITE) {
520
        ok_to_mklabel = true;
521
    } else {
522
        if (virStorageBackendDeviceIsEmpty(def->source.devices[0].path,
523
                                           fmt, true))
524 525
            ok_to_mklabel = true;
    }
526

527
    if (ok_to_mklabel) {
528
        if (virStorageBackendZeroPartitionTable(def->source.devices[0].path,
529 530 531
                                                1024 * 1024) < 0)
            goto error;

532
        /* eg parted /dev/sda mklabel --script msdos */
533
        if (format == VIR_STORAGE_POOL_DISK_UNKNOWN)
534
            format = def->source.format = VIR_STORAGE_POOL_DISK_DOS;
535
        if (format == VIR_STORAGE_POOL_DISK_DOS)
536 537 538 539
            fmt = "msdos";
        else
            fmt = virStoragePoolFormatDiskTypeToString(format);

540
        cmd = virCommandNewArgList(PARTED,
541
                                   def->source.devices[0].path,
542 543
                                   "mklabel",
                                   "--script",
544
                                   fmt,
545
                                   NULL);
546
        ret = virCommandRun(cmd, NULL);
547
    }
548

549
 error:
550
    virCommandFree(cmd);
551
    return ret;
552 553
}

554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572

struct virStorageVolNumData {
    int count;
};

static int
virStorageVolNumOfPartTypes(virStorageVolDefPtr def,
                            const void *opaque)
{
    struct virStorageVolNumData *data = (struct virStorageVolNumData *)opaque;

    if (def->source.partType == VIR_STORAGE_VOL_DISK_TYPE_PRIMARY ||
        def->source.partType == VIR_STORAGE_VOL_DISK_TYPE_EXTENDED)
        data->count++;

    return 0;
}


573 574 575 576
/**
 * Decides what kind of partition type that should be created.
 * Important when the partition table is of msdos type
 */
577
static int
578 579
virStorageBackendDiskPartTypeToCreate(virStoragePoolObjPtr pool)
{
580
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
581 582
    struct virStorageVolNumData data = { .count = 0 };

583
    if (def->source.format == VIR_STORAGE_POOL_DISK_DOS) {
584
        /* count primary and extended partitions,
585
           can't be more than 3 to create a new primary partition */
586 587 588 589
        if (virStoragePoolObjForEachVolume(pool, virStorageVolNumOfPartTypes,
                                           &data) == 0) {
            if (data.count >= 4)
                return VIR_STORAGE_VOL_DISK_TYPE_LOGICAL;
590 591 592 593 594 595 596 597
        }
    }

    /* for all other cases, all partitions are primary */
    return VIR_STORAGE_VOL_DISK_TYPE_PRIMARY;
}

static int
598
virStorageBackendDiskPartFormat(virStoragePoolObjPtr pool,
599
                                virStorageVolDefPtr vol,
E
Eric Blake 已提交
600
                                char** partFormat)
601
{
602 603 604
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);

    if (def->source.format == VIR_STORAGE_POOL_DISK_DOS) {
E
Eric Blake 已提交
605
        const char *partedFormat;
606
        partedFormat = virStoragePartedFsTypeToString(vol->target.format);
E
Eric Blake 已提交
607
        if (partedFormat == NULL) {
608 609
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("Invalid partition type"));
E
Eric Blake 已提交
610
            return -1;
611 612
        }
        if (vol->target.format == VIR_STORAGE_VOL_DISK_EXTENDED) {
Y
Yuri Chornoivan 已提交
613
            /* make sure we don't have an extended partition already */
614 615 616
            if (virStoragePoolObjSearchVolume(pool,
                                              virStorageVolPartFindExtended,
                                              NULL)) {
617 618
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("extended partition already exists"));
E
Eric Blake 已提交
619
                    return -1;
620
            }
621
            if (VIR_STRDUP(*partFormat, partedFormat) < 0)
E
Eric Blake 已提交
622
                return -1;
623 624 625 626 627 628
        } else {
            /* create primary partition as long as it is possible
               and after that check if an extended partition exists
               to create logical partitions. */
            /* XXX Only support one extended partition */
            switch (virStorageBackendDiskPartTypeToCreate(pool)) {
E
Eric Blake 已提交
629
            case VIR_STORAGE_VOL_DISK_TYPE_PRIMARY:
630
                if (virAsprintf(partFormat, "primary %s", partedFormat) < 0)
E
Eric Blake 已提交
631
                    return -1;
E
Eric Blake 已提交
632 633
                break;
            case VIR_STORAGE_VOL_DISK_TYPE_LOGICAL:
Y
Yuri Chornoivan 已提交
634
                /* make sure we have an extended partition */
635 636 637 638 639 640 641 642 643 644
                if (virStoragePoolObjSearchVolume(pool,
                                                  virStorageVolPartFindExtended,
                                                  NULL)) {
                    if (virAsprintf(partFormat, "logical %s",
                                    partedFormat) < 0)
                        return -1;
                } else {
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("no extended partition found and no "
                                     "primary partition available"));
E
Eric Blake 已提交
645 646 647 648
                    return -1;
                }
                break;
            default:
649 650
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               "%s", _("unknown partition type"));
E
Eric Blake 已提交
651
                return -1;
652 653 654
            }
        }
    } else {
655
        if (VIR_STRDUP(*partFormat, "primary") < 0)
E
Eric Blake 已提交
656
            return -1;
657 658 659 660 661
    }
    return 0;
}

/**
J
Ján Tomko 已提交
662
 * Aligns a new partition to nearest cylinder boundary
E
Eric Blake 已提交
663
 * when having a msdos partition table type
J
Ján Tomko 已提交
664
 * to avoid any problem with already existing
665 666 667
 * partitions
 */
static int
668 669 670 671
virStorageBackendDiskPartBoundaries(virStoragePoolObjPtr pool,
                                    unsigned long long *start,
                                    unsigned long long *end,
                                    unsigned long long allocation)
672
{
673
    size_t i;
674
    int smallestExtent = -1;
675 676 677
    unsigned long long smallestSize = 0;
    unsigned long long extraBytes = 0;
    unsigned long long alignedAllocation = allocation;
678 679
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
    virStoragePoolSourceDevicePtr dev = &def->source.devices[0];
680
    unsigned long long cylinderSize = (unsigned long long)dev->geometry.heads *
681 682
                                      dev->geometry.sectors * SECTOR_SIZE;

683
    VIR_DEBUG("find free area: allocation %llu, cyl size %llu", allocation,
E
Eric Blake 已提交
684
          cylinderSize);
685 686 687
    int partType = virStorageBackendDiskPartTypeToCreate(pool);

    /* how many extra bytes we have since we allocate
J
Ján Tomko 已提交
688
       aligned to the cylinder boundary */
689 690
    extraBytes = cylinderSize - (allocation % cylinderSize);

691
    for (i = 0; i < dev->nfreeExtent; i++) {
692 693 694 695 696
         unsigned long long size =
             dev->freeExtents[i].end -
             dev->freeExtents[i].start;
         unsigned long long neededSize = allocation;

697
         if (def->source.format == VIR_STORAGE_POOL_DISK_DOS) {
J
Ján Tomko 已提交
698
             /* align to cylinder boundary */
699 700 701 702 703 704
             neededSize += extraBytes;
             if ((*start % cylinderSize) > extraBytes) {
                 /* add an extra cylinder if the offset can't fit within
                    the extra bytes we have */
                 neededSize += cylinderSize;
             }
705
             /* if we are creating a logical partition, we need one extra
706
                block between partitions (or actually move start one block) */
707
             if (partType == VIR_STORAGE_VOL_DISK_TYPE_LOGICAL)
708 709 710 711 712 713 714 715 716 717 718 719
                 size -= SECTOR_SIZE;
         }
         if (size > neededSize &&
             (smallestSize == 0 ||
             size < smallestSize)) {
             /* for logical partition, the free extent
                must be within a logical free area */
             if (partType == VIR_STORAGE_VOL_DISK_TYPE_LOGICAL &&
                 dev->freeExtents[i].type != VIR_STORAGE_FREE_LOGICAL) {
                 continue;
                 /* for primary partition, the free extent
                    must not be within a logical free area */
E
Eric Blake 已提交
720 721 722
             } else if (partType == VIR_STORAGE_VOL_DISK_TYPE_PRIMARY &&
                        dev->freeExtents[i].type != VIR_STORAGE_FREE_NORMAL) {
                 continue;
723 724 725 726 727 728 729 730
             }
             smallestSize = size;
             smallestExtent = i;
             alignedAllocation = neededSize;
         }
    }

    if (smallestExtent == -1) {
731 732
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no large enough free extent"));
733 734 735
        return -1;
    }

736
    VIR_DEBUG("aligned alloc %llu", alignedAllocation);
737 738 739 740 741 742 743 744
    *start = dev->freeExtents[smallestExtent].start;

    if (partType == VIR_STORAGE_VOL_DISK_TYPE_LOGICAL) {
        /* for logical partition, skip one block */
        *start += SECTOR_SIZE;
    }

    *end = *start + alignedAllocation;
745
    if (def->source.format == VIR_STORAGE_POOL_DISK_DOS) {
J
Ján Tomko 已提交
746
        /* adjust our allocation if start is not at a cylinder boundary */
747 748 749
        *end -= (*start % cylinderSize);
    }

750
    /* counting in bytes, we want the last byte of the current sector */
751
    *end -= 1;
752
    VIR_DEBUG("final aligned start %llu, end %llu", *start, *end);
753 754 755 756
    return 0;
}


757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780
/* virStorageBackendDiskDeleteVol
 * @pool: Pointer to the storage pool
 * @vol: Pointer to the volume definition
 * @flags: flags (unused for now)
 *
 * This API will remove the disk volume partition either from direct
 * API call or as an error path during creation when the partition
 * name provided during create doesn't match the name read from
 * virStorageBackendDiskReadPartitions.
 *
 * For a device mapper device, device respresentation is dependant upon
 * device mapper configuration, but the general rule of thumb is that at
 * creation if a device name ends with a number, then a partition separator
 * "p" is added to the created name; otherwise, if the device name doesn't
 * end with a number, then there is no partition separator. This name is
 * what ends up in the vol->target.path. This ends up being a link to a
 * /dev/mapper/dm-# device which cannot be used in the algorithm to determine
 * which partition to remove, but a properly handled target.path can be.
 *
 * For non device mapper devices, just need to resolve the link of the
 * vol->target.path in order to get the path.
 *
 * Returns 0 on success, -1 on failure with error message set.
 */
781
static int
782
virStorageBackendDiskDeleteVol(virStoragePoolObjPtr pool,
783 784 785 786 787
                               virStorageVolDefPtr vol,
                               unsigned int flags)
{
    char *part_num = NULL;
    char *devpath = NULL;
788
    char *dev_name;
789 790
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
    char *src_path = def->source.devices[0].path;
791
    char *srcname = last_component(src_path);
792 793 794 795 796 797
    virCommandPtr cmd = NULL;
    bool isDevMapperDevice;
    int rc = -1;

    virCheckFlags(0, -1);

798 799 800
    if (!vol->target.path) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("volume target path empty for source path '%s'"),
801
                      src_path);
802 803 804
        return -1;
    }

805 806 807 808 809 810 811 812 813 814 815 816 817 818 819
    /* NB: This is the corollary to the algorithm in libvirt_parthelper
     *     (parthelper.c) that is used to generate the target.path name
     *     for use by libvirt. Changes to either, need to be reflected
     *     in both places */
    isDevMapperDevice = virIsDevMapperDevice(vol->target.path);
    if (isDevMapperDevice) {
        dev_name = last_component(vol->target.path);
    } else {
        if (virFileResolveLink(vol->target.path, &devpath) < 0) {
            virReportSystemError(errno,
                                 _("Couldn't read volume target path '%s'"),
                                 vol->target.path);
            goto cleanup;
        }
        dev_name = last_component(devpath);
820 821 822 823
    }

    VIR_DEBUG("dev_name=%s, srcname=%s", dev_name, srcname);

824
    if (!STRPREFIX(dev_name, srcname)) {
825 826 827 828 829 830
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Volume path '%s' did not start with parent "
                         "pool source device name."), dev_name);
        goto cleanup;
    }

831
    part_num = dev_name + strlen(srcname);
832

833 834 835 836
    /* For device mapper and we have a partition character 'p' as the
     * current character, let's move beyond that before checking part_num */
    if (isDevMapperDevice && *part_num == 'p')
        part_num++;
837

838 839 840 841 842
    if (*part_num == 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("cannot parse partition number from target "
                         "'%s'"), dev_name);
        goto cleanup;
843 844
    }

845 846 847 848 849 850 851 852 853 854
    /* eg parted /dev/sda rm 2 or /dev/mapper/mpathc rm 2 */
    cmd = virCommandNewArgList(PARTED,
                               src_path,
                               "rm",
                               "--script",
                               part_num,
                               NULL);
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

855 856 857 858
    /* Refreshing the pool is the easiest option as LOGICAL and EXTENDED
     * partition allocation/capacity management is handled within
     * virStorageBackendDiskMakeDataVol and trying to redo that logic
     * here is pointless
859
     */
860
    virStoragePoolObjClearVols(pool);
861
    if (virStorageBackendDiskRefreshPool(pool) < 0)
862
        goto cleanup;
863

864 865 866 867 868 869 870 871
    rc = 0;
 cleanup:
    VIR_FREE(devpath);
    virCommandFree(cmd);
    return rc;
}


872
static int
873
virStorageBackendDiskCreateVol(virStoragePoolObjPtr pool,
874 875
                               virStorageVolDefPtr vol)
{
E
Eric Blake 已提交
876
    int res = -1;
877
    char *partFormat = NULL;
878
    unsigned long long startOffset = 0, endOffset = 0;
879
    virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool);
880
    virErrorPtr save_err;
881
    virCommandPtr cmd = virCommandNewArgList(PARTED,
882
                                             def->source.devices[0].path,
883 884 885
                                             "mkpart",
                                             "--script",
                                             NULL);
886

887 888 889 890
    if (vol->target.encryption &&
        vol->target.encryption->format != VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("storage pool only supports LUKS encrypted volumes"));
891
        goto cleanup;
892
    }
893

894
    if (virStorageBackendDiskPartFormat(pool, vol, &partFormat) != 0)
895
        goto cleanup;
896
    virCommandAddArg(cmd, partFormat);
897

898 899 900 901 902 903 904
    /* If we're going to encrypt using LUKS, then we could need up to
     * an extra 2MB for the LUKS header - so account for that now */
    if (vol->target.encryption)
        vol->target.capacity += 2 * 1024 * 1024;

    if (virStorageBackendDiskPartBoundaries(pool, &startOffset, &endOffset,
                                            vol->target.capacity) < 0)
E
Eric Blake 已提交
905
        goto cleanup;
906

907 908
    virCommandAddArgFormat(cmd, "%lluB", startOffset);
    virCommandAddArgFormat(cmd, "%lluB", endOffset);
909

910
    if (virCommandRun(cmd, NULL) < 0)
E
Eric Blake 已提交
911
        goto cleanup;
912

913
    /* wait for device node to show up */
J
John Ferlan 已提交
914
    virWaitForDevices();
915

916
    /* Blow away free extent info, as we're about to re-populate it */
917 918
    VIR_FREE(def->source.devices[0].freeExtents);
    def->source.devices[0].nfreeExtent = 0;
919

920 921 922 923
    /* Specifying a target path is meaningless */
    VIR_FREE(vol->target.path);

    /* Fetch actual extent info, generate key */
924 925 926 927 928 929 930 931 932
    if (virStorageBackendDiskReadPartitions(pool, vol) < 0)
        goto error;

    if (vol->target.encryption) {
        /* Adjust the sizes to account for the LUKS header */
        vol->target.capacity -= 2 * 1024 * 1024;
        vol->target.allocation -= 2 * 1024 * 1024;
        if (virStorageBackendCreateVolUsingQemuImg(pool, vol, NULL, 0) < 0)
            goto error;
933
    }
934

E
Eric Blake 已提交
935 936
    res = 0;

937
 cleanup:
E
Eric Blake 已提交
938
    VIR_FREE(partFormat);
939
    virCommandFree(cmd);
E
Eric Blake 已提交
940
    return res;
941 942 943 944 945 946 947 948 949 950

 error:
    /* Best effort to remove the partition. Ignore any errors
     * since we could be calling this with vol->target.path == NULL
     */
    save_err = virSaveLastError();
    ignore_value(virStorageBackendDiskDeleteVol(pool, vol, 0));
    virSetError(save_err);
    virFreeError(save_err);
    goto cleanup;
951 952
}

953

954
static int
955
virStorageBackendDiskBuildVolFrom(virStoragePoolObjPtr pool,
956 957 958 959 960 961
                                  virStorageVolDefPtr vol,
                                  virStorageVolDefPtr inputvol,
                                  unsigned int flags)
{
    virStorageBackendBuildVolFrom build_func;

962
    build_func = virStorageBackendGetBuildVolFromFunction(vol, inputvol);
963 964 965
    if (!build_func)
        return -1;

966
    return build_func(pool, vol, inputvol, flags);
967
}
968 969


970
static int
971
virStorageBackendDiskVolWipe(virStoragePoolObjPtr pool,
972 973 974 975 976
                             virStorageVolDefPtr vol,
                             unsigned int algorithm,
                             unsigned int flags)
{
    if (vol->source.partType != VIR_STORAGE_VOL_DISK_TYPE_EXTENDED)
977
        return virStorageBackendVolWipeLocal(pool, vol, algorithm, flags);
978 979 980 981 982 983 984 985 986

    /* Wiping an extended partition is not support */
    virReportError(VIR_ERR_NO_SUPPORT,
                   _("cannot wipe extended partition '%s'"),
                   vol->target.path);
    return -1;
}


987 988 989
virStorageBackend virStorageBackendDisk = {
    .type = VIR_STORAGE_POOL_DISK,

990
    .startPool = virStorageBackendDiskStartPool,
991 992 993 994 995
    .buildPool = virStorageBackendDiskBuildPool,
    .refreshPool = virStorageBackendDiskRefreshPool,

    .createVol = virStorageBackendDiskCreateVol,
    .deleteVol = virStorageBackendDiskDeleteVol,
996
    .buildVolFrom = virStorageBackendDiskBuildVolFrom,
997 998
    .uploadVol = virStorageBackendVolUploadLocal,
    .downloadVol = virStorageBackendVolDownloadLocal,
999
    .wipeVol = virStorageBackendDiskVolWipe,
1000
};
1001 1002 1003 1004 1005 1006 1007


int
virStorageBackendDiskRegister(void)
{
    return virStorageBackendRegister(&virStorageBackendDisk);
}