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

« back to all changes in this revision

Viewing changes to lib/activate/dev_manager.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:
41
41
        CLEAN
42
42
} action_t;
43
43
 
 
44
/* This list must match lib/misc/lvm-string.c:build_dm_uuid(). */
 
45
const char *uuid_suffix_list[] = { "pool", "cdata", "cmeta", "tdata", "tmeta", NULL};
 
46
 
44
47
struct dev_manager {
45
48
        struct dm_pool *mem;
46
49
 
482
485
                 struct dm_info *info, uint32_t *read_ahead)
483
486
{
484
487
        int r = 0;
 
488
        char old_style_dlid[sizeof(UUID_PREFIX) + 2 * ID_LEN];
 
489
        const char *suffix, *suffix_position;
 
490
        unsigned i = 0;
485
491
 
 
492
        /* Check for dlid */
486
493
        if ((r = _info_run(NULL, dlid, info, read_ahead, 0, with_open_count,
487
494
                           with_read_ahead, 0, 0)) && info->exists)
488
495
                return 1;
489
 
        else if ((r = _info_run(NULL, dlid + sizeof(UUID_PREFIX) - 1, info,
 
496
 
 
497
        /* Check for original version of dlid before the suffixes got added in 2.02.106 */
 
498
        if ((suffix_position = rindex(dlid, '-'))) {
 
499
                while ((suffix = uuid_suffix_list[i++])) {
 
500
                        if (strcmp(suffix_position + 1, suffix))
 
501
                                continue;
 
502
 
 
503
                        (void) strncpy(old_style_dlid, dlid, sizeof(old_style_dlid));
 
504
                        old_style_dlid[sizeof(old_style_dlid) - 1] = '\0';
 
505
                        if ((r = _info_run(NULL, old_style_dlid, info, read_ahead, 0, with_open_count,
 
506
                                           with_read_ahead, 0, 0)) && info->exists)
 
507
                                return 1;
 
508
                }
 
509
        }
 
510
 
 
511
        /* Check for dlid before UUID_PREFIX was added */
 
512
        if ((r = _info_run(NULL, dlid + sizeof(UUID_PREFIX) - 1, info,
490
513
                                read_ahead, 0, with_open_count,
491
514
                                with_read_ahead, 0, 0)) && info->exists)
492
515
                return 1;
719
742
        return 1;
720
743
}
721
744
 
722
 
static percent_range_t _combine_percent(percent_t a, percent_t b,
723
 
                                        uint32_t numerator, uint32_t denominator)
 
745
static dm_percent_range_t _combine_percent(dm_percent_t a, dm_percent_t b,
 
746
                                           uint32_t numerator, uint32_t denominator)
724
747
{
725
 
        if (a == PERCENT_MERGE_FAILED || b == PERCENT_MERGE_FAILED)
726
 
                return PERCENT_MERGE_FAILED;
727
 
 
728
 
        if (a == PERCENT_INVALID || b == PERCENT_INVALID)
729
 
                return PERCENT_INVALID;
730
 
 
731
 
        if (a == PERCENT_100 && b == PERCENT_100)
732
 
                return PERCENT_100;
733
 
 
734
 
        if (a == PERCENT_0 && b == PERCENT_0)
735
 
                return PERCENT_0;
736
 
 
737
 
        return (percent_range_t) make_percent(numerator, denominator);
 
748
        if (a == LVM_PERCENT_MERGE_FAILED || b == LVM_PERCENT_MERGE_FAILED)
 
749
                return LVM_PERCENT_MERGE_FAILED;
 
750
 
 
751
        if (a == DM_PERCENT_INVALID || b == DM_PERCENT_INVALID)
 
752
                return DM_PERCENT_INVALID;
 
753
 
 
754
        if (a == DM_PERCENT_100 && b == DM_PERCENT_100)
 
755
                return DM_PERCENT_100;
 
756
 
 
757
        if (a == DM_PERCENT_0 && b == DM_PERCENT_0)
 
758
                return DM_PERCENT_0;
 
759
 
 
760
        return (dm_percent_range_t) dm_make_percent(numerator, denominator);
738
761
}
739
762
 
740
763
static int _percent_run(struct dev_manager *dm, const char *name,
741
764
                        const char *dlid,
742
765
                        const char *target_type, int wait,
743
 
                        const struct logical_volume *lv, percent_t *overall_percent,
 
766
                        const struct logical_volume *lv, dm_percent_t *overall_percent,
744
767
                        uint32_t *event_nr, int fail_if_percent_unsupported)
745
768
{
746
769
        int r = 0;
754
777
        struct lv_segment *seg = NULL;
755
778
        struct segment_type *segtype;
756
779
        int first_time = 1;
757
 
        percent_t percent = PERCENT_INVALID;
 
780
        dm_percent_t percent = DM_PERCENT_INVALID;
758
781
 
759
782
        uint64_t total_numerator = 0, total_denominator = 0;
760
783
 
829
852
        if (first_time) {
830
853
                /* above ->target_percent() was not executed! */
831
854
                /* FIXME why return PERCENT_100 et. al. in this case? */
832
 
                *overall_percent = PERCENT_100;
 
855
                *overall_percent = DM_PERCENT_100;
833
856
                if (fail_if_percent_unsupported)
834
857
                        goto_out;
835
858
        }
836
859
 
837
 
        log_debug_activation("LV percent: %f", percent_to_float(*overall_percent));
 
860
        log_debug_activation("LV percent: %f", dm_percent_to_float(*overall_percent));
838
861
        r = 1;
839
862
 
840
863
      out:
844
867
 
845
868
static int _percent(struct dev_manager *dm, const char *name, const char *dlid,
846
869
                    const char *target_type, int wait,
847
 
                    const struct logical_volume *lv, percent_t *percent,
 
870
                    const struct logical_volume *lv, dm_percent_t *percent,
848
871
                    uint32_t *event_nr, int fail_if_percent_unsupported)
849
872
{
850
873
        if (dlid && *dlid) {
988
1011
 
989
1012
int dev_manager_snapshot_percent(struct dev_manager *dm,
990
1013
                                 const struct logical_volume *lv,
991
 
                                 percent_t *percent)
 
1014
                                 dm_percent_t *percent)
992
1015
{
993
1016
        const struct logical_volume *snap_lv;
994
1017
        char *name;
1041
1064
/* FIXME Cope with more than one target */
1042
1065
int dev_manager_mirror_percent(struct dev_manager *dm,
1043
1066
                               const struct logical_volume *lv, int wait,
1044
 
                               percent_t *percent, uint32_t *event_nr)
 
1067
                               dm_percent_t *percent, uint32_t *event_nr)
1045
1068
{
1046
1069
        char *name;
1047
1070
        const char *dlid;
1325
1348
 
1326
1349
int dev_manager_thin_pool_percent(struct dev_manager *dm,
1327
1350
                                  const struct logical_volume *lv,
1328
 
                                  int metadata, percent_t *percent)
 
1351
                                  int metadata, dm_percent_t *percent)
1329
1352
{
1330
1353
        char *name;
1331
1354
        const char *dlid;
1348
1371
 
1349
1372
int dev_manager_thin_percent(struct dev_manager *dm,
1350
1373
                             const struct logical_volume *lv,
1351
 
                             int mapped, percent_t *percent)
 
1374
                             int mapped, dm_percent_t *percent)
1352
1375
{
1353
1376
        char *name;
1354
1377
        const char *dlid;
1703
1726
        return 1;
1704
1727
}
1705
1728
 
1706
 
struct thin_cb_data {
 
1729
struct pool_cb_data {
 
1730
        struct dev_manager *dm;
1707
1731
        const struct logical_volume *pool_lv;
1708
 
        struct dev_manager *dm;
 
1732
 
 
1733
        int skip_zero;  /* to skip zeroed device header (check first 64B) */
 
1734
        int exec;       /* which binary to call */
 
1735
        int opts;
 
1736
        const char *defaults;
 
1737
        const char *global;
1709
1738
};
1710
1739
 
1711
 
static int _thin_pool_callback(struct dm_tree_node *node,
1712
 
                               dm_node_callback_t type, void *cb_data)
 
1740
static int _pool_callback(struct dm_tree_node *node,
 
1741
                          dm_node_callback_t type, void *cb_data)
1713
1742
{
1714
 
        int ret, status;
1715
 
        const struct thin_cb_data *data = cb_data;
1716
 
        const char *dmdir = dm_dir();
 
1743
        int ret, status, fd;
 
1744
        char *split;
1717
1745
        const struct dm_config_node *cn;
1718
1746
        const struct dm_config_value *cv;
1719
 
        const char *thin_check =
1720
 
                find_config_tree_str_allow_empty(data->pool_lv->vg->cmd, global_thin_check_executable_CFG, NULL);
1721
 
        const struct logical_volume *mlv = first_seg(data->pool_lv)->metadata_lv;
1722
 
        size_t len = strlen(dmdir) + 2 * (strlen(mlv->vg->name) + strlen(mlv->name)) + 3;
1723
 
        char meta_path[len];
 
1747
        const struct pool_cb_data *data = cb_data;
 
1748
        const struct logical_volume *pool_lv = data->pool_lv;
 
1749
        const struct logical_volume *mlv = first_seg(pool_lv)->metadata_lv;
 
1750
        long buf[64 / sizeof(long)]; /* buffer for short disk header (64B) */
1724
1751
        int args = 0;
1725
 
        const char *argv[19]; /* Max supported 15 args */
1726
 
        char *split, *dm_name;
 
1752
        const char *argv[19] = { /* Max supported 15 args */
 
1753
                find_config_tree_str_allow_empty(pool_lv->vg->cmd, data->exec, NULL) /* argv[0] */
 
1754
        };
1727
1755
 
1728
 
        if (!thin_check[0])
 
1756
        if (!*argv[0])
1729
1757
                return 1; /* Checking disabled */
1730
1758
 
1731
 
        if (!(dm_name = dm_build_dm_name(data->dm->mem, mlv->vg->name,
1732
 
                                         mlv->name, NULL)) ||
1733
 
            (dm_snprintf(meta_path, len, "%s/%s", dmdir, dm_name) < 0)) {
1734
 
                log_error("Failed to build thin metadata path.");
1735
 
                return 0;
1736
 
        }
1737
 
 
1738
 
        if ((cn = find_config_tree_node(mlv->vg->cmd, global_thin_check_options_CFG, NULL))) {
 
1759
        if ((cn = find_config_tree_node(mlv->vg->cmd, data->opts, NULL))) {
1739
1760
                for (cv = cn->v; cv && args < 16; cv = cv->next) {
1740
1761
                        if (cv->type != DM_CFG_STRING) {
1741
1762
                                log_error("Invalid string in config file: "
1742
 
                                          "global/thin_check_options");
 
1763
                                          "global/%s_check_options",
 
1764
                                          data->global);
1743
1765
                                return 0;
1744
1766
                        }
1745
1767
                        argv[++args] = cv->v.str;
1746
1768
                }
1747
1769
        } else {
1748
1770
                /* Use default options (no support for options with spaces) */
1749
 
                if (!(split = dm_pool_strdup(data->dm->mem, DEFAULT_THIN_CHECK_OPTIONS))) {
1750
 
                        log_error("Failed to duplicate thin check string.");
 
1771
                if (!(split = dm_pool_strdup(data->dm->mem, data->defaults))) {
 
1772
                        log_error("Failed to duplicate defaults.");
1751
1773
                        return 0;
1752
1774
                }
1753
1775
                args = dm_split_words(split, 16, 0, (char**) argv + 1);
1754
1776
        }
1755
1777
 
1756
1778
        if (args == 16) {
1757
 
                log_error("Too many options for thin check command.");
1758
 
                return 0;
1759
 
        }
1760
 
 
1761
 
        argv[0] = thin_check;
1762
 
        argv[++args] = meta_path;
1763
 
        argv[++args] = NULL;
1764
 
 
1765
 
        if (!(ret = exec_cmd(data->pool_lv->vg->cmd, (const char * const *)argv,
 
1779
                log_error("Too many options for %s command.", argv[0]);
 
1780
                return 0;
 
1781
        }
 
1782
 
 
1783
        if (!(argv[++args] = lv_dmpath_dup(data->dm->mem, mlv))) {
 
1784
                log_error("Failed to build pool metadata path.");
 
1785
                return 0;
 
1786
        }
 
1787
 
 
1788
        if (data->skip_zero) {
 
1789
                if ((fd = open(argv[args], O_RDONLY)) < 0) {
 
1790
                        log_sys_error("open", argv[args]);
 
1791
                        return 0;
 
1792
                }
 
1793
                /* let's assume there is no problem to read 64 bytes */
 
1794
                if (read(fd, buf, sizeof(buf)) < sizeof(buf)) {
 
1795
                        log_sys_error("read", argv[args]);
 
1796
                        return 0;
 
1797
                }
 
1798
                for (ret = 0; ret < DM_ARRAY_SIZE(buf); ++ret)
 
1799
                        if (buf[ret])
 
1800
                                break;
 
1801
 
 
1802
                if (close(fd))
 
1803
                        log_sys_error("close", argv[args]);
 
1804
 
 
1805
                if (ret == DM_ARRAY_SIZE(buf)) {
 
1806
                        log_debug("%s skipped, detect empty disk header on %s.",
 
1807
                                  argv[0], argv[args]);
 
1808
                        return 1;
 
1809
                }
 
1810
        }
 
1811
 
 
1812
        if (!(ret = exec_cmd(pool_lv->vg->cmd, (const char * const *)argv,
1766
1813
                             &status, 0))) {
1767
1814
                switch (type) {
1768
1815
                case DM_NODE_CALLBACK_PRELOADED:
1769
 
                        log_err_once("Check of thin pool %s/%s failed (status:%d). "
1770
 
                                     "Manual repair required (thin_dump --repair %s)!",
1771
 
                                     data->pool_lv->vg->name, data->pool_lv->name,
1772
 
                                     status, meta_path);
 
1816
                        log_err_once("Check of pool %s failed (status:%d). "
 
1817
                                     "Manual repair required!",
 
1818
                                     display_lvname(pool_lv), status);
1773
1819
                        break;
1774
1820
                default:
1775
 
                        log_warn("WARNING: Integrity check of metadata for thin pool "
1776
 
                                 "%s/%s failed.",
1777
 
                                 data->pool_lv->vg->name, data->pool_lv->name);
 
1821
                        log_warn("WARNING: Integrity check of metadata for pool "
 
1822
                                 "%s failed.", display_lvname(pool_lv));
1778
1823
                }
1779
1824
                /*
1780
1825
                 * FIXME: What should we do here??
1781
1826
                 *
1782
1827
                 * Maybe mark the node, so it's not activating
1783
 
                 * as thin_pool but as error/linear and let the
 
1828
                 * as pool but as error/linear and let the
1784
1829
                 * dm tree resolve the issue.
1785
1830
                 */
1786
1831
        }
1787
1832
 
1788
 
        dm_pool_free(data->dm->mem, dm_name);
1789
 
 
1790
1833
        return ret;
1791
1834
}
1792
1835
 
1793
 
static int _thin_pool_register_callback(struct dev_manager *dm,
1794
 
                                        struct dm_tree_node *node,
1795
 
                                        const struct logical_volume *lv)
 
1836
static int _pool_register_callback(struct dev_manager *dm,
 
1837
                                   struct dm_tree_node *node,
 
1838
                                   const struct logical_volume *lv)
1796
1839
{
1797
 
        struct thin_cb_data *data;
 
1840
        struct pool_cb_data *data;
1798
1841
 
1799
 
        /* Skip metadata testing for unused pool. */
1800
 
        if (!first_seg(lv)->transaction_id ||
1801
 
            ((first_seg(lv)->transaction_id == 1) &&
1802
 
             pool_has_message(first_seg(lv), NULL, 0)))
 
1842
        /* Skip metadata testing for unused thin pool. */
 
1843
        if (lv_is_thin_pool(lv) &&
 
1844
            (!first_seg(lv)->transaction_id ||
 
1845
             ((first_seg(lv)->transaction_id == 1) &&
 
1846
              pool_has_message(first_seg(lv), NULL, 0))))
1803
1847
                return 1;
1804
1848
 
1805
 
        if (!(data = dm_pool_alloc(dm->mem, sizeof(*data)))) {
 
1849
        if (!(data = dm_pool_zalloc(dm->mem, sizeof(*data)))) {
1806
1850
                log_error("Failed to allocated path for callback.");
1807
1851
                return 0;
1808
1852
        }
1809
1853
 
1810
1854
        data->dm = dm;
1811
 
        data->pool_lv = lv;
1812
 
 
1813
 
        dm_tree_node_set_callback(node, _thin_pool_callback, data);
 
1855
 
 
1856
        if (lv_is_thin_pool(lv)) {
 
1857
                data->pool_lv = lv;
 
1858
                data->skip_zero = 1;
 
1859
                data->exec = global_thin_check_executable_CFG;
 
1860
                data->opts = global_thin_check_options_CFG;
 
1861
                data->defaults = DEFAULT_THIN_CHECK_OPTIONS;
 
1862
                data->global = "thin";
 
1863
        } else if (lv_is_cache(lv)) { /* cache pool */
 
1864
                data->pool_lv = first_seg(lv)->pool_lv;
 
1865
                data->skip_zero = dm->activation;
 
1866
                data->exec = global_cache_check_executable_CFG;
 
1867
                data->opts = global_cache_check_options_CFG;
 
1868
                data->defaults = DEFAULT_CACHE_CHECK_OPTIONS;
 
1869
                data->global = "cache";
 
1870
        } else {
 
1871
                log_error(INTERNAL_ERROR "Registering unsupported pool callback.");
 
1872
                return 0;
 
1873
        }
 
1874
 
 
1875
        dm_tree_node_set_callback(node, _pool_callback, data);
1814
1876
 
1815
1877
        return 1;
1816
1878
}
1825
1887
        struct seg_list *sl;
1826
1888
        struct dm_list *snh;
1827
1889
        struct lv_segment *seg;
1828
 
        struct dm_tree_node *thin_node;
 
1890
        struct dm_tree_node *node;
1829
1891
        const char *uuid;
1830
1892
 
1831
1893
        if (lv_is_cache_pool(lv)) {
1857
1919
                /* FIXME Implement dm_tree_node_skip_childrens optimisation */
1858
1920
                if (!(uuid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
1859
1921
                        return_0;
1860
 
                if ((thin_node = dm_tree_find_node_by_uuid(dtree, uuid)))
1861
 
                        dm_tree_node_skip_childrens(thin_node, 1);
 
1922
                if ((node = dm_tree_find_node_by_uuid(dtree, uuid)))
 
1923
                        dm_tree_node_skip_childrens(node, 1);
1862
1924
#endif
1863
1925
        }
1864
1926
 
1887
1949
                        /* TODO: extend _cached_info() to return dnode */
1888
1950
                        if (!(uuid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
1889
1951
                                return_0;
1890
 
                        if ((thin_node = dm_tree_find_node_by_uuid(dtree, uuid)) &&
1891
 
                            !_thin_pool_register_callback(dm, thin_node, lv))
 
1952
                        if ((node = dm_tree_find_node_by_uuid(dtree, uuid)) &&
 
1953
                            !_pool_register_callback(dm, node, lv))
 
1954
                                return_0;
 
1955
                }
 
1956
        }
 
1957
 
 
1958
        if (!origin_only && lv_is_cache(lv)) {
 
1959
                if (!dm->activation) {
 
1960
                        /* Setup callback for non-activation partial tree */
 
1961
                        /* Activation gets own callback when needed */
 
1962
                        /* TODO: extend _cached_info() to return dnode */
 
1963
                        if (!(uuid = build_dm_uuid(dm->mem, lv, lv_layer(lv))))
 
1964
                                return_0;
 
1965
                        if ((node = dm_tree_find_node_by_uuid(dtree, uuid)) &&
 
1966
                            !_pool_register_callback(dm, node, lv))
1892
1967
                                return_0;
1893
1968
                }
1894
1969
        }
1959
2034
                return NULL;
1960
2035
        }
1961
2036
 
 
2037
        dm_tree_set_optional_uuid_suffixes(dtree, &uuid_suffix_list[0]);
 
2038
 
1962
2039
        if (!_add_lv_to_dtree(dm, dtree, lv, (lv_is_origin(lv) || lv_is_thin_volume(lv)) ? origin_only : 0))
1963
2040
                goto_bad;
1964
2041
 
2067
2144
                       stat(name, &info) < 0 || !S_ISBLK(info.st_mode))) ||
2068
2145
                    (seg_type(seg, s) == AREA_LV && !seg_lv(seg, s))) {
2069
2146
                        if (!seg->lv->vg->cmd->partial_activation) {
2070
 
                                log_error("Aborting.  LV %s is now incomplete "
2071
 
                                          "and --partial was not specified.", seg->lv->name);
2072
 
                                return 0;
 
2147
                                if (!seg->lv->vg->cmd->degraded_activation ||
 
2148
                                    !lv_is_raid_type(seg->lv)) {
 
2149
                                        log_error("Aborting.  LV %s is now incomplete "
 
2150
                                                  "and '--activationmode partial' was not specified.", seg->lv->name);
 
2151
                                        return 0;
 
2152
                                }
2073
2153
                        }
2074
2154
                        if (!_add_error_area(dm, node, seg, s))
2075
2155
                                return_0;
2436
2516
        return 1;
2437
2517
}
2438
2518
 
 
2519
#if 0
2439
2520
static int _set_udev_flags_for_children(struct dev_manager *dm,
2440
2521
                                        struct volume_group *vg,
2441
2522
                                        struct dm_tree_node *dnode)
2486
2567
 
2487
2568
        return 1;
2488
2569
}
 
2570
#endif
2489
2571
 
2490
2572
static int _add_new_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
2491
2573
                                struct logical_volume *lv, struct lv_activate_opts *laopts,
2628
2710
 
2629
2711
        /* Setup thin pool callback */
2630
2712
        if (lv_is_thin_pool(lv) && layer &&
2631
 
            !_thin_pool_register_callback(dm, dnode, lv))
 
2713
            !_pool_register_callback(dm, dnode, lv))
 
2714
                return_0;
 
2715
 
 
2716
        if (lv_is_cache(lv) &&
 
2717
            !_pool_register_callback(dm, dnode, lv))
2632
2718
                return_0;
2633
2719
 
2634
2720
        if (read_ahead == DM_READ_AHEAD_AUTO) {
2648
2734
                        if (!_add_new_lv_to_dtree(dm, dtree, sl->seg->lv, laopts, NULL))
2649
2735
                                return_0;
2650
2736
 
 
2737
#if 0
 
2738
        /* Should not be needed, will be removed */
2651
2739
        if (!_set_udev_flags_for_children(dm, lv->vg, dnode))
2652
2740
                return_0;
 
2741
#endif
2653
2742
 
2654
2743
        return 1;
2655
2744
}
2811
2900
        /* Only process nodes with uuid of "LVM-" plus VG id. */
2812
2901
        switch(action) {
2813
2902
        case CLEAN:
 
2903
                if (retry_deactivation())
 
2904
                        dm_tree_retry_remove(root);
2814
2905
                /* Deactivate any unused non-toplevel nodes */
2815
2906
                if (!_clean_tree(dm, root, laopts->origin_only ? dlid : NULL))
2816
2907
                        goto_out;
2935
3026
                return r;
2936
3027
        }
2937
3028
 
 
3029
        dm_tree_set_optional_uuid_suffixes(dtree, &uuid_suffix_list[0]);
 
3030
 
2938
3031
        if (!dm_tree_add_dev(dtree, (uint32_t) MAJOR(dev->dev), (uint32_t) MINOR(dev->dev))) {
2939
3032
                log_error("Failed to add device %s (%" PRIu32 ":%" PRIu32") to dtree",
2940
3033
                          dev_name(dev), (uint32_t) MAJOR(dev->dev), (uint32_t) MINOR(dev->dev));