LCOV - code coverage report
Current view: top level - misc/kabi/lvm2.git/lib/mirror - mirrored.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 13 187 7.0 %
Date: 2010-04-13 Functions: 2 13 15.4 %
Branches: 1 140 0.7 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
       3                 :            :  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
       4                 :            :  *
       5                 :            :  * This file is part of LVM2.
       6                 :            :  *
       7                 :            :  * This copyrighted material is made available to anyone wishing to use,
       8                 :            :  * modify, copy, or redistribute it subject to the terms and conditions
       9                 :            :  * of the GNU Lesser General Public License v.2.1.
      10                 :            :  *
      11                 :            :  * You should have received a copy of the GNU Lesser General Public License
      12                 :            :  * along with this program; if not, write to the Free Software Foundation,
      13                 :            :  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "lib.h"
      17                 :            : #include "toolcontext.h"
      18                 :            : #include "metadata.h"
      19                 :            : #include "segtype.h"
      20                 :            : #include "display.h"
      21                 :            : #include "text_export.h"
      22                 :            : #include "text_import.h"
      23                 :            : #include "config.h"
      24                 :            : #include "defaults.h"
      25                 :            : #include "lvm-string.h"
      26                 :            : #include "targets.h"
      27                 :            : #include "activate.h"
      28                 :            : #include "sharedlib.h"
      29                 :            : #include "str_list.h"
      30                 :            : 
      31                 :            : #ifdef DMEVENTD
      32                 :            : #  include "libdevmapper-event.h"
      33                 :            : #endif
      34                 :            : 
      35                 :            : static int _block_on_error_available = 0;
      36                 :            : static unsigned _mirror_attributes = 0;
      37                 :            : 
      38                 :            : enum {
      39                 :            :         MIRR_DISABLED,
      40                 :            :         MIRR_RUNNING,
      41                 :            :         MIRR_COMPLETED
      42                 :            : };
      43                 :            : 
      44                 :            : struct mirror_state {
      45                 :            :         uint32_t default_region_size;
      46                 :            : };
      47                 :            : 
      48                 :          0 : static const char *_mirrored_name(const struct lv_segment *seg)
      49                 :            : {
      50                 :          0 :         return seg->segtype->name;
      51                 :            : }
      52                 :            : 
      53                 :          0 : static void _mirrored_display(const struct lv_segment *seg)
      54                 :            : {
      55                 :            :         const char *size;
      56                 :            :         uint32_t s;
      57                 :            : 
      58                 :          0 :         log_print("  Mirrors\t\t%u", seg->area_count);
      59                 :          0 :         log_print("  Mirror size\t\t%u", seg->area_len);
      60         [ #  # ]:          0 :         if (seg->log_lv)
      61                 :          0 :                 log_print("  Mirror log volume\t%s", seg->log_lv->name);
      62                 :            : 
      63         [ #  # ]:          0 :         if (seg->region_size) {
      64                 :          0 :                 size = display_size(seg->lv->vg->cmd,
      65                 :            :                                     (uint64_t) seg->region_size);
      66                 :          0 :                 log_print("  Mirror region size\t%s", size);
      67                 :            :         }
      68                 :            : 
      69                 :          0 :         log_print("  Mirror original:");
      70                 :          0 :         display_stripe(seg, 0, "    ");
      71                 :          0 :         log_print("  Mirror destinations:");
      72         [ #  # ]:          0 :         for (s = 1; s < seg->area_count; s++)
      73                 :          0 :                 display_stripe(seg, s, "    ");
      74                 :          0 :         log_print(" ");
      75                 :          0 : }
      76                 :            : 
      77                 :          0 : static int _mirrored_text_import_area_count(struct config_node *sn, uint32_t *area_count)
      78                 :            : {
      79         [ #  # ]:          0 :         if (!get_config_uint32(sn, "mirror_count", area_count)) {
      80                 :          0 :                 log_error("Couldn't read 'mirror_count' for "
      81                 :            :                           "segment '%s'.", config_parent_name(sn));
      82                 :          0 :                 return 0;
      83                 :            :         }
      84                 :            : 
      85                 :          0 :         return 1;
      86                 :            : }
      87                 :            : 
      88                 :          0 : static int _mirrored_text_import(struct lv_segment *seg, const struct config_node *sn,
      89                 :            :                         struct dm_hash_table *pv_hash)
      90                 :            : {
      91                 :            :         const struct config_node *cn;
      92                 :          0 :         char *logname = NULL;
      93                 :            : 
      94         [ #  # ]:          0 :         if (find_config_node(sn, "extents_moved")) {
      95         [ #  # ]:          0 :                 if (get_config_uint32(sn, "extents_moved",
      96                 :            :                                       &seg->extents_copied))
      97                 :          0 :                         seg->status |= PVMOVE;
      98                 :            :                 else {
      99                 :          0 :                         log_error("Couldn't read 'extents_moved' for "
     100                 :            :                                   "segment %s of logical volume %s.",
     101                 :            :                                   config_parent_name(sn), seg->lv->name);
     102                 :          0 :                         return 0;
     103                 :            :                 }
     104                 :            :         }
     105                 :            : 
     106         [ #  # ]:          0 :         if (find_config_node(sn, "region_size")) {
     107         [ #  # ]:          0 :                 if (!get_config_uint32(sn, "region_size",
     108                 :            :                                       &seg->region_size)) {
     109                 :          0 :                         log_error("Couldn't read 'region_size' for "
     110                 :            :                                   "segment %s of logical volume %s.",
     111                 :            :                                   config_parent_name(sn), seg->lv->name);
     112                 :          0 :                         return 0;
     113                 :            :                 }
     114                 :            :         }
     115                 :            : 
     116         [ #  # ]:          0 :         if ((cn = find_config_node(sn, "mirror_log"))) {
     117 [ #  # ][ #  # ]:          0 :                 if (!cn->v || !cn->v->v.str) {
     118                 :          0 :                         log_error("Mirror log type must be a string.");
     119                 :          0 :                         return 0;
     120                 :            :                 }
     121                 :          0 :                 logname = cn->v->v.str;
     122         [ #  # ]:          0 :                 if (!(seg->log_lv = find_lv(seg->lv->vg, logname))) {
     123                 :          0 :                         log_error("Unrecognised mirror log in "
     124                 :            :                                   "segment %s of logical volume %s.",
     125                 :            :                                   config_parent_name(sn), seg->lv->name);
     126                 :          0 :                         return 0;
     127                 :            :                 }
     128                 :          0 :                 seg->log_lv->status |= MIRROR_LOG;
     129                 :            :         }
     130                 :            : 
     131 [ #  # ][ #  # ]:          0 :         if (logname && !seg->region_size) {
     132                 :          0 :                 log_error("Missing region size for mirror log for "
     133                 :            :                           "segment %s of logical volume %s.",
     134                 :            :                           config_parent_name(sn), seg->lv->name);
     135                 :          0 :                 return 0;
     136                 :            :         }
     137                 :            : 
     138         [ #  # ]:          0 :         if (!(cn = find_config_node(sn, "mirrors"))) {
     139                 :          0 :                 log_error("Couldn't find mirrors array for "
     140                 :            :                           "segment %s of logical volume %s.",
     141                 :            :                           config_parent_name(sn), seg->lv->name);
     142                 :          0 :                 return 0;
     143                 :            :         }
     144                 :            : 
     145                 :          0 :         return text_import_areas(seg, sn, cn, pv_hash, MIRROR_IMAGE);
     146                 :            : }
     147                 :            : 
     148                 :          0 : static int _mirrored_text_export(const struct lv_segment *seg, struct formatter *f)
     149                 :            : {
     150         [ #  # ]:          0 :         outf(f, "mirror_count = %u", seg->area_count);
     151         [ #  # ]:          0 :         if (seg->status & PVMOVE)
     152         [ #  # ]:          0 :                 outsize(f, (uint64_t) seg->extents_copied * seg->lv->vg->extent_size,
     153                 :            :                         "extents_moved = %" PRIu32, seg->extents_copied);
     154         [ #  # ]:          0 :         if (seg->log_lv)
     155         [ #  # ]:          0 :                 outf(f, "mirror_log = \"%s\"", seg->log_lv->name);
     156         [ #  # ]:          0 :         if (seg->region_size)
     157         [ #  # ]:          0 :                 outf(f, "region_size = %" PRIu32, seg->region_size);
     158                 :            : 
     159                 :          0 :         return out_areas(f, seg, "mirror");
     160                 :            : }
     161                 :            : 
     162                 :            : #ifdef DEVMAPPER_SUPPORT
     163                 :          0 : static struct mirror_state *_mirrored_init_target(struct dm_pool *mem,
     164                 :            :                                          struct cmd_context *cmd)
     165                 :            : {
     166                 :            :         struct mirror_state *mirr_state;
     167                 :            : 
     168         [ #  # ]:          0 :         if (!(mirr_state = dm_pool_alloc(mem, sizeof(*mirr_state)))) {
     169                 :          0 :                 log_error("struct mirr_state allocation failed");
     170                 :          0 :                 return NULL;
     171                 :            :         }
     172                 :            : 
     173                 :          0 :         mirr_state->default_region_size = 2 *
     174                 :            :             find_config_tree_int(cmd,
     175                 :            :                             "activation/mirror_region_size",
     176                 :            :                             DEFAULT_MIRROR_REGION_SIZE);
     177                 :            : 
     178                 :          0 :         return mirr_state;
     179                 :            : }
     180                 :            : 
     181                 :          0 : static int _mirrored_target_percent(void **target_state,
     182                 :            :                                     percent_range_t *percent_range,
     183                 :            :                                     struct dm_pool *mem,
     184                 :            :                                     struct cmd_context *cmd,
     185                 :            :                                     struct lv_segment *seg, char *params,
     186                 :            :                                     uint64_t *total_numerator,
     187                 :            :                                     uint64_t *total_denominator)
     188                 :            : {
     189                 :            :         struct mirror_state *mirr_state;
     190                 :            :         uint64_t numerator, denominator;
     191                 :            :         unsigned mirror_count, m;
     192                 :            :         int used;
     193                 :          0 :         char *pos = params;
     194                 :            : 
     195         [ #  # ]:          0 :         if (!*target_state)
     196                 :          0 :                 *target_state = _mirrored_init_target(mem, cmd);
     197                 :            : 
     198                 :          0 :         mirr_state = *target_state;
     199                 :            : 
     200                 :            :         /* Status line: <#mirrors> (maj:min)+ <synced>/<total_regions> */
     201                 :          0 :         log_debug("Mirror status: %s", params);
     202                 :            : 
     203         [ #  # ]:          0 :         if (sscanf(pos, "%u %n", &mirror_count, &used) != 1) {
     204                 :          0 :                 log_error("Failure parsing mirror status mirror count: %s",
     205                 :            :                           params);
     206                 :          0 :                 return 0;
     207                 :            :         }
     208                 :          0 :         pos += used;
     209                 :            : 
     210         [ #  # ]:          0 :         for (m = 0; m < mirror_count; m++) {
     211         [ #  # ]:          0 :                 if (sscanf(pos, "%*x:%*x %n", &used) != 0) {
     212                 :          0 :                         log_error("Failure parsing mirror status devices: %s",
     213                 :            :                                   params);
     214                 :          0 :                         return 0;
     215                 :            :                 }
     216                 :          0 :                 pos += used;
     217                 :            :         }
     218                 :            : 
     219         [ #  # ]:          0 :         if (sscanf(pos, "%" PRIu64 "/%" PRIu64 "%n", &numerator, &denominator,
     220                 :            :                    &used) != 2) {
     221                 :          0 :                 log_error("Failure parsing mirror status fraction: %s", params);
     222                 :          0 :                 return 0;
     223                 :            :         }
     224                 :          0 :         pos += used;
     225                 :            : 
     226                 :          0 :         *total_numerator += numerator;
     227                 :          0 :         *total_denominator += denominator;
     228                 :            : 
     229         [ #  # ]:          0 :         if (seg)
     230                 :          0 :                 seg->extents_copied = seg->area_len * numerator / denominator;
     231                 :            : 
     232         [ #  # ]:          0 :         if (numerator == denominator)
     233                 :          0 :                 *percent_range = PERCENT_100;
     234         [ #  # ]:          0 :         else if (numerator == 0)
     235                 :          0 :                 *percent_range = PERCENT_0;
     236                 :            :         else
     237                 :          0 :                 *percent_range = PERCENT_0_TO_100;
     238                 :            : 
     239                 :          0 :         return 1;
     240                 :            : }
     241                 :            : 
     242                 :          0 : static int _add_log(struct dev_manager *dm, struct lv_segment *seg,
     243                 :            :                     struct dm_tree_node *node, uint32_t area_count, uint32_t region_size)
     244                 :            : {
     245                 :          0 :         unsigned clustered = 0;
     246                 :          0 :         char *log_dlid = NULL;
     247                 :          0 :         uint32_t log_flags = 0;
     248                 :            : 
     249                 :            :         /*
     250                 :            :          * Use clustered mirror log for non-exclusive activation
     251                 :            :          * in clustered VG.
     252                 :            :          */
     253   [ #  #  #  # ]:          0 :         if ((!(seg->lv->status & ACTIVATE_EXCL) &&
     254                 :          0 :               (vg_is_clustered(seg->lv->vg))))
     255                 :          0 :                 clustered = 1;
     256                 :            : 
     257         [ #  # ]:          0 :         if (seg->log_lv) {
     258                 :            :                 /* If disk log, use its UUID */
     259         [ #  # ]:          0 :                 if (!(log_dlid = build_dlid(dm, seg->log_lv->lvid.s, NULL))) {
     260                 :          0 :                         log_error("Failed to build uuid for log LV %s.",
     261                 :            :                                   seg->log_lv->name);
     262                 :          0 :                         return 0;
     263                 :            :                 }
     264                 :            :         } else {
     265                 :            :                 /* If core log, use mirror's UUID and set DM_CORELOG flag */
     266         [ #  # ]:          0 :                 if (!(log_dlid = build_dlid(dm, seg->lv->lvid.s, NULL))) {
     267                 :          0 :                         log_error("Failed to build uuid for mirror LV %s.",
     268                 :            :                                   seg->lv->name);
     269                 :          0 :                         return 0;
     270                 :            :                 }
     271                 :          0 :                 log_flags |= DM_CORELOG;
     272                 :            :         }
     273                 :            : 
     274 [ #  # ][ #  # ]:          0 :         if (mirror_in_sync() && !(seg->status & PVMOVE))
     275                 :          0 :                 log_flags |= DM_NOSYNC;
     276                 :            : 
     277 [ #  # ][ #  # ]:          0 :         if (_block_on_error_available && !(seg->status & PVMOVE))
     278                 :          0 :                 log_flags |= DM_BLOCK_ON_ERROR;
     279                 :            : 
     280                 :          0 :         return dm_tree_node_add_mirror_target_log(node, region_size, clustered, log_dlid, area_count, log_flags);
     281                 :            : }
     282                 :            : 
     283                 :          0 : static int _mirrored_add_target_line(struct dev_manager *dm, struct dm_pool *mem,
     284                 :            :                                 struct cmd_context *cmd, void **target_state,
     285                 :            :                                 struct lv_segment *seg,
     286                 :            :                                 struct dm_tree_node *node, uint64_t len,
     287                 :            :                                 uint32_t *pvmove_mirror_count)
     288                 :            : {
     289                 :            :         struct mirror_state *mirr_state;
     290                 :          0 :         uint32_t area_count = seg->area_count;
     291                 :          0 :         unsigned start_area = 0u;
     292                 :          0 :         int mirror_status = MIRR_RUNNING;
     293                 :            :         uint32_t region_size;
     294                 :            :         int r;
     295                 :            : 
     296         [ #  # ]:          0 :         if (!*target_state)
     297                 :          0 :                 *target_state = _mirrored_init_target(mem, cmd);
     298                 :            : 
     299                 :          0 :         mirr_state = *target_state;
     300                 :            : 
     301                 :            :         /*
     302                 :            :          * Mirror segment could have only 1 area temporarily
     303                 :            :          * if the segment is under conversion.
     304                 :            :          */
     305         [ #  # ]:          0 :         if (seg->area_count == 1)
     306                 :          0 :                 mirror_status = MIRR_DISABLED;
     307                 :            : 
     308                 :            :         /*
     309                 :            :          * For pvmove, only have one mirror segment RUNNING at once.
     310                 :            :          * Segments before this are COMPLETED and use 2nd area.
     311                 :            :          * Segments after this are DISABLED and use 1st area.
     312                 :            :          */
     313         [ #  # ]:          0 :         if (seg->status & PVMOVE) {
     314         [ #  # ]:          0 :                 if (seg->extents_copied == seg->area_len) {
     315                 :          0 :                         mirror_status = MIRR_COMPLETED;
     316                 :          0 :                         start_area = 1;
     317         [ #  # ]:          0 :                 } else if ((*pvmove_mirror_count)++) {
     318                 :          0 :                         mirror_status = MIRR_DISABLED;
     319                 :          0 :                         area_count = 1;
     320                 :            :                 }
     321                 :            :                 /* else MIRR_RUNNING */
     322                 :            :         }
     323                 :            : 
     324         [ #  # ]:          0 :         if (mirror_status != MIRR_RUNNING) {
     325         [ #  # ]:          0 :                 if (!dm_tree_node_add_linear_target(node, len))
     326                 :          0 :                         return_0;
     327                 :          0 :                 goto done;
     328                 :            :         }
     329                 :            : 
     330         [ #  # ]:          0 :         if (!(seg->status & PVMOVE)) {
     331         [ #  # ]:          0 :                 if (!seg->region_size) {
     332                 :          0 :                         log_error("Missing region size for mirror segment.");
     333                 :          0 :                         return 0;
     334                 :            :                 }
     335                 :          0 :                 region_size = seg->region_size;
     336                 :            : 
     337                 :            :         } else
     338                 :          0 :                 region_size = adjusted_mirror_region_size(seg->lv->vg->extent_size,
     339                 :            :                                                           seg->area_len,
     340                 :            :                                                           mirr_state->default_region_size);
     341                 :            : 
     342         [ #  # ]:          0 :         if (!dm_tree_node_add_mirror_target(node, len))
     343                 :          0 :                 return_0;
     344                 :            : 
     345         [ #  # ]:          0 :         if ((r = _add_log(dm, seg, node, area_count, region_size)) <= 0) {
     346                 :          0 :                 stack;
     347                 :          0 :                 return r;
     348                 :            :         }
     349                 :            : 
     350                 :            :       done:
     351                 :          0 :         return add_areas_line(dm, seg, node, start_area, area_count);
     352                 :            : }
     353                 :            : 
     354                 :          0 : static int _mirrored_target_present(struct cmd_context *cmd,
     355                 :            :                                     const struct lv_segment *seg,
     356                 :            :                                     unsigned *attributes)
     357                 :            : {
     358                 :            :         static int _mirrored_checked = 0;
     359                 :            :         static int _mirrored_present = 0;
     360                 :            :         uint32_t maj, min, patchlevel;
     361                 :            :         unsigned maj2, min2, patchlevel2;
     362                 :            :         char vsn[80];
     363                 :            : 
     364         [ #  # ]:          0 :         if (!_mirrored_checked) {
     365                 :          0 :                 _mirrored_present = target_present(cmd, "mirror", 1);
     366                 :            : 
     367                 :            :                 /*
     368                 :            :                  * block_on_error available as "block_on_error" log
     369                 :            :                  * argument with mirror target >= 1.1 and <= 1.11
     370                 :            :                  * or with 1.0 in RHEL4U3 driver >= 4.5
     371                 :            :                  *
     372                 :            :                  * block_on_error available as "handle_errors" mirror
     373                 :            :                  * argument with mirror target >= 1.12.
     374                 :            :                  *
     375                 :            :                  * libdm-deptree.c is smart enough to handle the differences
     376                 :            :                  * between block_on_error and handle_errors for all
     377                 :            :                  * mirror target versions >= 1.1
     378                 :            :                  */
     379                 :            :                 /* FIXME Move this into libdevmapper */
     380                 :            : 
     381   [ #  #  #  # ]:          0 :                 if (target_version("mirror", &maj, &min, &patchlevel) &&
                 [ #  # ]
           [ #  #  #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     382                 :          0 :                     maj == 1 &&
     383                 :          0 :                     ((min >= 1) ||
     384                 :          0 :                      (min == 0 && driver_version(vsn, sizeof(vsn)) &&
     385                 :          0 :                       sscanf(vsn, "%u.%u.%u", &maj2, &min2, &patchlevel2) == 3 &&
     386                 :          0 :                       maj2 == 4 && min2 == 5 && patchlevel2 == 0)))     /* RHEL4U3 */
     387                 :          0 :                         _block_on_error_available = 1;
     388                 :            :         }
     389                 :            : 
     390                 :            :         /*
     391                 :            :          * Check only for modules if atttributes requested and no previous check.
     392                 :            :          * FIXME: Fails incorrectly if cmirror was built into kernel.
     393                 :            :          */
     394         [ #  # ]:          0 :         if (attributes) {
     395 [ #  # ][ #  # ]:          0 :                 if (!_mirror_attributes && module_present(cmd, "log-clustered"))
     396                 :          0 :                         _mirror_attributes |= MIRROR_LOG_CLUSTERED;
     397                 :          0 :                 *attributes = _mirror_attributes;
     398                 :            :         }
     399                 :          0 :         _mirrored_checked = 1;
     400                 :            : 
     401                 :          0 :         return _mirrored_present;
     402                 :            : }
     403                 :            : 
     404                 :            : #ifdef DMEVENTD
     405                 :            : static int _get_mirror_dso_path(struct cmd_context *cmd, char **dso)
     406                 :            : {
     407                 :            :         char *path;
     408                 :            :         const char *libpath;
     409                 :            : 
     410                 :            :         if (!(path = dm_pool_alloc(cmd->mem, PATH_MAX))) {
     411                 :            :                 log_error("Failed to allocate dmeventd library path.");
     412                 :            :                 return 0;
     413                 :            :         }
     414                 :            : 
     415                 :            :         libpath = find_config_tree_str(cmd, "dmeventd/mirror_library",
     416                 :            :                                        DEFAULT_DMEVENTD_MIRROR_LIB);
     417                 :            : 
     418                 :            :         get_shared_library_path(cmd, libpath, path, PATH_MAX);
     419                 :            : 
     420                 :            :         *dso = path;
     421                 :            : 
     422                 :            :         return 1;
     423                 :            : }
     424                 :            : 
     425                 :            : static struct dm_event_handler *_create_dm_event_handler(const char *dmname,
     426                 :            :                                                          const char *dso,
     427                 :            :                                                          enum dm_event_mask mask)
     428                 :            : {
     429                 :            :         struct dm_event_handler *dmevh;
     430                 :            : 
     431                 :            :         if (!(dmevh = dm_event_handler_create()))
     432                 :            :                 return_0;
     433                 :            : 
     434                 :            :        if (dm_event_handler_set_dso(dmevh, dso))
     435                 :            :                 goto fail;
     436                 :            : 
     437                 :            :         if (dm_event_handler_set_dev_name(dmevh, dmname))
     438                 :            :                 goto fail;
     439                 :            : 
     440                 :            :         dm_event_handler_set_event_mask(dmevh, mask);
     441                 :            :         return dmevh;
     442                 :            : 
     443                 :            : fail:
     444                 :            :         dm_event_handler_destroy(dmevh);
     445                 :            :         return NULL;
     446                 :            : }
     447                 :            : 
     448                 :            : static int _target_monitored(struct lv_segment *seg, int *pending)
     449                 :            : {
     450                 :            :         char *dso, *name;
     451                 :            :         struct logical_volume *lv;
     452                 :            :         struct volume_group *vg;
     453                 :            :         enum dm_event_mask evmask = 0;
     454                 :            :         struct dm_event_handler *dmevh;
     455                 :            : 
     456                 :            :         lv = seg->lv;
     457                 :            :         vg = lv->vg;
     458                 :            : 
     459                 :            :         *pending = 0;
     460                 :            :         if (!_get_mirror_dso_path(vg->cmd, &dso))
     461                 :            :                 return_0;
     462                 :            : 
     463                 :            :         if (!(name = build_dm_name(vg->cmd->mem, vg->name, lv->name, NULL)))
     464                 :            :                 return_0;
     465                 :            : 
     466                 :            :         if (!(dmevh = _create_dm_event_handler(name, dso, DM_EVENT_ALL_ERRORS)))
     467                 :            :                 return_0;
     468                 :            : 
     469                 :            :         if (dm_event_get_registered_device(dmevh, 0)) {
     470                 :            :                 dm_event_handler_destroy(dmevh);
     471                 :            :                 return 0;
     472                 :            :         }
     473                 :            : 
     474                 :            :         evmask = dm_event_handler_get_event_mask(dmevh);
     475                 :            :         if (evmask & DM_EVENT_REGISTRATION_PENDING) {
     476                 :            :                 *pending = 1;
     477                 :            :                 evmask &= ~DM_EVENT_REGISTRATION_PENDING;
     478                 :            :         }
     479                 :            : 
     480                 :            :         dm_event_handler_destroy(dmevh);
     481                 :            : 
     482                 :            :         return evmask;
     483                 :            : }
     484                 :            : 
     485                 :            : /* FIXME This gets run while suspended and performs banned operations. */
     486                 :            : static int _target_set_events(struct lv_segment *seg,
     487                 :            :                               int evmask __attribute((unused)), int set)
     488                 :            : {
     489                 :            :         char *dso, *name;
     490                 :            :         struct logical_volume *lv;
     491                 :            :         struct volume_group *vg;
     492                 :            :         struct dm_event_handler *dmevh;
     493                 :            :         int r;
     494                 :            : 
     495                 :            :         lv = seg->lv;
     496                 :            :         vg = lv->vg;
     497                 :            : 
     498                 :            :         if (!_get_mirror_dso_path(vg->cmd, &dso))
     499                 :            :                 return_0;
     500                 :            : 
     501                 :            :         if (!(name = build_dm_name(vg->cmd->mem, vg->name, lv->name, NULL)))
     502                 :            :                 return_0;
     503                 :            : 
     504                 :            :         if (!(dmevh = _create_dm_event_handler(name, dso, DM_EVENT_ALL_ERRORS)))
     505                 :            :                 return_0;
     506                 :            : 
     507                 :            :         r = set ? dm_event_register_handler(dmevh) : dm_event_unregister_handler(dmevh);
     508                 :            :         dm_event_handler_destroy(dmevh);
     509                 :            :         if (!r)
     510                 :            :                 return_0;
     511                 :            : 
     512                 :            :         log_info("%s %s for events", set ? "Monitored" : "Unmonitored", name);
     513                 :            : 
     514                 :            :         return 1;
     515                 :            : }
     516                 :            : 
     517                 :            : static int _target_monitor_events(struct lv_segment *seg, int events)
     518                 :            : {
     519                 :            :         return _target_set_events(seg, events, 1);
     520                 :            : }
     521                 :            : 
     522                 :            : static int _target_unmonitor_events(struct lv_segment *seg, int events)
     523                 :            : {
     524                 :            :         return _target_set_events(seg, events, 0);
     525                 :            : }
     526                 :            : 
     527                 :            : #endif /* DMEVENTD */
     528                 :            : #endif /* DEVMAPPER_SUPPORT */
     529                 :            : 
     530                 :          0 : static int _mirrored_modules_needed(struct dm_pool *mem,
     531                 :            :                                     const struct lv_segment *seg,
     532                 :            :                                     struct dm_list *modules)
     533                 :            : {
     534   [ #  #  #  # ]:          0 :         if (seg->log_lv &&
     535                 :          0 :             !list_segment_modules(mem, first_seg(seg->log_lv), modules))
     536                 :          0 :                 return_0;
     537                 :            : 
     538   [ #  #  #  # ]:          0 :         if (vg_is_clustered(seg->lv->vg) &&
     539                 :          0 :             !str_list_add(mem, modules, "clog")) {
     540                 :          0 :                 log_error("cluster log string list allocation failed");
     541                 :          0 :                 return 0;
     542                 :            :         }
     543                 :            : 
     544         [ #  # ]:          0 :         if (!str_list_add(mem, modules, "mirror")) {
     545                 :          0 :                 log_error("mirror string list allocation failed");
     546                 :          0 :                 return 0;
     547                 :            :         }
     548                 :            : 
     549                 :          0 :         return 1;
     550                 :            : }
     551                 :            : 
     552                 :          3 : static void _mirrored_destroy(const struct segment_type *segtype)
     553                 :            : {
     554                 :          3 :         dm_free((void *) segtype);
     555                 :          3 : }
     556                 :            : 
     557                 :            : static struct segtype_handler _mirrored_ops = {
     558                 :            :         .name = _mirrored_name,
     559                 :            :         .display = _mirrored_display,
     560                 :            :         .text_import_area_count = _mirrored_text_import_area_count,
     561                 :            :         .text_import = _mirrored_text_import,
     562                 :            :         .text_export = _mirrored_text_export,
     563                 :            : #ifdef DEVMAPPER_SUPPORT
     564                 :            :         .add_target_line = _mirrored_add_target_line,
     565                 :            :         .target_percent = _mirrored_target_percent,
     566                 :            :         .target_present = _mirrored_target_present,
     567                 :            : #ifdef DMEVENTD
     568                 :            :         .target_monitored = _target_monitored,
     569                 :            :         .target_monitor_events = _target_monitor_events,
     570                 :            :         .target_unmonitor_events = _target_unmonitor_events,
     571                 :            : #endif
     572                 :            : #endif
     573                 :            :         .modules_needed = _mirrored_modules_needed,
     574                 :            :         .destroy = _mirrored_destroy,
     575                 :            : };
     576                 :            : 
     577                 :            : #ifdef MIRRORED_INTERNAL
     578                 :          3 : struct segment_type *init_mirrored_segtype(struct cmd_context *cmd)
     579                 :            : #else                           /* Shared */
     580                 :            : struct segment_type *init_segtype(struct cmd_context *cmd);
     581                 :            : struct segment_type *init_segtype(struct cmd_context *cmd)
     582                 :            : #endif
     583                 :            : {
     584                 :          3 :         struct segment_type *segtype = dm_malloc(sizeof(*segtype));
     585                 :            : 
     586         [ -  + ]:          3 :         if (!segtype)
     587                 :          0 :                 return_NULL;
     588                 :            : 
     589                 :          3 :         segtype->cmd = cmd;
     590                 :          3 :         segtype->ops = &_mirrored_ops;
     591                 :          3 :         segtype->name = "mirror";
     592                 :          3 :         segtype->private = NULL;
     593                 :          3 :         segtype->flags = SEG_AREAS_MIRRORED | SEG_MONITORED;
     594                 :            : 
     595                 :          3 :         log_very_verbose("Initialised segtype: %s", segtype->name);
     596                 :            : 
     597                 :          3 :         return segtype;
     598                 :            : }

Generated by: LCOV version 1.8