]> sourceware.org Git - lvm2.git/blob - lib/format1/layout.c
thin: fix recent commits
[lvm2.git] / lib / format1 / layout.c
1 /*
2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 * Copyright (C) 2004-2006 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 "disk-rep.h"
18
19 /*
20 * Only works with powers of 2.
21 */
22 static uint32_t _round_up(uint32_t n, uint32_t size)
23 {
24 size--;
25 return (n + size) & ~size;
26 }
27
28 /* Unused.
29 static uint32_t _div_up(uint32_t n, uint32_t size)
30 {
31 return _round_up(n, size) / size;
32 }
33 */
34
35 /*
36 * Each chunk of metadata should be aligned to
37 * METADATA_ALIGN.
38 */
39 static uint32_t _next_base(struct data_area *area)
40 {
41 return _round_up(area->base + area->size, METADATA_ALIGN);
42 }
43
44 /*
45 * Quick calculation based on pe_start.
46 */
47 static int _adjust_pe_on_disk(struct pv_disk *pvd)
48 {
49 uint32_t pe_start = pvd->pe_start << SECTOR_SHIFT;
50
51 if (pe_start < pvd->pe_on_disk.base + pvd->pe_on_disk.size)
52 return 0;
53
54 pvd->pe_on_disk.size = pe_start - pvd->pe_on_disk.base;
55 return 1;
56 }
57
58 static void _calc_simple_layout(struct pv_disk *pvd)
59 {
60 pvd->pv_on_disk.base = METADATA_BASE;
61 pvd->pv_on_disk.size = PV_SIZE;
62
63 pvd->vg_on_disk.base = _next_base(&pvd->pv_on_disk);
64 pvd->vg_on_disk.size = VG_SIZE;
65
66 pvd->pv_uuidlist_on_disk.base = _next_base(&pvd->vg_on_disk);
67 pvd->pv_uuidlist_on_disk.size = MAX_PV * NAME_LEN;
68
69 pvd->lv_on_disk.base = _next_base(&pvd->pv_uuidlist_on_disk);
70 pvd->lv_on_disk.size = MAX_LV * sizeof(struct lv_disk);
71
72 pvd->pe_on_disk.base = _next_base(&pvd->lv_on_disk);
73 pvd->pe_on_disk.size = pvd->pe_total * sizeof(struct pe_disk);
74 }
75
76 static int _check_vg_limits(struct disk_list *dl)
77 {
78 if (dl->vgd.lv_max > MAX_LV) {
79 log_error("MaxLogicalVolumes of %d exceeds format limit of %d "
80 "for VG '%s'", dl->vgd.lv_max, MAX_LV - 1,
81 dl->pvd.vg_name);
82 return 0;
83 }
84
85 if (dl->vgd.pv_max > MAX_PV) {
86 log_error("MaxPhysicalVolumes of %d exceeds format limit of %d "
87 "for VG '%s'", dl->vgd.pv_max, MAX_PV - 1,
88 dl->pvd.vg_name);
89 return 0;
90 }
91
92 return 1;
93 }
94
95 /*
96 * This assumes pe_count and pe_start have already
97 * been calculated correctly.
98 */
99 int calculate_layout(struct disk_list *dl)
100 {
101 struct pv_disk *pvd = &dl->pvd;
102
103 _calc_simple_layout(pvd);
104 if (!_adjust_pe_on_disk(pvd)) {
105 log_error("Insufficient space for metadata and PE's.");
106 return 0;
107 }
108
109 if (!_check_vg_limits(dl))
110 return 0;
111
112 return 1;
113 }
114
115 /*
116 * The number of extents that can fit on a disk is metadata format dependant.
117 * pe_start is any existing value for pe_start
118 */
119 int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
120 uint32_t max_extent_count, uint64_t pe_start)
121 {
122 struct pv_disk *pvd = dm_malloc(sizeof(*pvd));
123 uint32_t end;
124
125 if (!pvd)
126 return_0;
127
128 /*
129 * Guess how many extents will fit, bearing in mind that
130 * one is going to be knocked off at the start of the
131 * next loop.
132 */
133 if (max_extent_count)
134 pvd->pe_total = max_extent_count + 1;
135 else
136 pvd->pe_total = (pv->size / extent_size);
137
138 if (pvd->pe_total < PE_SIZE_PV_SIZE_REL) {
139 log_error("Too few extents on %s. Try smaller extent size.",
140 pv_dev_name(pv));
141 dm_free(pvd);
142 return 0;
143 }
144
145 do {
146 pvd->pe_total--;
147 _calc_simple_layout(pvd);
148 end = ((pvd->pe_on_disk.base + pvd->pe_on_disk.size +
149 SECTOR_SIZE - 1) >> SECTOR_SHIFT);
150
151 if (pe_start && end < pe_start)
152 end = pe_start;
153
154 pvd->pe_start = _round_up(end, LVM1_PE_ALIGN);
155
156 } while ((pvd->pe_start + (pvd->pe_total * extent_size))
157 > pv->size);
158
159 if (pvd->pe_total > MAX_PE_TOTAL) {
160 log_error("Metadata extent limit (%u) exceeded for %s - "
161 "%u required", MAX_PE_TOTAL, pv_dev_name(pv),
162 pvd->pe_total);
163 dm_free(pvd);
164 return 0;
165 }
166
167 pv->pe_count = pvd->pe_total;
168 pv->pe_start = pvd->pe_start;
169 /* We can't set pe_size here without breaking LVM1 compatibility */
170 dm_free(pvd);
171 return 1;
172 }
This page took 0.041193 seconds and 5 git commands to generate.