LCOV - code coverage report
Current view: top level - misc/kabi/lvm2.git/lib/replicator - replicator.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 19 334 5.7 %
Date: 2010-04-13 Functions: 2 23 8.7 %
Branches: 4 306 1.3 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2009-2010 Red Hat, Inc. All rights reserved.
       3                 :            :  *
       4                 :            :  * This file is part of LVM2.
       5                 :            :  *
       6                 :            :  * This copyrighted material is made available to anyone wishing to use,
       7                 :            :  * modify, copy, or redistribute it subject to the terms and conditions
       8                 :            :  * of the GNU Lesser General Public License v.2.1.
       9                 :            :  *
      10                 :            :  * You should have received a copy of the GNU Lesser General Public License
      11                 :            :  * along with this program; if not, write to the Free Software Foundation,
      12                 :            :  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      13                 :            :  */
      14                 :            : 
      15                 :            : #include "lib.h"
      16                 :            : #include "toolcontext.h"
      17                 :            : #include "metadata.h"
      18                 :            : #include "segtype.h"
      19                 :            : #include "text_export.h"
      20                 :            : #include "text_import.h"
      21                 :            : #include "config.h"
      22                 :            : #include "activate.h"
      23                 :            : #include "str_list.h"
      24                 :            : #include "targets.h"  /* build_dlid */
      25                 :            : #ifdef DMEVENTD
      26                 :            : #  include "sharedlib.h"
      27                 :            : #  include "libdevmapper-event.h"
      28                 :            : #endif
      29                 :            : 
      30                 :            : /* Dm kernel module name for replicator */
      31                 :            : #define REPLICATOR_MODULE "replicator"
      32                 :            : #define REPLICATOR_DEV_MODULE "replicator-dev"
      33                 :            : 
      34                 :            : /*
      35                 :            :  * Macro used as return argument - returns 0.
      36                 :            :  * return is left to be written in the function for better readability.
      37                 :            :  */
      38                 :            : #define SEG_LOG_ERROR(t, p...) \
      39                 :            :         log_error(t " segment %s of logical volume %s.", ## p, \
      40                 :            :                   config_parent_name(sn), seg->lv->name), 0;
      41                 :            : 
      42                 :            : 
      43                 :            : /*
      44                 :            :  *  Replicator target
      45                 :            :  */
      46                 :          0 : static const char *_replicator_name(const struct lv_segment *seg)
      47                 :            : {
      48                 :          0 :         return seg->segtype->name;
      49                 :            : }
      50                 :            : 
      51                 :            : /* FIXME: missing implementation */
      52                 :          0 : static void _replicator_display(const struct lv_segment *seg)
      53                 :            : {
      54                 :            :         //const char *size;
      55                 :            :         //uint32_t s;
      56                 :            : 
      57                 :          0 :         log_print("  Replicator");
      58         [ #  # ]:          0 :         if (seg->rlog_lv)
      59                 :          0 :                 log_print("  Replicator volume\t%s", seg->rlog_lv->name);
      60                 :          0 : }
      61                 :            : 
      62                 :            : /* Wrapper for get_config_uint32() with default value */
      63                 :          0 : static uint32_t _get_config_uint32(const struct config_node *cn,
      64                 :            :                                    const char *path,
      65                 :            :                                    uint32_t def)
      66                 :            : {
      67                 :            :         uint32_t t;
      68                 :            : 
      69         [ #  # ]:          0 :         return get_config_uint32(cn, path, &t) ? t : def;
      70                 :            : }
      71                 :            : 
      72                 :            : /* Wrapper for get_config_uint64() with default value */
      73                 :          0 : static uint64_t _get_config_uint64(const struct config_node *cn,
      74                 :            :                                    const char *path,
      75                 :            :                                    uint64_t def)
      76                 :            : {
      77                 :            :         uint64_t t;
      78                 :            : 
      79         [ #  # ]:          0 :         return get_config_uint64(cn, path, &t) ? t : def;
      80                 :            : }
      81                 :            : 
      82                 :            : 
      83                 :            : /* Strings replicator_state_t enum */
      84                 :            : static const char _state_txt[NUM_REPLICATOR_STATE][8] = {
      85                 :            :         "passive",
      86                 :            :         "active"
      87                 :            : };
      88                 :            : 
      89                 :            : /* Parse state string */
      90                 :          0 : static replicator_state_t _get_state(const struct config_node *sn,
      91                 :            :                                      const char *path, replicator_state_t def)
      92                 :            : {
      93                 :            :         char *str;
      94                 :            :         unsigned i;
      95                 :            : 
      96         [ #  # ]:          0 :         if (get_config_str(sn, path, &str)) {
      97         [ #  # ]:          0 :                 for (i = 0; i < sizeof(_state_txt)/sizeof(_state_txt[0]); ++i)
      98         [ #  # ]:          0 :                         if (strcasecmp(str, _state_txt[i]) == 0)
      99                 :          0 :                                 return (replicator_state_t) i;
     100                 :            : 
     101                 :          0 :                 log_warn("%s: unknown value '%s', using default '%s' state",
     102                 :            :                          path, str, _state_txt[def]);
     103                 :            :         }
     104                 :            : 
     105                 :          0 :         return def;
     106                 :            : }
     107                 :            : 
     108                 :            : /* Strings for replicator_action_t enum */
     109                 :            : static const char _op_mode_txt[NUM_DM_REPLICATOR_MODES][8] = {
     110                 :            :         "sync",
     111                 :            :         "warn",
     112                 :            :         "stall",
     113                 :            :         "drop",
     114                 :            :         "fail"
     115                 :            : };
     116                 :            : 
     117                 :            : 
     118                 :            : /* Parse action string */
     119                 :          0 : static dm_replicator_mode_t _get_op_mode(const struct config_node *sn,
     120                 :            :                                          const char *path, dm_replicator_mode_t def)
     121                 :            : {
     122                 :            :         char *str;
     123                 :            :         unsigned i;
     124                 :            : 
     125         [ #  # ]:          0 :         if (get_config_str(sn, path, &str)) {
     126         [ #  # ]:          0 :                 for (i = 0; i < sizeof(_op_mode_txt)/sizeof(_op_mode_txt[0]); ++i)
     127         [ #  # ]:          0 :                         if (strcasecmp(str, _op_mode_txt[i]) == 0) {
     128                 :          0 :                                 log_very_verbose("Setting %s to %s",
     129                 :            :                                                  path, _op_mode_txt[i]);
     130                 :          0 :                                 return (dm_replicator_mode_t) i;
     131                 :            :                         }
     132                 :          0 :                 log_warn("%s: unknown value '%s', using default '%s' operation mode",
     133                 :            :                          path, str, _op_mode_txt[def]);
     134                 :            :         }
     135                 :            : 
     136                 :          0 :         return def;
     137                 :            : }
     138                 :            : 
     139                 :          0 : static struct replicator_site *_get_site(struct logical_volume *replicator,
     140                 :            :                                          const char *key)
     141                 :            : {
     142                 :          0 :         struct dm_pool *mem = replicator->vg->vgmem;
     143                 :            :         struct replicator_site *rsite;
     144                 :            : 
     145                 :          0 :         log_very_verbose("_get_site %s in LV %p", key, replicator->name);
     146                 :            : 
     147         [ #  # ]:          0 :         dm_list_iterate_items(rsite, &replicator->rsites)
     148         [ #  # ]:          0 :                 if (strcasecmp(rsite->name, key) == 0)
     149                 :          0 :                         return rsite;
     150                 :            : 
     151                 :          0 :         log_very_verbose("adding new site %s in seg", key);
     152                 :            : 
     153         [ #  # ]:          0 :         if (!(rsite = dm_pool_zalloc(mem, sizeof(*rsite))))
     154                 :          0 :                 return_NULL;
     155                 :            : 
     156         [ #  # ]:          0 :         if (!(rsite->name = dm_pool_strdup(mem, key)))
     157                 :          0 :                 return_NULL;
     158                 :            : 
     159                 :          0 :         rsite->replicator = replicator;
     160                 :          0 :         dm_list_init(&rsite->rdevices);
     161                 :          0 :         dm_list_add(&replicator->rsites, &rsite->list);
     162                 :            : 
     163                 :          0 :         return rsite;
     164                 :            : }
     165                 :            : 
     166                 :            : 
     167                 :            : /* Parse replicator site element */
     168                 :          0 : static int _add_site(struct lv_segment *seg,
     169                 :            :                      const char *key,
     170                 :            :                      const struct config_node *sn)
     171                 :            : {
     172                 :          0 :         struct dm_pool *mem = seg->lv->vg->vgmem;
     173                 :            :         const struct config_node *cn;
     174                 :            :         struct replicator_site *rsite;
     175                 :            : 
     176         [ #  # ]:          0 :         if (!(rsite = _get_site(seg->lv, key)))
     177                 :          0 :                 return_0;
     178                 :            : 
     179         [ #  # ]:          0 :         if (!find_config_node(sn, "site_index"))
     180                 :          0 :                 return SEG_LOG_ERROR("Mandatory site_index is missing for");
     181                 :            : 
     182                 :          0 :         rsite->state = _get_state(sn, "state", REPLICATOR_STATE_PASSIVE);
     183                 :          0 :         rsite->site_index = _get_config_uint32(sn, "site_index", 0);
     184         [ #  # ]:          0 :         if (rsite->site_index > seg->rsite_index_highest)
     185                 :          0 :                 return SEG_LOG_ERROR("site_index=%d > highest_site_index=%d for",
     186                 :            :                                      rsite->site_index, seg->rsite_index_highest);
     187                 :            : 
     188                 :          0 :         rsite->fall_behind_data = _get_config_uint64(sn, "fall_behind_data", 0);
     189                 :          0 :         rsite->fall_behind_ios = _get_config_uint32(sn, "fall_behind_ios", 0);
     190                 :          0 :         rsite->fall_behind_timeout = _get_config_uint32(sn, "fall_behind_timeout", 0);
     191                 :          0 :         rsite->op_mode = DM_REPLICATOR_SYNC;
     192                 :            : 
     193   [ #  #  #  # ]:          0 :         if (rsite->fall_behind_data ||
                 [ #  # ]
     194                 :          0 :             rsite->fall_behind_ios ||
     195                 :          0 :             rsite->fall_behind_timeout) {
     196 [ #  # ][ #  # ]:          0 :                 if (rsite->fall_behind_data && rsite->fall_behind_ios)
     197                 :          0 :                         return SEG_LOG_ERROR("Defined both fall_behind_data "
     198                 :            :                                              "and fall_behind_ios in");
     199                 :            : 
     200 [ #  # ][ #  # ]:          0 :                 if (rsite->fall_behind_data && rsite->fall_behind_timeout)
     201                 :          0 :                         return SEG_LOG_ERROR("Defined both fall_behind_data "
     202                 :            :                                              "and fall_behind_timeout in");
     203                 :            : 
     204 [ #  # ][ #  # ]:          0 :                 if (rsite->fall_behind_ios && rsite->fall_behind_timeout)
     205                 :          0 :                         return SEG_LOG_ERROR("Defined both fall_behind_ios "
     206                 :            :                                              "and fall_behind_timeout in");
     207                 :            : 
     208                 :          0 :                 rsite->op_mode = _get_op_mode(sn, "operation_mode",
     209                 :            :                                               rsite->op_mode);
     210                 :            :         }
     211                 :            : 
     212         [ #  # ]:          0 :         if ((cn = find_config_node(sn, "volume_group"))) {
     213 [ #  # ][ #  # ]:          0 :                 if (!cn->v || cn->v->type != CFG_STRING)
     214                 :          0 :                         return SEG_LOG_ERROR("volume_group must be a string in");
     215                 :            : 
     216         [ #  # ]:          0 :                 if (!(rsite->vg_name = dm_pool_strdup(mem, cn->v->v.str)))
     217                 :          0 :                         return_0;
     218                 :            : 
     219         [ #  # ]:          0 :         } else if (rsite->site_index != 0)
     220                 :          0 :                 return SEG_LOG_ERROR("volume_group is mandatory for remote site in");
     221                 :            : 
     222                 :          0 :         log_very_verbose("VG/Site: %s/%s state=%s site_index=%d op_mode=%s aios=%d adata=%"
     223                 :            :                          PRId64 " atimeout=%d", rsite->vg_name, key,
     224                 :            :                          _state_txt[rsite->state], rsite->site_index,
     225                 :            :                          _op_mode_txt[rsite->op_mode], rsite->fall_behind_ios,
     226                 :            :                          rsite->fall_behind_data, rsite->fall_behind_timeout);
     227                 :            : 
     228                 :          0 :         return 1;
     229                 :            : }
     230                 :            : 
     231                 :            : 
     232                 :            : /* Import replicator segment */
     233                 :          0 : static int _replicator_text_import(struct lv_segment *seg,
     234                 :            :                                    const struct config_node *sn,
     235                 :            :                                    struct dm_hash_table *pv_hash __attribute((unused)))
     236                 :            : {
     237                 :            :         const struct config_node *cn;
     238                 :            :         struct logical_volume *rlog_lv;
     239                 :            : 
     240                 :          0 :         log_very_verbose("%s segment '%s' k:%s a:%d", __func__, seg->lv->name, sn->sib->key, seg->area_count);
     241                 :            : 
     242         [ #  # ]:          0 :         if (!replicator_add_replicator_dev(seg->lv, NULL))
     243                 :          0 :                 return_0;
     244                 :            : 
     245 [ #  # ][ #  # ]:          0 :         if (!(cn = find_config_node(sn, "replicator_log")) ||
                 [ #  # ]
     246                 :          0 :             !cn->v || cn->v->type != CFG_STRING)
     247                 :          0 :                 return SEG_LOG_ERROR("Replicator log type must be a string in");
     248                 :            : 
     249         [ #  # ]:          0 :         if (!(rlog_lv = find_lv(seg->lv->vg, cn->v->v.str)))
     250                 :          0 :                 return SEG_LOG_ERROR("Unknown replicator log %s in",
     251                 :            :                                      cn->v->v.str);
     252                 :            : 
     253 [ #  # ][ #  # ]:          0 :         if (!(cn = find_config_node(sn, "replicator_log_type")) ||
                 [ #  # ]
     254                 :          0 :             !cn->v || cn->v->type != CFG_STRING)
     255                 :          0 :                 return SEG_LOG_ERROR("Replicator log's type must be a string in");
     256         [ #  # ]:          0 :         if (strcasecmp(cn->v->v.str, "ringbuffer"))
     257                 :          0 :                 return SEG_LOG_ERROR("Only ringbuffer replicator log type is supported in");
     258                 :            : 
     259         [ #  # ]:          0 :         if (!(seg->rlog_type = dm_pool_strdup(seg->lv->vg->vgmem, cn->v->v.str)))
     260                 :          0 :                 return_0;
     261                 :            : 
     262                 :            : 
     263                 :          0 :         log_very_verbose("replicator_log = %s", rlog_lv->name);
     264                 :          0 :         log_very_verbose("replicator_log_type = %s", seg->rlog_type);
     265                 :            : 
     266         [ #  # ]:          0 :         if (!replicator_add_rlog(seg, rlog_lv))
     267                 :          0 :                 return_0;
     268                 :            : 
     269                 :          0 :         seg->rdevice_index_highest = _get_config_uint64(sn, "highest_device_index", 0);
     270                 :          0 :         seg->rsite_index_highest = _get_config_uint32(sn, "highest_site_index", 0);
     271                 :            : 
     272                 :          0 :         seg->region_size = _get_config_uint32(sn, "sync_log_size", 0);
     273                 :            : 
     274         [ #  # ]:          0 :         for (; sn; sn = sn->sib)
     275         [ #  # ]:          0 :                 if (!sn->v) {
     276         [ #  # ]:          0 :                         for (cn = sn->sib; cn; cn = cn->sib)
     277 [ #  # ][ #  # ]:          0 :                                 if (!cn->v && (strcasecmp(cn->key ,sn->key) == 0))
     278                 :          0 :                                         return SEG_LOG_ERROR("Detected duplicate site "
     279                 :            :                                                              "name %s in", sn->key);
     280         [ #  # ]:          0 :                         if (!_add_site(seg, sn->key, sn->child))
     281                 :          0 :                                 return_0;
     282                 :            :                 }
     283                 :          0 :         return 1;
     284                 :            : }
     285                 :            : 
     286                 :            : /* Export replicator segment */
     287                 :          0 : static int _replicator_text_export(const struct lv_segment *seg,
     288                 :            :                                    struct formatter *f)
     289                 :            : {
     290                 :            :         struct replicator_site *rsite;
     291                 :            : 
     292         [ #  # ]:          0 :         if (!seg->rlog_lv)
     293                 :          0 :                 return_0;
     294                 :            : 
     295         [ #  # ]:          0 :         outf(f, "replicator_log = \"%s\"", seg->rlog_lv->name);
     296         [ #  # ]:          0 :         outf(f, "replicator_log_type = \"%s\"", seg->rlog_type);
     297         [ #  # ]:          0 :         outf(f, "highest_device_index = %" PRIu64, seg->rdevice_index_highest);
     298         [ #  # ]:          0 :         outf(f, "highest_site_index = %d", seg->rsite_index_highest);
     299                 :            : 
     300         [ #  # ]:          0 :         if (seg->region_size)
     301         [ #  # ]:          0 :                 outsize(f, (uint64_t)seg->region_size,
     302                 :            :                         "sync_log_size = %" PRIu32, seg->region_size);
     303                 :            : 
     304         [ #  # ]:          0 :         if (!dm_list_empty(&seg->lv->rsites))
     305         [ #  # ]:          0 :                 outnl(f);
     306                 :            : 
     307         [ #  # ]:          0 :         dm_list_iterate_items(rsite, &seg->lv->rsites) {
     308         [ #  # ]:          0 :                 outf(f, "%s {", rsite->name);
     309                 :          0 :                 out_inc_indent(f);
     310                 :            : 
     311         [ #  # ]:          0 :                 outf(f, "state = \"%s\"", _state_txt[rsite->state]);
     312         [ #  # ]:          0 :                 outf(f, "site_index = %d", rsite->site_index);
     313                 :            : 
     314                 :            :                 /* Only non-default parameters are written */
     315         [ #  # ]:          0 :                 if (rsite->op_mode != DM_REPLICATOR_SYNC)
     316         [ #  # ]:          0 :                         outf(f, "operation_mode = \"%s\"",
     317                 :            :                              _op_mode_txt[rsite->op_mode]);
     318         [ #  # ]:          0 :                 if (rsite->fall_behind_timeout)
     319         [ #  # ]:          0 :                         outfc(f, "# seconds", "fall_behind_timeout = %u",
     320                 :            :                              rsite->fall_behind_timeout);
     321         [ #  # ]:          0 :                 if (rsite->fall_behind_ios)
     322         [ #  # ]:          0 :                         outfc(f, "# io operations", "fall_behind_ios = %u",
     323                 :            :                              rsite->fall_behind_ios);
     324         [ #  # ]:          0 :                 if (rsite->fall_behind_data)
     325         [ #  # ]:          0 :                         outsize(f, rsite->fall_behind_data, "fall_behind_data = %" PRIu64,
     326                 :            :                                 rsite->fall_behind_data);
     327 [ #  # ][ #  # ]:          0 :                 if (rsite->state != REPLICATOR_STATE_ACTIVE && rsite->vg_name)
     328         [ #  # ]:          0 :                         outf(f, "volume_group = \"%s\"", rsite->vg_name);
     329                 :            : 
     330                 :          0 :                 out_dec_indent(f);
     331         [ #  # ]:          0 :                 outf(f, "}");
     332                 :            :         }
     333                 :            : 
     334                 :          0 :         return 1;
     335                 :            : }
     336                 :            : 
     337                 :            : #ifdef DEVMAPPER_SUPPORT
     338                 :          0 : static int _replicator_add_target_line(struct dev_manager *dm,
     339                 :            :                                        struct dm_pool *mem,
     340                 :            :                                        struct cmd_context *cmd,
     341                 :            :                                        void **target_state,
     342                 :            :                                        struct lv_segment *seg,
     343                 :            :                                        struct dm_tree_node *node,
     344                 :            :                                        uint64_t len,
     345                 :            :                                        uint32_t *pvmove_mirror_count)
     346                 :            : {
     347                 :            :         const char *rlog_dlid;
     348                 :            :         struct replicator_site *rsite;
     349                 :            : 
     350                 :          0 :         log_very_verbose("Activate replicator '%s' %s",
     351                 :            :                          seg->lv->name, seg->lv->lvid.s);
     352         [ #  # ]:          0 :         if (!seg->rlog_lv)
     353                 :          0 :                 return_0;
     354                 :            : 
     355         [ #  # ]:          0 :         if (!(rlog_dlid = build_dlid(dm, seg->rlog_lv->lvid.s, NULL)))
     356                 :          0 :                 return_0;
     357                 :            : 
     358         [ #  # ]:          0 :         dm_list_iterate_items(rsite, &seg->lv->rsites) {
     359         [ #  # ]:          0 :                 if (!dm_tree_node_add_replicator_target(node,
     360                 :          0 :                                                         seg->rlog_lv->size,
     361                 :            :                                                         rlog_dlid,
     362                 :            :                                                         seg->rlog_type,
     363                 :            :                                                         rsite->site_index,
     364                 :            :                                                         rsite->op_mode,
     365                 :            :                                                         rsite->fall_behind_timeout,
     366                 :            :                                                         rsite->fall_behind_data,
     367                 :            :                                                         rsite->fall_behind_ios)) {
     368         [ #  # ]:          0 :                         if (rsite->site_index == 0) {
     369                 :          0 :                                 log_error("Failed to add replicator log '%s' "
     370                 :            :                                           "to replicator '%s'.",
     371                 :            :                                           rlog_dlid, seg->lv->name);
     372                 :          0 :                                 return 0;
     373                 :            :                         }
     374                 :            :                         // FIXME:
     375                 :            :                 }
     376                 :            :         }
     377                 :            : 
     378                 :          0 :         return 1;
     379                 :            : }
     380                 :            : 
     381                 :            : /* FIXME: write something useful for replicator here */
     382                 :          0 : static int _replicator_target_percent(void **target_state,
     383                 :            :                                       percent_range_t *percent_range,
     384                 :            :                                       struct dm_pool *mem,
     385                 :            :                                       struct cmd_context *cmd,
     386                 :            :                                       struct lv_segment *seg,
     387                 :            :                                       char *params, uint64_t *total_numerator,
     388                 :            :                                       uint64_t *total_denominator)
     389                 :            : {
     390                 :          0 :         return 1;
     391                 :            : }
     392                 :            : 
     393                 :            : /* Check for module presence */
     394                 :          0 : static int _replicator_target_present(struct cmd_context *cmd,
     395                 :            :                                       const struct lv_segment *seg __attribute((unused)),
     396                 :            :                                       unsigned *attributes __attribute((unused)))
     397                 :            : {
     398                 :            :         static int _checked = 0;
     399                 :            :         static int _present = 0;
     400                 :            : 
     401         [ #  # ]:          0 :         if (!_checked) {
     402                 :          0 :                 _present = target_present(cmd, REPLICATOR_MODULE, 1);
     403                 :          0 :                 _checked = 1;
     404                 :            :         }
     405                 :            : 
     406                 :          0 :         return _present;
     407                 :            : }
     408                 :            : 
     409                 :            : #endif
     410                 :            : 
     411                 :          0 : static int _replicator_modules_needed(struct dm_pool *mem,
     412                 :            :                                       const struct lv_segment *seg __attribute((unused)),
     413                 :            :                                       struct dm_list *modules)
     414                 :            : {
     415         [ #  # ]:          0 :         if (!str_list_add(mem, modules, REPLICATOR_MODULE))
     416                 :          0 :                 return_0;
     417                 :            : 
     418         [ #  # ]:          0 :         if (!str_list_add(mem, modules, REPLICATOR_DEV_MODULE))
     419                 :          0 :                 return_0;
     420                 :            : 
     421                 :          0 :         return 1;
     422                 :            : }
     423                 :            : 
     424                 :          6 : static void _replicator_destroy(const struct segment_type *segtype)
     425                 :            : {
     426                 :          6 :         dm_free((void *)segtype);
     427                 :          6 : }
     428                 :            : 
     429                 :            : static struct segtype_handler _replicator_ops = {
     430                 :            :         .name = _replicator_name,
     431                 :            :         .display = _replicator_display,
     432                 :            :         .text_import = _replicator_text_import,
     433                 :            :         .text_export = _replicator_text_export,
     434                 :            : #ifdef DEVMAPPER_SUPPORT
     435                 :            :         .add_target_line = _replicator_add_target_line,
     436                 :            :         .target_percent = _replicator_target_percent,
     437                 :            :         .target_present = _replicator_target_present,
     438                 :            : #endif
     439                 :            :         .modules_needed = _replicator_modules_needed,
     440                 :            :         .destroy = _replicator_destroy,
     441                 :            : };
     442                 :            : 
     443                 :            : /*
     444                 :            :  *  Replicator-dev  target
     445                 :            :  */
     446                 :          0 : static void _replicator_dev_display(const struct lv_segment *seg)
     447                 :            : {
     448                 :            :         //const char *size;
     449                 :            :         //uint32_t s;
     450                 :            :         // FIXME: debug test code for now
     451                 :          0 :         log_print("  Replicator\t\t%u", seg->area_count);
     452                 :          0 :         log_print("  Mirror size\t\t%u", seg->area_len);
     453         [ #  # ]:          0 :         if (seg->log_lv)
     454                 :          0 :                 log_print("  Replicator log volume\t%s", seg->rlog_lv->name);
     455                 :            : 
     456                 :          0 : }
     457                 :            : 
     458                 :          0 : static int _add_device(struct lv_segment *seg,
     459                 :            :                        const char *site_name,
     460                 :            :                        const struct config_node *sn,
     461                 :            :                        uint64_t devidx)
     462                 :            : {
     463                 :          0 :         struct dm_pool *mem = seg->lv->vg->vgmem;
     464                 :          0 :         struct logical_volume *lv = NULL;
     465                 :          0 :         struct logical_volume *slog_lv = NULL;
     466                 :          0 :         struct replicator_site *rsite = _get_site(seg->replicator, site_name);
     467                 :            :         struct replicator_device *rdev;
     468                 :          0 :         const char *dev_str = NULL;
     469                 :          0 :         const char *slog_str = NULL;
     470                 :            :         const struct config_node *cn;
     471                 :            : 
     472         [ #  # ]:          0 :         dm_list_iterate_items(rdev, &rsite->rdevices)
     473         [ #  # ]:          0 :                 if (rdev->replicator_dev == seg)
     474                 :          0 :                         return SEG_LOG_ERROR("Duplicate site found in");
     475                 :            : 
     476         [ #  # ]:          0 :         if ((cn = find_config_node(sn, "sync_log"))) {
     477 [ #  # ][ #  # ]:          0 :                 if (!cn->v || !cn->v->v.str)
     478                 :          0 :                         return SEG_LOG_ERROR("Sync log must be a string in");
     479                 :          0 :                 slog_str = cn->v->v.str;
     480                 :            :         }
     481                 :            : 
     482 [ #  # ][ #  # ]:          0 :         if (!(cn = find_config_node(sn, "logical_volume")) ||
                 [ #  # ]
     483                 :          0 :             !cn->v || !cn->v->v.str)
     484                 :          0 :                 return SEG_LOG_ERROR("Logical volume must be a string in");
     485                 :            : 
     486                 :          0 :         dev_str = cn->v->v.str;
     487                 :            : 
     488         [ #  # ]:          0 :         if (!seg->lv->rdevice) {
     489         [ #  # ]:          0 :                 if (slog_str)
     490                 :          0 :                         return SEG_LOG_ERROR("Sync log %s defined for local "
     491                 :            :                                              "device in", slog_str);
     492                 :            : 
     493                 :            :                 /* Check for device in current VG */
     494         [ #  # ]:          0 :                 if (!(lv = find_lv(seg->lv->vg, dev_str)))
     495                 :          0 :                         return SEG_LOG_ERROR("Logical volume %s not found in",
     496                 :            :                                              dev_str);
     497                 :            :         } else {
     498         [ #  # ]:          0 :                 if (!slog_str)
     499                 :          0 :                         return SEG_LOG_ERROR("Sync log is missing for remote "
     500                 :            :                                              "device in");
     501                 :            :                 /* Check for slog device in current VG */
     502         [ #  # ]:          0 :                 if (!(slog_lv = find_lv(seg->lv->vg, slog_str)))
     503                 :          0 :                         return SEG_LOG_ERROR("Sync log %s not found in",
     504                 :            :                                              slog_str);
     505                 :            :         }
     506                 :            : 
     507         [ #  # ]:          0 :         if (!(rdev = dm_pool_zalloc(mem, sizeof(*rdev))))
     508                 :          0 :                 return_0;
     509                 :            : 
     510         [ #  # ]:          0 :         if (!(rdev->name = dm_pool_strdup(mem, dev_str)))
     511                 :          0 :                 return_0;
     512                 :            : 
     513                 :          0 :         log_very_verbose("Created  rdev=%p lv=%p str=%p",
     514                 :            :                          rdev, seg->lv, slog_str);
     515                 :          0 :         rdev->replicator_dev = seg;
     516                 :          0 :         rdev->rsite = rsite;
     517                 :          0 :         rdev->device_index = devidx;
     518                 :            : 
     519         [ #  # ]:          0 :         if (!seg->lv->rdevice) {
     520         [ #  # ]:          0 :                 if (!replicator_dev_add_rimage(rdev, lv))
     521                 :          0 :                         return SEG_LOG_ERROR("LV inconsistency found in");
     522                 :          0 :                 seg->lv->rdevice = rdev;
     523                 :            :         } else {
     524   [ #  #  #  # ]:          0 :                 if (!slog_str ||
     525                 :          0 :                     !(rdev->slog_name = dm_pool_strdup(mem, slog_str)))
     526                 :          0 :                         return_0;
     527                 :            : 
     528         [ #  # ]:          0 :                 if (!replicator_dev_add_slog(rdev, slog_lv))
     529                 :          0 :                         return SEG_LOG_ERROR("Sync log inconsistency found in");
     530                 :            : 
     531                 :            :                 // we keep only name reference for remote LV
     532                 :            :                 //log_verbose("FIND REMOTE VG %p   %s", rsite->vg, rsite->vg_name);
     533                 :            :                 //lv = find_lv(rsite->vg, dev_str);
     534                 :            :                 //log_verbose("FIND REMOTE %s   %p  %s", dev_str, lv, (lv) ? lv->name : "NOT FOUND");
     535                 :            :         }
     536                 :            : 
     537                 :          0 :         dm_list_add(&rsite->rdevices, &rdev->list);// linked site list
     538                 :            : 
     539                 :          0 :         return 1;
     540                 :            : }
     541                 :            : 
     542                 :            : /* Import replicator segment */
     543                 :          0 : static int _replicator_dev_text_import(struct lv_segment *seg,
     544                 :            :                                        const struct config_node *sn,
     545                 :            :                                        struct dm_hash_table *pv_hash __attribute((unused)))
     546                 :            : {
     547                 :            :         const struct config_node *cn;
     548                 :            :         struct logical_volume *replicator;
     549                 :            :         uint64_t devidx;
     550                 :            : 
     551                 :          0 :         log_very_verbose("%s segment '%s' k:%s a:%d", __func__, seg->lv->name, sn->sib->key, seg->area_count);
     552                 :            : 
     553         [ #  # ]:          0 :         if (!(cn = find_config_node(sn, "replicator")))
     554                 :          0 :                 return SEG_LOG_ERROR("Replicator is missing for");
     555                 :            : 
     556 [ #  # ][ #  # ]:          0 :         if (!cn->v || !cn->v->v.str)
     557                 :          0 :                 return SEG_LOG_ERROR("Replicator must be a string for");
     558                 :            : 
     559         [ #  # ]:          0 :         if (!(replicator = find_lv(seg->lv->vg, cn->v->v.str)))
     560                 :          0 :                 return SEG_LOG_ERROR("Unknown replicator %s for", cn->v->v.str);
     561                 :            : 
     562         [ #  # ]:          0 :         if (!replicator_add_replicator_dev(replicator, seg))
     563                 :          0 :                 return_0;
     564                 :            : 
     565                 :          0 :         log_very_verbose("replicator=%s", replicator->name);
     566                 :            : 
     567                 :            :         /* Mandatory */
     568   [ #  #  #  # ]:          0 :         if (!find_config_node(sn, "device_index") ||
     569                 :          0 :             !get_config_uint64(sn, "device_index", &devidx))
     570                 :          0 :                 return SEG_LOG_ERROR("Could not read 'device_index' for");
     571                 :            : 
     572                 :            :         /* Read devices from sites */
     573         [ #  # ]:          0 :         for (; sn; sn = sn->sib)
     574 [ #  # ][ #  # ]:          0 :                 if (!(sn->v) && !_add_device(seg, sn->key, sn->child, devidx))
     575                 :          0 :                         return_0;
     576                 :            : 
     577         [ #  # ]:          0 :         if (!seg->lv->rdevice)
     578                 :          0 :                 return SEG_LOG_ERROR("Replicator device without site in");
     579                 :            : 
     580                 :          0 :         seg->rlog_lv = NULL;
     581                 :          0 :         seg->lv->status |= REPLICATOR;
     582                 :            : 
     583                 :          0 :         return 1;
     584                 :            : }
     585                 :            : 
     586                 :            : /* Export replicator-dev segment */
     587                 :          0 : static int _replicator_dev_text_export(const struct lv_segment *seg,
     588                 :            :                                        struct formatter *f)
     589                 :            : {
     590                 :            :         struct replicator_site *rsite;
     591                 :            :         struct replicator_device *rdev;
     592                 :            : 
     593 [ #  # ][ #  # ]:          0 :         if (!seg->replicator || !seg->lv->rdevice)
     594                 :          0 :                 return_0;
     595                 :            : 
     596         [ #  # ]:          0 :         outf(f, "replicator = \"%s\"", seg->replicator->name);
     597         [ #  # ]:          0 :         outf(f, "device_index = %" PRId64, seg->lv->rdevice->device_index);
     598                 :            : 
     599         [ #  # ]:          0 :         outnl(f);
     600                 :            : 
     601         [ #  # ]:          0 :         dm_list_iterate_items(rsite, &seg->replicator->rsites) {
     602         [ #  # ]:          0 :                 dm_list_iterate_items(rdev, &rsite->rdevices) {
     603         [ #  # ]:          0 :                         if (rdev->replicator_dev != seg)
     604                 :          0 :                                 continue;
     605                 :            : 
     606         [ #  # ]:          0 :                         outf(f, "%s {", rdev->rsite->name);
     607                 :            : 
     608                 :          0 :                         out_inc_indent(f);
     609                 :            : 
     610 [ #  # ][ #  # ]:          0 :                         outf(f, "logical_volume = \"%s\"",
     611                 :            :                              rdev->name ? rdev->name : rdev->lv->name);
     612                 :            : 
     613         [ #  # ]:          0 :                         if (rdev->slog)
     614         [ #  # ]:          0 :                                 outf(f, "sync_log = \"%s\"", rdev->slog->name);
     615         [ #  # ]:          0 :                         else if (rdev->slog_name)
     616         [ #  # ]:          0 :                                 outf(f, "sync_log = \"%s\"", rdev->slog_name);
     617                 :            : 
     618                 :          0 :                         out_dec_indent(f);
     619                 :            : 
     620         [ #  # ]:          0 :                         outf(f, "}");
     621                 :            :                 }
     622                 :            :         }
     623                 :            : 
     624                 :          0 :         return 1;
     625                 :            : }
     626                 :            : 
     627                 :            : #ifdef DEVMAPPER_SUPPORT
     628                 :            : /*
     629                 :            :  * Add target for passive site matching the device index
     630                 :            :  */
     631                 :          0 : static int _replicator_dev_add_target_line(struct dev_manager *dm,
     632                 :            :                                            struct dm_pool *mem,
     633                 :            :                                            struct cmd_context *cmd,
     634                 :            :                                            void **target_state,
     635                 :            :                                            struct lv_segment *seg,
     636                 :            :                                            struct dm_tree_node *node,
     637                 :            :                                            uint64_t len,
     638                 :            :                                            uint32_t *pvmove_mirror_count)
     639                 :            : {
     640                 :            :         const char *replicator_dlid, *rdev_dlid, *slog_dlid;
     641                 :            :         struct replicator_device *rdev, *rdev_search;
     642                 :            :         struct replicator_site *rsite;
     643                 :            :         uint32_t slog_size;
     644                 :            :         uint32_t slog_flags;
     645                 :            : 
     646         [ #  # ]:          0 :         if (!lv_is_active_replicator_dev(seg->lv)) {
     647                 :            :                 /* Create passive linear mapping */
     648                 :          0 :                 log_very_verbose("Inactive replicator %s using %s.",
     649                 :            :                                  seg->lv->name, seg->lv->rdevice->lv->name);
     650         [ #  # ]:          0 :                 if (!dm_tree_node_add_linear_target(node, seg->lv->size))
     651                 :          0 :                         return_0;
     652         [ #  # ]:          0 :                 if (!(rdev_dlid = build_dlid(dm, seg->lv->rdevice->lv->lvid.s, NULL)))
     653                 :          0 :                         return_0;
     654                 :          0 :                 return dm_tree_node_add_target_area(node, NULL, rdev_dlid, 0);
     655         [ #  # ]:          0 :         } else if (seg->lv->rdevice->rsite->site_index) {
     656                 :          0 :                 log_error("Active site with site_index != 0 (%s, %d)",
     657                 :            :                           seg->lv->rdevice->rsite->name,
     658                 :            :                           seg->lv->rdevice->rsite->site_index);
     659                 :          0 :                 return 0; /* Replicator without any active site */
     660                 :            :         }
     661                 :            : 
     662                 :            :         /*
     663                 :            :          * At this point all devices that have some connection with replicator
     664                 :            :          * must be present in dm_tree
     665                 :            :          */
     666                 :          0 :         log_very_verbose("Creating replicator %s (size %" PRIu64 ")   %s %s",
     667                 :            :                          seg->lv->name, seg->lv->size,
     668                 :            :                          seg->lv->rdevice->lv->name,
     669                 :            :                          seg->lv->rdevice->lv->lvid.s );
     670                 :            : 
     671   [ #  #  #  # ]:          0 :         if (!seg_is_replicator_dev(seg) ||
     672                 :          0 :             !(replicator_dlid = build_dlid(dm, seg->replicator->lvid.s, NULL)))
     673                 :          0 :                 return_0;
     674                 :            : 
     675                 :            :         /* Select remote devices with the same device index */
     676         [ #  # ]:          0 :         dm_list_iterate_items(rsite, &seg->replicator->rsites) {
     677                 :          0 :                 log_verbose("Adding site: %s", rsite->name);
     678         [ #  # ]:          0 :                 if (rsite->site_index == 0) {
     679                 :            :                         /* Local slink0 device */
     680                 :          0 :                         rdev = seg->lv->rdevice;
     681                 :            :                 } else {
     682                 :            :                         //log_verbose("Adding remote sites from: %s  list size: %d", seg->replicator_lv->name, dm_list_size(&seg->replicator_lv->rsites));
     683                 :          0 :                         rdev = NULL;
     684         [ #  # ]:          0 :                         dm_list_iterate_items(rdev_search, &rsite->rdevices) {
     685         [ #  # ]:          0 :                                 if (rdev_search->replicator_dev == seg) {
     686         [ #  # ]:          0 :                                         log_verbose("Found %s  in %s", (rdev_search->lv) ?
     687                 :            :                                                     rdev_search->lv->name : rdev_search->name,
     688                 :            :                                                     rsite->name);
     689                 :          0 :                                         rdev = rdev_search;
     690                 :          0 :                                         break;
     691                 :            :                                 }
     692                 :            :                         }
     693                 :            : 
     694         [ #  # ]:          0 :                         if (!rdev) {
     695                 :          0 :                                 log_error(INTERNAL_ERROR "rdev list not found.");
     696                 :          0 :                                 return 0;
     697                 :            :                         }
     698                 :            :                 }
     699                 :            : 
     700   [ #  #  #  # ]:          0 :                 if (!rdev->lv ||
     701                 :          0 :                     !(rdev_dlid = build_dlid(dm, rdev->lv->lvid.s, NULL)))
     702                 :          0 :                         return_0;
     703                 :            : 
     704                 :          0 :                 slog_dlid = NULL;
     705                 :            : 
     706                 :            :                 /* Using either disk or core (in memory) log */
     707         [ #  # ]:          0 :                 if (rdev->slog) {
     708                 :          0 :                         slog_flags = DM_NOSYNC;
     709                 :          0 :                         slog_size = (uint32_t) rdev->slog->size;
     710                 :            :                         /* slog_size = 2048;  FIXME: HACK */
     711         [ #  # ]:          0 :                         if (!(slog_dlid = build_dlid(dm, rdev->slog->lvid.s, NULL)))
     712                 :          0 :                                 return_0;
     713 [ #  # ][ #  # ]:          0 :                 } else if (rdev->slog_name &&
     714                 :          0 :                            sscanf(rdev->slog_name, "%" PRIu32, &slog_size) == 1) {
     715                 :          0 :                         slog_flags = DM_CORELOG | DM_FORCESYNC;
     716         [ #  # ]:          0 :                         if (slog_size == 0) {
     717                 :          0 :                                 log_error("Failed to use empty corelog size "
     718                 :            :                                           "in replicator '%s'.",
     719                 :            :                                           rsite->replicator->name);
     720                 :          0 :                                 return 0;
     721                 :            :                         }
     722                 :            :                 } else  {
     723                 :          0 :                         slog_flags = DM_CORELOG | DM_FORCESYNC;
     724                 :          0 :                         slog_size = 0; /* NOLOG */
     725                 :            :                 }
     726                 :            : 
     727         [ #  # ]:          0 :                 if (!dm_tree_node_add_replicator_dev_target(node,
     728                 :          0 :                                                             seg->lv->size,
     729                 :            :                                                             replicator_dlid,
     730                 :          0 :                                                             seg->lv->rdevice->device_index,
     731                 :            :                                                             rdev_dlid,
     732                 :            :                                                             rsite->site_index,
     733                 :            :                                                             slog_dlid,
     734                 :            :                                                             slog_flags,
     735                 :            :                                                             slog_size)) {
     736                 :          0 :                         return_0;
     737                 :            :                         /*
     738                 :            :                          * CHECKME: handle 'state = dropped' in future
     739                 :            :                          */
     740                 :            :                 }
     741                 :            :         }
     742                 :            : 
     743                 :          0 :         return 1;
     744                 :            : }
     745                 :            : 
     746                 :            : /* FIXME: write something useful for replicator-dev here */
     747                 :          0 : static int _replicator_dev_target_percent(void **target_state,
     748                 :            :                                           percent_range_t *percent_range,
     749                 :            :                                           struct dm_pool *mem,
     750                 :            :                                           struct cmd_context *cmd,
     751                 :            :                                           struct lv_segment *seg,
     752                 :            :                                           char *params,
     753                 :            :                                           uint64_t *total_numerator,
     754                 :            :                                           uint64_t *total_denominator)
     755                 :            : {
     756                 :          0 :         return 1;
     757                 :            : }
     758                 :            : 
     759                 :            : /* Check for module presence */
     760                 :          0 : static int _replicator_dev_target_present(struct cmd_context *cmd,
     761                 :            :                                           const struct lv_segment *seg __attribute((unused)),
     762                 :            :                                           unsigned *attributes __attribute((unused)))
     763                 :            : {
     764                 :            :         static int _checked = 0;
     765                 :            :         static int _present = 0;
     766                 :            : 
     767         [ #  # ]:          0 :         if (!_checked) {
     768                 :          0 :                 _present = target_present(cmd, REPLICATOR_DEV_MODULE, 1);
     769                 :          0 :                 _checked = 1;
     770                 :            :         }
     771                 :            : 
     772                 :          0 :         return _present;
     773                 :            : }
     774                 :            : 
     775                 :            : #endif
     776                 :            : 
     777                 :            : static struct segtype_handler _replicator_dev_ops = {
     778                 :            :         .name = _replicator_name,
     779                 :            :         .display = _replicator_dev_display,
     780                 :            :         .text_import = _replicator_dev_text_import,
     781                 :            :         .text_export = _replicator_dev_text_export,
     782                 :            : #ifdef DEVMAPPER_SUPPORT
     783                 :            :         .add_target_line = _replicator_dev_add_target_line,
     784                 :            :         .target_percent = _replicator_dev_target_percent,
     785                 :            :         .target_present = _replicator_dev_target_present,
     786                 :            : #endif
     787                 :            :         .modules_needed = _replicator_modules_needed,
     788                 :            :         .destroy = _replicator_destroy,
     789                 :            : };
     790                 :            : 
     791                 :            : #ifdef REPLICATOR_INTERNAL
     792                 :          3 : int init_replicator_segtype(struct segtype_library *seglib)
     793                 :            : #else /* Shared */
     794                 :            : int init_multiple_segtype(struct segtype_library *seglib);
     795                 :            : int init_multiple_segtype(struct segtype_library *seglib)
     796                 :            : #endif
     797                 :            : {
     798                 :            :         struct segment_type *segtype;
     799                 :            : 
     800         [ -  + ]:          3 :         if (!(segtype = dm_malloc(sizeof(*segtype))))
     801                 :          0 :                 return_0;
     802                 :            : 
     803                 :          3 :         segtype->ops = &_replicator_ops;
     804                 :          3 :         segtype->name = REPLICATOR_MODULE;
     805                 :          3 :         segtype->private = NULL;
     806                 :          3 :         segtype->flags = SEG_REPLICATOR;
     807                 :            : 
     808         [ -  + ]:          3 :         if (!lvm_register_segtype(seglib, segtype))
     809                 :          0 :                 return_0;
     810                 :            : 
     811                 :          3 :         log_very_verbose("Initialised segtype: " REPLICATOR_MODULE);
     812                 :            : 
     813         [ -  + ]:          3 :         if (!(segtype = dm_malloc(sizeof(*segtype))))
     814                 :          0 :                 return_0;
     815                 :            : 
     816                 :          3 :         segtype->ops = &_replicator_dev_ops;
     817                 :          3 :         segtype->name = REPLICATOR_DEV_MODULE;
     818                 :          3 :         segtype->private = NULL;
     819                 :          3 :         segtype->flags = SEG_REPLICATOR_DEV;
     820                 :            : 
     821         [ -  + ]:          3 :         if (!lvm_register_segtype(seglib, segtype))
     822                 :          0 :                 return_0;
     823                 :            : 
     824                 :          3 :         log_very_verbose("Initialised segtype: " REPLICATOR_DEV_MODULE);
     825                 :            : 
     826                 :          3 :         return 1;
     827                 :            : }

Generated by: LCOV version 1.8