~ubuntu-branches/debian/sid/lvm2/sid

« back to all changes in this revision

Viewing changes to lib/metadata/thin_manip.c

  • Committer: Package Import Robot
  • Author(s): Bastian Blank
  • Date: 2014-08-19 15:37:06 UTC
  • mfrom: (1.1.18)
  • Revision ID: package-import@ubuntu.com-20140819153706-i1gaio8lg534dara
Tags: 2.02.109-1
New upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
#include "defaults.h"
21
21
#include "display.h"
22
22
 
23
 
int detach_pool_metadata_lv(struct lv_segment *pool_seg, struct logical_volume **metadata_lv)
24
 
{
25
 
        struct logical_volume *lv = pool_seg->metadata_lv;
26
 
 
27
 
        if (!lv || !lv_is_thin_pool_metadata(lv) ||
28
 
            !remove_seg_from_segs_using_this_lv(lv, pool_seg)) {
29
 
                log_error(INTERNAL_ERROR "LV %s is invalid thin pool.", pool_seg->lv->name);
30
 
                return 0;
31
 
        }
32
 
 
33
 
        lv_set_visible(lv);
34
 
        lv->status &= ~THIN_POOL_METADATA;
35
 
        *metadata_lv = lv;
36
 
        pool_seg->metadata_lv = NULL;
37
 
 
38
 
        return 1;
39
 
}
40
 
 
41
23
int attach_pool_message(struct lv_segment *pool_seg, dm_thin_message_t type,
42
24
                        struct logical_volume *lv, uint32_t delete_id,
43
25
                        int no_update)
231
213
 
232
214
int pool_below_threshold(const struct lv_segment *pool_seg)
233
215
{
234
 
        percent_t percent;
235
 
        int threshold = PERCENT_1 *
 
216
        dm_percent_t percent;
 
217
        int threshold = DM_PERCENT_1 *
236
218
                find_config_tree_int(pool_seg->lv->vg->cmd, activation_thin_pool_autoextend_threshold_CFG,
237
219
                                     lv_config_profile(pool_seg->lv));
238
220
 
366
348
        return 1;
367
349
}
368
350
 
369
 
int update_profilable_pool_params(struct cmd_context *cmd, struct profile *profile,
370
 
                                  int passed_args, int *chunk_size_calc_method,
371
 
                                  uint32_t *chunk_size, thin_discards_t *discards,
372
 
                                  int *zero)
 
351
int update_thin_pool_params(struct volume_group *vg,
 
352
                            unsigned attr, int passed_args, uint32_t data_extents,
 
353
                            uint64_t *pool_metadata_size,
 
354
                            int *chunk_size_calc_method, uint32_t *chunk_size,
 
355
                            thin_discards_t *discards, int *zero)
373
356
{
 
357
        struct cmd_context *cmd = vg->cmd;
 
358
        struct profile *profile = vg->profile;
 
359
        uint32_t extent_size = vg->extent_size;
 
360
        size_t estimate_chunk_size;
374
361
        const char *str;
375
362
 
376
363
        if (!(passed_args & PASS_ARG_CHUNK_SIZE)) {
377
364
                if (!(*chunk_size = find_config_tree_int(cmd, allocation_thin_pool_chunk_size_CFG, profile) * 2)) {
378
 
                        str = find_config_tree_str(cmd, allocation_thin_pool_chunk_size_policy_CFG, profile);
 
365
                        if (!(str = find_config_tree_str(cmd, allocation_thin_pool_chunk_size_policy_CFG, profile))) {
 
366
                                log_error(INTERNAL_ERROR "Could not find configuration.");
 
367
                                return 0;
 
368
                        }
379
369
                        if (!strcasecmp(str, "generic"))
380
370
                                *chunk_size_calc_method = THIN_CHUNK_SIZE_CALC_METHOD_GENERIC;
381
371
                        else if (!strcasecmp(str, "performance"))
384
374
                                log_error("Thin pool chunk size calculation policy \"%s\" is unrecognised.", str);
385
375
                                return 0;
386
376
                        }
387
 
                        *chunk_size = get_default_allocation_thin_pool_chunk_size_CFG(cmd, profile) * 2;
 
377
                        if (!(*chunk_size = get_default_allocation_thin_pool_chunk_size_CFG(cmd, profile)))
 
378
                                return_0;
388
379
                }
389
380
        }
