1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-22 17:35:59 +03:00
lvm2/lib/metadata/lv_alloc.h

87 lines
3.3 KiB
C
Raw Normal View History

2003-09-15 22:22:50 +04:00
/*
2004-03-30 23:35:44 +04:00
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
2012-01-26 02:37:48 +04:00
* Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
2003-09-15 22:22:50 +04:00
*
2004-03-30 23:35:44 +04:00
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License v.2.1.
2004-03-30 23:35:44 +04:00
*
* You should have received a copy of the GNU Lesser General Public License
2004-03-30 23:35:44 +04:00
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2003-09-15 22:22:50 +04:00
*/
#ifndef _LVM_LV_ALLOC_H
2012-01-26 02:37:48 +04:00
#define _LVM_LV_ALLOC_H
2003-09-15 22:22:50 +04:00
2012-01-26 02:26:33 +04:00
#include "metadata-exported.h"
struct lv_segment *alloc_lv_segment(const struct segment_type *segtype,
2005-04-22 19:44:00 +04:00
struct logical_volume *lv,
uint32_t le, uint32_t len,
uint64_t status,
2005-04-22 19:44:00 +04:00
uint32_t stripe_size,
2005-06-01 20:51:55 +04:00
struct logical_volume *log_lv,
2005-04-22 19:44:00 +04:00
uint32_t area_count,
uint32_t area_len,
uint32_t chunk_size,
2005-06-01 20:51:55 +04:00
uint32_t region_size,
uint32_t extents_copied,
struct lv_segment *pvmove_source_seg);
2005-04-22 19:44:00 +04:00
int set_lv_segment_area_pv(struct lv_segment *seg, uint32_t area_num,
struct physical_volume *pv, uint32_t pe);
int set_lv_segment_area_lv(struct lv_segment *seg, uint32_t area_num,
struct logical_volume *lv, uint32_t le,
uint64_t status);
int move_lv_segment_area(struct lv_segment *seg_to, uint32_t area_to,
struct lv_segment *seg_from, uint32_t area_from);
int release_lv_segment_area(struct lv_segment *seg, uint32_t s,
uint32_t area_reduction);
int release_and_discard_lv_segment_area(struct lv_segment *seg, uint32_t s, uint32_t area_reduction);
2005-04-22 19:43:02 +04:00
2005-06-01 20:51:55 +04:00
struct alloc_handle;
struct alloc_handle *allocate_extents(struct volume_group *vg,
struct logical_volume *lv,
const struct segment_type *segtype,
2005-06-01 20:51:55 +04:00
uint32_t stripes,
uint32_t mirrors, uint32_t log_count,
uint32_t log_region_size, uint32_t extents,
struct dm_list *allocatable_pvs,
alloc_policy_t alloc, int approx_alloc,
struct dm_list *parallel_areas);
2005-06-01 20:51:55 +04:00
int lv_add_segment(struct alloc_handle *ah,
uint32_t first_area, uint32_t num_areas,
struct logical_volume *lv,
const struct segment_type *segtype,
2005-06-01 20:51:55 +04:00
uint32_t stripe_size,
uint64_t status,
uint32_t region_size);
2005-06-01 20:51:55 +04:00
int lv_add_mirror_areas(struct alloc_handle *ah,
struct logical_volume *lv, uint32_t le,
uint32_t region_size);
pvmove: Enable all-or-nothing (atomic) pvmoves pvmove can be used to move single LVs by name or multiple LVs that lie within the specified PV range (e.g. /dev/sdb1:0-1000). When moving more than one LV, the portions of those LVs that are in the range to be moved are added to a new temporary pvmove LV. The LVs then point to the range in the pvmove LV, rather than the PV range. Example 1: We have two LVs in this example. After they were created, the first LV was grown, yeilding two segments in LV1. So, there are two LVs with a total of three segments. Before pvmove: --------- --------- --------- | LV1s0 | | LV2s0 | | LV1s1 | --------- --------- --------- | | | ------------------------------------- PV | 000 - 255 | 256 - 511 | 512 - 767 | ------------------------------------- After pvmove inserts the temporary pvmove LV: --------- --------- --------- | LV1s0 | | LV2s0 | | LV1s1 | --------- --------- --------- | | | ------------------------------------- pvmove0 | seg 0 | seg 1 | seg 2 | ------------------------------------- | | | ------------------------------------- PV | 000 - 255 | 256 - 511 | 512 - 767 | ------------------------------------- Each of the affected LV segments now point to a range of blocks in the pvmove LV, which purposefully corresponds to the segments moved from the original LVs into the temporary pvmove LV. The current implementation goes on from here to mirror the temporary pvmove LV by segment. Further, as the pvmove LV is activated, only one of its segments is actually mirrored (i.e. "moving") at a time. The rest are either complete or not addressed yet. If the pvmove is aborted, those segments that are completed will remain on the destination and those that are not yet addressed or in the process of moving will stay on the source PV. Thus, it is possible to have a partially completed move - some LVs (or certain segments of LVs) on the source PV and some on the destination. Example 2: What 'example 1' might look if it was half-way through the move. --------- --------- --------- | LV1s0 | | LV2s0 | | LV1s1 | --------- --------- --------- | | | ------------------------------------- pvmove0 | seg 0 | seg 1 | seg 2 | ------------------------------------- | | | | ------------------------- source PV | | 256 - 511 | 512 - 767 | | ------------------------- | || ------------------------- dest PV | 000 - 255 | 256 - 511 | ------------------------- This update allows the user to specify that they would like the pvmove mirror created "by LV" rather than "by segment". That is, the pvmove LV becomes an image in an encapsulating mirror along with the allocated copy image. Example 3: A pvmove that is performed "by LV" rather than "by segment". --------- --------- | LV1s0 | | LV2s0 | --------- --------- | | ------------------------- pvmove0 | * LV-level mirror * | ------------------------- / \ pvmove_mimage0 / pvmove_mimage1 ------------------------- ------------------------- | seg 0 | seg 1 | | seg 0 | seg 1 | ------------------------- ------------------------- | | | | ------------------------- ------------------------- | 000 - 255 | 256 - 511 | | 000 - 255 | 256 - 511 | ------------------------- ------------------------- source PV dest PV The thing that differentiates a pvmove done in this way and a simple "up-convert" from linear to mirror is the preservation of the distinct segments. A normal up-convert would simply allocate the necessary space with no regard for segment boundaries. The pvmove operation must preserve the segments because they are the critical boundary between the segments of the LVs being moved. So, when the pvmove copy image is allocated, all corresponding segments must be allocated. The code that merges ajoining segments that are part of the same LV when the metadata is written must also be avoided in this case. This method of mirroring is unique enough to warrant its own definitional macro, MIRROR_BY_SEGMENTED_LV. This joins the two existing macros: MIRROR_BY_SEG (for original pvmove) and MIRROR_BY_LV (for user created mirrors). The advantages of performing pvmove in this way is that all of the LVs affected can be moved together. It is an all-or-nothing approach that leaves all LV segments on the source PV if the move is aborted. Additionally, a mirror log can be used (in the future) to provide tracking of progress; allowing the copy to continue where it left off in the event there is a deactivation.
2014-06-18 07:59:36 +04:00
int lv_add_segmented_mirror_image(struct alloc_handle *ah,
struct logical_volume *lv, uint32_t le,
uint32_t region_size);
int lv_add_mirror_lvs(struct logical_volume *lv,
struct logical_volume **sub_lvs,
uint32_t num_extra_areas,
uint64_t status, uint32_t region_size);
int lv_add_log_segment(struct alloc_handle *ah, uint32_t first_area,
struct logical_volume *log_lv, uint64_t status);
int lv_add_virtual_segment(struct logical_volume *lv, uint64_t status,
uint32_t extents, const struct segment_type *segtype);
2005-06-01 20:51:55 +04:00
void alloc_destroy(struct alloc_handle *ah);
struct dm_list *build_parallel_areas_from_lv(struct logical_volume *lv,
unsigned use_pvmove_parent_lv,
unsigned create_single_list);
2003-09-15 22:22:50 +04:00
#endif