Tizen 2.1 base
[external/device-mapper.git] / lib / metadata / replicator_manip.c
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 "locking.h"
17 #include "metadata.h"
18 #include "segtype.h"
19 #include "toolcontext.h"
20
21 /* Add lv as replicator_dev device */
22 int replicator_dev_add_rimage(struct replicator_device *rdev,
23                               struct logical_volume *lv)
24 {
25         if (!lv || !rdev)
26                 return_0;
27
28         if (lv_is_rimage(lv)) {
29                 log_error("Logical volume %s is already part of other "
30                           "replicator.", lv->name);
31                 return 0;
32         }
33
34         if (rdev->lv) {
35                 log_error("Logical volume %s can not be attached to an "
36                           "already defined replicator device", lv->name);
37                 return 0;
38         }
39
40         lv_set_hidden(lv);
41         lv->rdevice = rdev;
42         rdev->lv = lv;
43
44         return add_seg_to_segs_using_this_lv(lv, rdev->replicator_dev);
45 }
46
47 /* Remove lv from replicator_dev device */
48 struct logical_volume *replicator_dev_remove_rimage(struct replicator_device *rdev)
49 {
50         struct logical_volume *lv;
51
52         if (!rdev || !rdev->lv)
53                 return_NULL;
54
55         lv = rdev->lv;
56         if (!remove_seg_from_segs_using_this_lv(lv, rdev->replicator_dev))
57                 return_NULL;
58
59         /* FIXME: - check for site references */
60         rdev->lv = NULL;
61         lv->rdevice = NULL;
62         lv_set_visible(lv);
63
64         return lv;
65 }
66
67 int replicator_dev_add_slog(struct replicator_device *rdev,
68                             struct logical_volume *slog)
69 {
70         if (!slog || !rdev)
71                 return_0;
72
73         if (rdev->slog) {
74                 log_error("Replicator device in site %s already has sync log.",
75                           rdev->rsite->name);
76                 return 0;
77         }
78
79         if (slog->rdevice) {
80                 log_error("Sync log %s is already used by replicator %s.",
81                           slog->name, slog->rdevice->rsite->replicator->name);
82                 return 0;
83         }
84
85         lv_set_hidden(slog);
86         slog->rdevice = rdev;
87         rdev->slog = slog;
88
89         return add_seg_to_segs_using_this_lv(slog, rdev->replicator_dev);
90 }
91
92 struct logical_volume *replicator_dev_remove_slog(struct replicator_device *rdev)
93 {
94         struct logical_volume *lv;
95
96         if (!rdev)
97                 return_NULL;
98
99         lv = rdev->slog;
100         if (!lv) {
101                 log_error("Replicator device in site %s does not have sync log.",
102                           rdev->rsite->name);
103                 return NULL;
104         }
105
106         if (!remove_seg_from_segs_using_this_lv(lv, rdev->replicator_dev))
107                 return_NULL;
108
109         rdev->slog = NULL;
110         lv->rdevice = NULL;
111         lv_set_visible(lv);
112
113         return lv;
114 }
115
116 int replicator_add_replicator_dev(struct logical_volume *replicator_lv,
117                                   struct lv_segment *replicator_dev_seg)
118 {
119         if (!replicator_lv)
120                 return_0;
121
122         if (!(replicator_lv->status & REPLICATOR)) {
123                 dm_list_init(&replicator_lv->rsites);
124                 lv_set_hidden(replicator_lv);
125                 replicator_lv->status |= REPLICATOR;
126         }
127
128         if (!replicator_dev_seg)
129                 return 1;
130
131         if (replicator_dev_seg->replicator) {
132                 log_error("Replicator device %s is already part of replicator.",
133                           replicator_dev_seg->lv->name);
134                 return 0;
135         }
136
137         replicator_dev_seg->replicator = replicator_lv;
138
139         return add_seg_to_segs_using_this_lv(replicator_lv, replicator_dev_seg);
140 }
141
142 /**
143  * Returns rimage ?? lv upon succeful detach of device
144  * entire LV entry should be removed by this crootall ??
145  */
146 struct logical_volume *replicator_remove_replicator_dev(struct lv_segment *replicator_dev_seg)
147 {
148         struct logical_volume *lv = NULL;
149
150         log_error("FIXME: not implemented.");
151 #if 0
152         /* FIXME: - this is going to be complex.... */
153         if (!replicator_dev_seg)
154                 return_NULL;
155
156         /* if slog or rimage - exit */
157
158         if (!remove_seg_from_segs_using_this_lv(lv, replicator_seg))
159                 return_NULL;
160
161         replicator_seg->rlog_lv = NULL;
162         lv->status &= ~REPLICATOR_LOG;
163         lv_set_visible(lv);
164 #endif
165
166         return lv;
167 }
168
169 int replicator_add_rlog(struct lv_segment *replicator_seg,
170                         struct logical_volume *rlog_lv)
171 {
172         if (!rlog_lv)
173                 return_0;
174
175         if (rlog_lv->status & REPLICATOR_LOG) {
176                 log_error("Rlog device %s is already used.", rlog_lv->name);
177                 return 0;
178         }
179
180         lv_set_hidden(rlog_lv);
181         rlog_lv->status |= REPLICATOR_LOG;
182         replicator_seg->rlog_lv = rlog_lv;
183
184         return add_seg_to_segs_using_this_lv(rlog_lv, replicator_seg);
185 }
186
187 struct logical_volume *replicator_remove_rlog(struct lv_segment *replicator_seg)
188 {
189         struct logical_volume *lv;
190
191         if (!replicator_seg)
192                 return_0;
193
194         if (!(lv = replicator_seg->rlog_lv)) {
195                 log_error("Replog segment %s does not have rlog.",
196                           replicator_seg->lv->name);
197                 return NULL;
198         }
199
200         if (!remove_seg_from_segs_using_this_lv(lv, replicator_seg))
201                 return_NULL;
202
203         replicator_seg->rlog_lv = NULL;
204         lv->status &= ~REPLICATOR_LOG;
205         lv_set_visible(lv);
206
207         return lv;
208 }
209
210
211 #if 0
212 /*
213  * Create new LV to pretend the original LV
214  * this target will have a 'replicator' segment
215  */
216 int lv_add_replicator(struct logical_volume *origin, const char *rep_suffix)
217 {
218         struct logical_volume *rep_lv;
219         char *name;
220         size_t slen;
221
222         if (!(name = strstr(origin->name, rep_suffix))) {
223                 log_error("Failed to find replicator suffix %s in LV name %s",
224                           rep_suffix, origin->name);
225                 return 0;
226         }
227         slen = (size_t)(name - origin->name);
228         name = alloca(slen + 1);
229         memcpy(name, origin->name, slen);
230         name[slen] = 0;
231
232         if ((rep_lv = find_lv(origin->vg, name))) {
233                 rep_lv->status |= VIRTUAL;
234                 return 1;
235         }
236
237         if (!(rep_lv = lv_create_empty(name, &origin->lvid,
238                                        LVM_READ | LVM_WRITE | VISIBLE_LV,
239                                        ALLOC_INHERIT, origin->vg)))
240                 return_0;
241
242         if (!lv_add_virtual_segment(rep_lv, 0, origin->le_count,
243                                     get_segtype_from_string(origin->vg->cmd,
244                                                             "error")))
245                 return_0;
246
247         rep_lv->status |= VIRTUAL;
248         return 1;
249 }
250
251 int lv_remove_replicator(struct logical_volume *lv)
252 {
253         return 1;
254 }
255 #endif
256
257 /*
258  * Check all replicator structures:
259  *  only non-clustered VG for Replicator
260  *  only one segment in replicator LV
261  *  site has correct combination of operation_mode parameters
262  *  site and related devices have correct index numbers
263  *  duplicate site names, site indexes, device names, device indexes
264  */
265 int check_replicator_segment(const struct lv_segment *rseg)
266 {
267         struct replicator_site *rsite, *rsiteb;
268         struct replicator_device *rdev, *rdevb;
269         struct logical_volume *lv = rseg->lv;
270         int r = 1;
271
272         if (vg_is_clustered(lv->vg)) {
273                 log_error("Volume Group %s of replicator %s is clustered",
274                           lv->vg->name, lv->name);
275                 return 0;
276         }
277
278         if (dm_list_size(&lv->segments) != 1) {
279                 log_error("Replicator %s segment size %d != 1",
280                           lv->name, dm_list_size(&lv->segments));
281                 return 0;
282         }
283
284         dm_list_iterate_items(rsite, &lv->rsites) {
285                 if (rsite->op_mode == DM_REPLICATOR_SYNC) {
286                         if (rsite->fall_behind_timeout) {
287                                 log_error("Defined fall_behind_timeout="
288                                           "%d for sync replicator %s/%s.",
289                                           rsite->fall_behind_timeout, lv->name,
290                                           rsite->name);
291                                 r = 0;
292                         }
293                         if (rsite->fall_behind_ios) {
294                                 log_error("Defined fall_behind_ios="
295                                           "%d for sync replicator %s/%s.",
296                                           rsite->fall_behind_ios, lv->name, rsite->name);
297                                 r = 0;
298                         }
299                         if (rsite->fall_behind_data) {
300                                 log_error("Defined fall_behind_data="
301                                           "%" PRIu64 " for sync replicator %s/%s.",
302                                           rsite->fall_behind_data, lv->name, rsite->name);
303                                 r = 0;
304                         }
305                 } else {
306                         if (rsite->fall_behind_timeout && rsite->fall_behind_ios) {
307                                 log_error("Defined fall_behind_timeout and"
308                                           " fall_behind_ios for async replicator %s/%s.",
309                                           lv->name, rsite->name);
310                                 r = 0;
311                         }
312                         if (rsite->fall_behind_timeout && rsite->fall_behind_data) {
313                                 log_error("Defined fall_behind_timeout and"
314                                           " fall_behind_data for async replicator %s/%s.",
315                                           lv->name, rsite->name);
316                                 r = 0;
317                         }
318                         if (rsite->fall_behind_ios && rsite->fall_behind_data) {
319                                 log_error("Defined fall_behind_ios and"
320                                           " fall_behind_data for async replicator %s/%s.",
321                                           lv->name, rsite->name);
322                                 r = 0;
323                         }
324                         if (!rsite->fall_behind_ios &&
325                             !rsite->fall_behind_data &&
326                             !rsite->fall_behind_timeout) {
327                                 log_error("fall_behind_timeout,"
328                                           " fall_behind_ios and fall_behind_data are"
329                                           " undefined for async replicator %s/%s.",
330                                           lv->name, rsite->name);
331                                 r = 0;
332                         }
333                 }
334                 dm_list_iterate_items(rsiteb, &lv->rsites) {
335                         if (rsite == rsiteb)
336                                 break;
337                         if (strcasecmp(rsite->name, rsiteb->name) == 0) {
338                                 log_error("Duplicate site name "
339                                           "%s detected for replicator %s.",
340                                           rsite->name, lv->name);
341                                 r = 0;
342                         }
343                         if ((rsite->vg_name && rsiteb->vg_name &&
344                              strcasecmp(rsite->vg_name, rsiteb->vg_name) == 0) ||
345                             (!rsite->vg_name && !rsiteb->vg_name)) {
346                                 log_error("Duplicate VG name "
347                                           "%s detected for replicator %s.",
348                                           (rsite->vg_name) ? rsite->vg_name : "<local>",
349                                           lv->name);
350                                 r = 0;
351                         }
352                         if (rsite->site_index == rsiteb->site_index) {
353                                 log_error("Duplicate site index %d detected "
354                                           "for replicator site %s/%s.",
355                                           rsite->site_index, lv->name,
356                                           rsite->name);
357                                 r = 0;
358                         }
359                         if (rsite->site_index > rseg->rsite_index_highest) {
360                                 log_error("Site index %d > %d (too high) "
361                                           "for replicator site %s/%s.",
362                                           rsite->site_index,
363                                           rseg->rsite_index_highest,
364                                           lv->name, rsite->name);
365                                 r = 0;
366                         }
367                 }
368
369                 dm_list_iterate_items(rdev, &rsite->rdevices) {
370                         dm_list_iterate_items(rdevb, &rsite->rdevices) {
371                                 if (rdev == rdevb)
372                                         break;
373                                 if (rdev->slog && (rdev->slog == rdevb->slog)) {
374                                         log_error("Duplicate sync log %s "
375                                                   "detected for replicator %s.",
376                                                   rdev->slog->name, lv->name);
377                                         r = 0;
378                                 }
379                                 if (strcasecmp(rdev->name, rdevb->name) == 0) {
380                                         log_error("Duplicate device name %s "
381                                                   "detected for replicator %s.",
382                                                   rdev->name, lv->name);
383                                         r = 0;
384                                 }
385                                 if (rdev->device_index == rdevb->device_index) {
386                                         log_error("Duplicate device index %"
387                                                   PRId64 " detected for "
388                                                   "replicator site %s/%s.",
389                                                   rdev->device_index,
390                                                   lv->name, rsite->name);
391                                         r = 0;
392                                 }
393                                 if (rdev->device_index > rseg->rdevice_index_highest) {
394                                         log_error("Device index %" PRIu64
395                                                   " > %" PRIu64 " (too high) "
396                                                   "for replicator site %s/%s.",
397                                                   rdev->device_index,
398                                                   rseg->rdevice_index_highest,
399                                                   lv->name, rsite->name);
400                                         r = 0;
401                                 }
402                         }
403                 }
404         }
405
406         return r;
407 }
408
409 /**
410  * Is this segment part of active replicator
411  */
412 int lv_is_active_replicator_dev(const struct logical_volume *lv)
413 {
414         return ((lv->status & REPLICATOR) &&
415                 lv->rdevice &&
416                 lv->rdevice->rsite &&
417                 lv->rdevice->rsite->state == REPLICATOR_STATE_ACTIVE);
418 }
419
420 /**
421  * Is this LV replicator control device
422  */
423 int lv_is_replicator(const struct logical_volume *lv)
424 {
425         return ((lv->status & REPLICATOR) &&
426                 !dm_list_empty(&lv->segments) &&
427                 seg_is_replicator(first_seg(lv)));
428 }
429
430 /**
431  * Is this LV replicator device
432  */
433 int lv_is_replicator_dev(const struct logical_volume *lv)
434 {
435         return ((lv->status & REPLICATOR) &&
436                 !dm_list_empty(&lv->segments) &&
437                 seg_is_replicator_dev(first_seg(lv)));
438 }
439
440 /**
441  * Is this LV replicated origin lv
442  */
443 int lv_is_rimage(const struct logical_volume *lv)
444 {
445         return (lv->rdevice && lv->rdevice->lv == lv);
446 }
447
448 /**
449  * Is this LV rlog
450  */
451 int lv_is_rlog(const struct logical_volume *lv)
452 {
453         return (lv->status & REPLICATOR_LOG);
454 }
455
456 /**
457  * Is this LV sync log
458  */
459 int lv_is_slog(const struct logical_volume *lv)
460 {
461         return (lv->rdevice && lv->rdevice->slog == lv);
462 }
463
464 /**
465  * Returns first replicator-dev in site in case the LV is replicator-dev,
466  * NULL otherwise
467  */
468 struct logical_volume *first_replicator_dev(const struct logical_volume *lv)
469 {
470         struct replicator_device *rdev;
471         struct replicator_site *rsite;
472
473         if (lv_is_replicator_dev(lv))
474                 dm_list_iterate_items(rsite, &first_seg(lv)->replicator->rsites) {
475                         dm_list_iterate_items(rdev, &rsite->rdevices)
476                                 return rdev->replicator_dev->lv;
477                         break;
478                 }
479
480         return NULL;
481 }
482
483 /**
484  * Add VG open parameters to sorted cmd_vg list.
485  *
486  * Maintain the alphabeticaly ordered list, avoid duplications.
487  *
488  * \return      Returns newly created or already present cmd_vg entry,
489  *              or NULL in error case.
490  */
491 struct cmd_vg *cmd_vg_add(struct dm_pool *mem, struct dm_list *cmd_vgs,
492                           const char *vg_name, const char *vgid,
493                           uint32_t flags)
494 {
495         struct cmd_vg *cvl, *ins;
496
497         if (!vg_name && !vgid) {
498                 log_error("Either vg_name or vgid must be set.");
499                 return NULL;
500         }
501
502         /* Is it already in the list ? */
503         if ((cvl = cmd_vg_lookup(cmd_vgs, vg_name, vgid)))
504                 return cvl;
505
506         if (!(cvl = dm_pool_zalloc(mem, sizeof(*cvl)))) {
507                 log_error("Allocation of cmd_vg failed.");
508                 return NULL;
509         }
510
511         if (vg_name && !(cvl->vg_name = dm_pool_strdup(mem, vg_name))) {
512                 dm_pool_free(mem, cvl);
513                 log_error("Allocation of vg_name failed.");
514                 return NULL;
515         }
516
517         if (vgid && !(cvl->vgid = dm_pool_strdup(mem, vgid))) {
518                 dm_pool_free(mem, cvl);
519                 log_error("Allocation of vgid failed.");
520                 return NULL;
521         }
522
523         cvl->flags = flags;
524
525         if (vg_name)
526                 dm_list_iterate_items(ins, cmd_vgs)
527                         if (strcmp(vg_name, ins->vg_name) < 0) {
528                                 cmd_vgs = &ins->list; /* new position */
529                                 break;
530                         }
531
532         dm_list_add(cmd_vgs, &cvl->list);
533
534         return cvl;
535 }
536
537 /**
538  * Find cmd_vg with given vg_name in cmd_vgs list.
539  *
540  * \param cmd_vgs       List of cmd_vg entries.
541  *
542  * \param vg_name       Name of VG to be found.
543
544  * \param vgid          UUID of VG to be found.
545  *
546  * \return              Returns cmd_vg entry if vg_name or vgid is found,
547  *                      NULL otherwise.
548  */
549 struct cmd_vg *cmd_vg_lookup(struct dm_list *cmd_vgs,
550                              const char *vg_name, const char *vgid)
551 {
552         struct cmd_vg *cvl;
553
554         dm_list_iterate_items(cvl, cmd_vgs)
555                 if ((vgid && cvl->vgid && !strcmp(vgid, cvl->vgid)) ||
556                     (vg_name && cvl->vg_name && !strcmp(vg_name, cvl->vg_name)))
557                         return cvl;
558         return NULL;
559 }
560
561 /**
562  * Read and lock multiple VGs stored in cmd_vgs list alphabeticaly.
563  * On the success list head pointer is set to VGs' cmd_vgs.
564  * (supports FAILED_INCONSISTENT)
565  *
566  * \param cmd_vg        Contains list of cmd_vg entries.
567  *
568  * \return              Returns 1 if all VG in cmd_vgs list are correctly
569  *                      openned and locked, 0 otherwise.
570  */
571 int cmd_vg_read(struct cmd_context *cmd, struct dm_list *cmd_vgs)
572 {
573         struct cmd_vg *cvl;
574
575         /* Iterate through alphabeticaly ordered cmd_vg list */
576         dm_list_iterate_items(cvl, cmd_vgs) {
577                 cvl->vg = vg_read(cmd, cvl->vg_name, cvl->vgid, cvl->flags);
578                 if (vg_read_error(cvl->vg)) {
579                         log_debug("Failed to vg_read %s", cvl->vg_name);
580                         return 0;
581                 }
582                 cvl->vg->cmd_vgs = cmd_vgs;     /* Make it usable in VG */
583         }
584
585         return 1;
586 }
587
588 /**
589  * Release opened and locked VGs from list.
590  *
591  * \param cmd_vgs       Contains list of cmd_vg entries.
592  */
593 void free_cmd_vgs(struct dm_list *cmd_vgs)
594 {
595         struct cmd_vg *cvl;
596
597         /* Backward iterate cmd_vg list */
598         dm_list_iterate_back_items(cvl, cmd_vgs) {
599                 if (vg_read_error(cvl->vg))
600                         free_vg(cvl->vg);
601                 else
602                         unlock_and_free_vg(cvl->vg->cmd, cvl->vg, cvl->vg_name);
603                 cvl->vg = NULL;
604         }
605 }
606
607 /**
608  * Find all needed remote VGs for processing given LV.
609  * Missing VGs are added to VG's cmd_vg list and flag cmd_missing_vgs is set.
610  */
611 int find_replicator_vgs(struct logical_volume *lv)
612 {
613         struct replicator_site *rsite;
614         int ret = 1;
615
616         if (!lv_is_replicator_dev(lv))
617                 return 1;
618
619         dm_list_iterate_items(rsite, &first_seg(lv)->replicator->rsites) {
620                 if (!rsite->vg_name || !lv->vg->cmd_vgs ||
621                     cmd_vg_lookup(lv->vg->cmd_vgs, rsite->vg_name, NULL))
622                         continue;
623                 ret = 0;
624                 /* Using cmd memory pool for cmd_vg list allocation */
625                 if (!cmd_vg_add(lv->vg->cmd->mem, lv->vg->cmd_vgs,
626                                 rsite->vg_name, NULL, 0)) {
627                         lv->vg->cmd_missing_vgs = 0; /* do not retry */
628                         stack;
629                         break;
630                 }
631
632                 log_debug("VG: %s added as missing.", rsite->vg_name);
633                 lv->vg->cmd_missing_vgs++;
634         }
635
636         return ret;
637 }
638
639 /**
640  * Read all remote VGs from lv's replicator sites.
641  * Function is used in activation context and needs all VGs already locked.
642  */
643 int lv_read_replicator_vgs(struct logical_volume *lv)
644 {
645         struct replicator_device *rdev;
646         struct replicator_site *rsite;
647         struct volume_group *vg;
648
649         if (!lv_is_replicator_dev(lv))
650                 return 1;
651
652         dm_list_iterate_items(rsite, &first_seg(lv)->replicator->rsites) {
653                 if (!rsite->vg_name)
654                         continue;
655                 vg = vg_read(lv->vg->cmd, rsite->vg_name, 0, 0); // READ_WITHOUT_LOCK
656                 if (vg_read_error(vg)) {
657                         log_error("Unable to read volume group %s",
658                                   rsite->vg_name);
659                         goto bad;
660                 }
661                 rsite->vg = vg;
662                 /* FIXME: handling missing LVs needs to be better */
663                 dm_list_iterate_items(rdev, &rsite->rdevices)
664                         if (!(rdev->lv = find_lv(vg, rdev->name))) {
665                                 log_error("Unable to find %s in volume group %s",
666                                           rdev->name, rsite->vg_name);
667                                 goto bad;
668                         }
669         }
670
671         return 1;
672 bad:
673         lv_release_replicator_vgs(lv);
674         return 0;
675 }
676
677 /**
678  * Release all VG resources taken by lv's replicator sites.
679  * Function is used in activation context and needs all VGs already locked.
680  */
681 void lv_release_replicator_vgs(struct logical_volume *lv)
682 {
683         struct replicator_site *rsite;
684
685         if (!lv_is_replicator_dev(lv))
686                 return;
687
688         dm_list_iterate_back_items(rsite, &first_seg(lv)->replicator->rsites)
689                 if (rsite->vg_name && rsite->vg) {
690                         free_vg(rsite->vg);
691                         rsite->vg = NULL;
692                 }
693 }