390
381
 
397
388
        }
398
389
 
399
390
        if (!(passed_args & PASS_ARG_DISCARDS)) {
400
 
                str = find_config_tree_str(cmd, allocation_thin_pool_discards_CFG, profile);
 
391
                if (!(str = find_config_tree_str(cmd, allocation_thin_pool_discards_CFG, profile))) {
 
392
                        log_error(INTERNAL_ERROR "Could not find configuration.");
 
393
                        return 0;
 
394
                }
401
395
                if (!get_pool_discards(str, discards))
402
396
                        return_0;
403
397
        }
405
399
        if (!(passed_args & PASS_ARG_ZERO))
406
400
                *zero = find_config_tree_bool(cmd, allocation_thin_pool_zero_CFG, profile);
407
401
 
408
 
        return 1;
409
 
}
410
 
 
411
 
int update_thin_pool_params(struct volume_group *vg, unsigned attr,
412
 
                            int passed_args,
413
 
                            uint32_t data_extents, uint32_t extent_size,
414
 
                            int *chunk_size_calc_method, uint32_t *chunk_size,
415
 
                            thin_discards_t *discards,
416
 
                            uint64_t *pool_metadata_size, int *zero)
417
 
{
418
 
        size_t estimate_chunk_size;
419
 
        struct cmd_context *cmd = vg->cmd;
420
 
 
421
 
        if (!update_profilable_pool_params(cmd, vg->profile, passed_args,
422
 
                                           chunk_size_calc_method, chunk_size,
423
 
                                           discards, zero))
424
 
                return_0;
425
 
 
426
402
        if (!(attr & THIN_FEATURE_BLOCK_SIZE) &&
427
403
            (*chunk_size & (*chunk_size - 1))) {
428
404
                log_error("Chunk size must be a power of 2 for this thin target version.");
447
423
                        }
448
424
                        log_verbose("Setting chunk size to %s.",
449
425
                                    display_size(cmd, *chunk_size));
450
 
                } else if (*pool_metadata_size > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE)) {
 
426
                } else if (*pool_metadata_size > (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2)) {
451
427
                        /* Suggest bigger chunk size */
452
428
                        estimate_chunk_size = (uint64_t) data_extents * extent_size /
453
 
                                (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE *
454
 
                                 (SECTOR_SIZE / UINT64_C(64)));
 
429
                                (DEFAULT_THIN_POOL_MAX_METADATA_SIZE * 2 * (SECTOR_SIZE / UINT64_C(64)));
455
430
                        log_warn("WARNING: Chunk size is too small for pool, suggested minimum is %s.",
456
431
                                 display_size(cmd, UINT64_C(1) << (ffs(estimate_chunk_size) + 1)));
457
432
                }
460
435
                if (*pool_metadata_size % extent_size)
461
436
                        *pool_metadata_size += extent_size - *pool_metadata_size % extent_size;
462
437
        } else {
463
 
                estimate_chunk_size =  (uint64_t) data_extents * extent_size /
 
438
                estimate_chunk_size = (uint64_t) data_extents * extent_size /
464
439
                        (*pool_metadata_size * (SECTOR_SIZE / UINT64_C(64)));
 
440
                if (estimate_chunk_size < DM_THIN_MIN_DATA_BLOCK_SIZE)
 
441
                        estimate_chunk_size = DM_THIN_MIN_DATA_BLOCK_SIZE;
 
442
                else if (estimate_chunk_size > DM_THIN_MAX_DATA_BLOCK_SIZE)
 
443
                        estimate_chunk_size = DM_THIN_MAX_DATA_BLOCK_SIZE;
 
444
 
465
445
                /* Check to eventually use bigger chunk size */
466
446
                if (!(passed_args & PASS_ARG_CHUNK_SIZE)) {
467
447
                        *chunk_size = estimate_chunk_size;
468
 
 
469
 
                        if (*chunk_size < DM_THIN_MIN_DATA_BLOCK_SIZE)
470
 
                                *chunk_size = DM_THIN_MIN_DATA_BLOCK_SIZE;
471
 
                        else if (*chunk_size > DM_THIN_MAX_DATA_BLOCK_SIZE)
472
 
                                *chunk_size = DM_THIN_MAX_DATA_BLOCK_SIZE;
473
 
 
474
 
                        log_verbose("Setting chunk size %s.",
475
 
                                    display_size(cmd, *chunk_size));
 
448
                        log_verbose("Setting chunk size %s.", display_size(cmd, *chunk_size));
476
449
                } else if (*chunk_size < estimate_chunk_size) {
477
450
                        /* Suggest bigger chunk size */
478
451
                        log_warn("WARNING: Chunk size is smaller then suggested minimum size %s.",
480
453
                }
481
454
        }
482
455
 
483
 
        if ((uint64_t) *chunk_size > (uint64_t) data_extents * extent_size) {
484
 
                log_error("Chunk size is bigger then pool data size.");
485
 
                return 0;
486
 
        }
487
 
 
488
456
        if (*pool_metadata_size > (2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE)) {
 
457
                *pool_metadata_size = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE;
489
458
                if (passed_args & PASS_ARG_POOL_METADATA_SIZE)
490
459
                        log_warn("WARNING: Maximum supported pool metadata size is %s.",
491
 
                                 display_size(cmd, 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE));
492
 
                *pool_metadata_size = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE;
 
460
                                 display_size(cmd, *pool_metadata_size));
493
461
        } else if (*pool_metadata_size < (2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE)) {
 
462
                *pool_metadata_size = 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE;
494
463
                if (passed_args & PASS_ARG_POOL_METADATA_SIZE)
495
464
                        log_warn("WARNING: Minimum supported pool metadata size is %s.",
496
 
                                 display_size(cmd, 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE));
497
 
                *pool_metadata_size = 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE;
 
465
                                 display_size(cmd, *pool_metadata_size));
498
466
        }
499
467
 
500
 
        log_verbose("Setting pool metadata size to %s.",
501
 
                    display_size(cmd, *pool_metadata_size));
502
 
 
503
468
        return 1;
504
469
}
505
470
 
534
499
 
535
500
        return "unknown";
536
501
}
537
 
 
538
 
struct logical_volume *alloc_pool_metadata(struct logical_volume *pool_lv,
539
 
                                           const char *name, uint32_t read_ahead,
540
 
                                           uint32_t stripes, uint32_t stripe_size,
541
 
                                           uint64_t size, alloc_policy_t alloc,
542
 
                                           struct dm_list *pvh)
543
 
{
544
 
        struct logical_volume *metadata_lv;
545
 
        /* FIXME: Make lvm2api usable */
546
 
        struct lvcreate_params lvc = {
547
 
                .activate = CHANGE_ALY,
548
 
                .alloc = alloc,
549
 
                .lv_name = name,
550
 
                .major = -1,
551
 
                .minor = -1,
552
 
                .permission = LVM_READ | LVM_WRITE,
553
 
                .pvh = pvh,
554
 
                .read_ahead = read_ahead,
555
 
                .stripe_size = stripe_size,
556
 
                .stripes = stripes,
557
 
                .vg_name = pool_lv->vg->name,
558
 
                .zero = 1,
559
 
        };
560
 
 
561
 
        dm_list_init(&lvc.tags);
562
 
 
563
 
        if (!(lvc.extents = extents_from_size(pool_lv->vg->cmd, size,
564
 
                                              pool_lv->vg->extent_size)))
565
 
                return_0;
566
 
 
567
 
        if (!(lvc.segtype = get_segtype_from_string(pool_lv->vg->cmd, "striped")))
568
 
                return_0;
569
 
 
570
 
        /* FIXME: allocate properly space for metadata_lv */
571
 
 
572
 
        if (!(metadata_lv = lv_create_single(pool_lv->vg, &lvc)))
573
 
                return_0;
574
 
 
575
 
        return metadata_lv;
576
 
}
577
 
 
578
 
static struct logical_volume *_alloc_pool_metadata_spare(struct volume_group *vg,
579
 
                                                         uint32_t extents,
580
 
                                                         struct dm_list *pvh)
581
 
{
582
 
        struct logical_volume *lv;
583
 
 
584
 
        /* FIXME: Make lvm2api usable */
585
 
        struct lvcreate_params lp = {
586
 
                .activate = CHANGE_ALY,
587
 
                .alloc = ALLOC_INHERIT,
588
 
                .extents = extents,
589
 
                .major = -1,
590
 
                .minor = -1,
591
 
                .permission = LVM_READ | LVM_WRITE,
592
 
                .pvh = pvh ? : &vg->pvs,
593
 
                .read_ahead = DM_READ_AHEAD_AUTO,
594
 
                .stripes = 1,
595
 
                .vg_name = vg->name,
596
 
                .zero = 1,
597
 
                .temporary = 1,
598
 
        };
599
 
 
600
 
        dm_list_init(&lp.tags);
601
 
 
602
 
        if (!(lp.segtype = get_segtype_from_string(vg->cmd, "striped")))
603
 
                return_0;
604
 
 
605
 
        /* FIXME: Maybe using silent mode ? */
606
 
        if (!(lv = lv_create_single(vg, &lp)))
607
 
                return_0;
608
 
 
609
 
        /* Spare LV should not be active */
610
 
        if (!deactivate_lv_local(vg->cmd, lv)) {
611
 
                log_error("Unable to deactivate pool metadata spare LV. "
612
 
                          "Manual intervention required.");
613
 
                return 0;
614
 
        }
615
 
 
616
 
        if (!vg_set_pool_metadata_spare(lv))
617
 
                return_0;
618
 
 
619
 
        return lv;
620
 
}
621
 
 
622
 
/*
623
 
 * Create/resize pool metadata spare LV
624
 
 * Caller does vg_write(), vg_commit() with pool creation
625
 
 * extents is 0, max size is determined
626
 
 */
627
 
int handle_pool_metadata_spare(struct volume_group *vg, uint32_t extents,
628
 
                               struct dm_list *pvh, int poolmetadataspare)
629
 
{
630
 
        struct logical_volume *lv = vg->pool_metadata_spare_lv;
631
 
        uint32_t seg_mirrors;
632
 
        struct lv_segment *seg;
633
 
        const struct lv_list *lvl;
634
 
 
635
 
        if (!extents)
636
 
                /* Find maximal size of metadata LV */
637
 
                dm_list_iterate_items(lvl, &vg->lvs)
638
 
                        if (lv_is_thin_pool_metadata(lvl->lv) &&
639
 
                            (lvl->lv->le_count > extents))
640
 
                                extents = lvl->lv->le_count;
641
 
 
642
 
        if (!poolmetadataspare) {
643
 
                /* TODO: Not showing when lvm.conf would define 'n' ? */
644
 
                if (DEFAULT_POOL_METADATA_SPARE && extents)
645
 
                        /* Warn if there would be any user */
646
 
                        log_warn("WARNING: recovery of pools without pool "
647
 
                                 "metadata spare LV is not automated.");
648
 
                return 1;
649
 
        }
650
 
 
651
 
        if (!lv) {
652
 
                if (!_alloc_pool_metadata_spare(vg, extents, pvh))
653
 
                        return_0;
654
 
 
655
 
                return 1;
656
 
        }
657
 
 
658
 
        seg = last_seg(lv);
659
 
        seg_mirrors = lv_mirror_count(lv);
660
 
 
661
 
        /* Check spare LV is big enough and preserve segtype */
662
 
        if ((lv->le_count < extents) && seg &&
663
 
            !lv_extend(lv, seg->segtype,
664
 
                       seg->area_count / seg_mirrors,
665
 
                       seg->stripe_size,
666
 
                       seg_mirrors,
667
 
                       seg->region_size,
668
 
                       extents - lv->le_count, NULL,
669
 
                       pvh, lv->alloc, 0))
670
 
                return_0;
671
 
 
672
 
        return 1;
673
 
}
674
 
 
675
 
int vg_set_pool_metadata_spare(struct logical_volume *lv)
676
 
{
677
 
        char new_name[NAME_LEN];
678
 
        struct volume_group *vg = lv->vg;
679
 
 
680
 
        if (vg->pool_metadata_spare_lv) {
681
 
                if (vg->pool_metadata_spare_lv == lv)
682
 
                        return 1;
683
 
                if (!vg_remove_pool_metadata_spare(vg))
684
 
                        return_0;
685
 
        }
686
 
 
687
 
        if (dm_snprintf(new_name, sizeof(new_name), "%s_pmspare", lv->name) < 0) {
688
 
                log_error("Can't create pool metadata spare. Name of pool LV "
689
 
                          "%s is too long.", lv->name);
690
 
                return 0;
691
 
        }
692
 
 
693
 
        if (!lv_rename_update(vg->cmd, lv, new_name, 0))
694
 
                return_0;
695
 
 
696
 
        lv_set_hidden(lv);
697
 
        lv->status |= POOL_METADATA_SPARE;
698
 
        vg->pool_metadata_spare_lv = lv;
699
 
 
700
 
        return 1;
701
 
}
702
 
 
703
 
int vg_remove_pool_metadata_spare(struct volume_group *vg)
704
 
{
705
 
        char new_name[NAME_LEN];
706
 
        char *c;
707
 
 
708
 
        struct logical_volume *lv = vg->pool_metadata_spare_lv;
709
 
 
710
 
        if (!(lv->status & POOL_METADATA_SPARE)) {
711
 
                log_error(INTERNAL_ERROR "LV %s is not pool metadata spare.",
712
 
                          lv->name);
713
 
                return 0;
714
 
        }
715
 
 
716
 
        vg->pool_metadata_spare_lv = NULL;
717
 
        lv->status &= ~POOL_METADATA_SPARE;
718
 
        lv_set_visible(lv);
719
 
 
720
 
        /* Cut off suffix _pmspare */
721
 
        (void) dm_strncpy(new_name, lv->name, sizeof(new_name));
722
 
        if (!(c = strchr(new_name, '_'))) {
723
 
                log_error(INTERNAL_ERROR "LV %s has no suffix for pool metadata spare.",
724
 
                          new_name);
725
 
                return 0;
726
 
        }
727
 
        *c = 0;
728
 
 
729
 
        /* If the name is in use, generate new lvol%d */
730
 
        if (find_lv_in_vg(vg, new_name) &&
731
 
            !generate_lv_name(vg, "lvol%d", new_name, sizeof(new_name))) {
732
 
                log_error("Failed to generate unique name for "
733
 
                          "pool metadata spare logical volume.");
734
 
                return 0;
735
 
        }
736
 
 
737
 
        log_print_unless_silent("Renaming existing pool metadata spare "
738
 
                                "logical volume \"%s/%s\" to \"%s/%s\".",
739
 
                                vg->name, lv->name, vg->name, new_name);
740
 
 
741
 
        if (!lv_rename_update(vg->cmd, lv, new_name, 0))
742
 
                return_0;
743
 
 
744
 
        /* To display default warning */
745
 
        (void) handle_pool_metadata_spare(vg, 0, 0, 0);
746
 
 
747
 
        return 1;
748
 
}