Branch data Line data Source code
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 : 0 : static uint32_t _round_up(uint32_t n, uint32_t size)
23 : : {
24 : 0 : size--;
25 : 0 : 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 : 0 : static uint32_t _next_base(struct data_area *area)
40 : : {
41 : 0 : return _round_up(area->base + area->size, METADATA_ALIGN);
42 : : }
43 : :
44 : : /*
45 : : * Quick calculation based on pe_start.
46 : : */
47 : 0 : static int _adjust_pe_on_disk(struct pv_disk *pvd)
48 : : {
49 : 0 : uint32_t pe_start = pvd->pe_start << SECTOR_SHIFT;
50 : :
51 [ # # ]: 0 : if (pe_start < pvd->pe_on_disk.base + pvd->pe_on_disk.size)
52 : 0 : return 0;
53 : :
54 : 0 : pvd->pe_on_disk.size = pe_start - pvd->pe_on_disk.base;
55 : 0 : return 1;
56 : : }
57 : :
58 : 0 : static void _calc_simple_layout(struct pv_disk *pvd)
59 : : {
60 : 0 : pvd->pv_on_disk.base = METADATA_BASE;
61 : 0 : pvd->pv_on_disk.size = PV_SIZE;
62 : :
63 : 0 : pvd->vg_on_disk.base = _next_base(&pvd->pv_on_disk);
64 : 0 : pvd->vg_on_disk.size = VG_SIZE;
65 : :
66 : 0 : pvd->pv_uuidlist_on_disk.base = _next_base(&pvd->vg_on_disk);
67 : 0 : pvd->pv_uuidlist_on_disk.size = MAX_PV * NAME_LEN;
68 : :
69 : 0 : pvd->lv_on_disk.base = _next_base(&pvd->pv_uuidlist_on_disk);
70 : 0 : pvd->lv_on_disk.size = MAX_LV * sizeof(struct lv_disk);
71 : :
72 : 0 : pvd->pe_on_disk.base = _next_base(&pvd->lv_on_disk);
73 : 0 : pvd->pe_on_disk.size = pvd->pe_total * sizeof(struct pe_disk);
74 : 0 : }
75 : :
76 : 0 : static int _check_vg_limits(struct disk_list *dl)
77 : : {
78 [ # # ]: 0 : if (dl->vgd.lv_max > MAX_LV) {
79 : 0 : 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 : 0 : return 0;
83 : : }
84 : :
85 [ # # ]: 0 : if (dl->vgd.pv_max > MAX_PV) {
86 : 0 : 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 : 0 : return 0;
90 : : }
91 : :
92 : 0 : return 1;
93 : : }
94 : :
95 : : /*
96 : : * This assumes pe_count and pe_start have already
97 : : * been calculated correctly.
98 : : */
99 : 0 : int calculate_layout(struct disk_list *dl)
100 : : {
101 : 0 : struct pv_disk *pvd = &dl->pvd;
102 : :
103 : 0 : _calc_simple_layout(pvd);
104 [ # # ]: 0 : if (!_adjust_pe_on_disk(pvd)) {
105 : 0 : log_error("Insufficient space for metadata and PE's.");
106 : 0 : return 0;
107 : : }
108 : :
109 [ # # ]: 0 : if (!_check_vg_limits(dl))
110 : 0 : return 0;
111 : :
112 : 0 : 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 : 0 : int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
120 : : uint32_t max_extent_count, uint64_t pe_start)
121 : : {
122 : 0 : struct pv_disk *pvd = dm_malloc(sizeof(*pvd));
123 : : uint32_t end;
124 : :
125 [ # # ]: 0 : if (!pvd)
126 : 0 : 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 [ # # ]: 0 : if (max_extent_count)
134 : 0 : pvd->pe_total = max_extent_count + 1;
135 : : else
136 : 0 : pvd->pe_total = (pv->size / extent_size);
137 : :
138 [ # # ]: 0 : if (pvd->pe_total < PE_SIZE_PV_SIZE_REL) {
139 : 0 : log_error("Too few extents on %s. Try smaller extent size.",
140 : : pv_dev_name(pv));
141 : 0 : dm_free(pvd);
142 : 0 : return 0;
143 : : }
144 : :
145 : : do {
146 : 0 : pvd->pe_total--;
147 : 0 : _calc_simple_layout(pvd);
148 : 0 : end = ((pvd->pe_on_disk.base + pvd->pe_on_disk.size +
149 : : SECTOR_SIZE - 1) >> SECTOR_SHIFT);
150 : :
151 [ # # # # ]: 0 : if (pe_start && end < pe_start)
152 : 0 : end = pe_start;
153 : :
154 : 0 : pvd->pe_start = _round_up(end, LVM1_PE_ALIGN);
155 : :
156 : 0 : } while ((pvd->pe_start + (pvd->pe_total * extent_size))
157 [ # # ]: 0 : > pv->size);
158 : :
159 [ # # ]: 0 : if (pvd->pe_total > MAX_PE_TOTAL) {
160 : 0 : log_error("Metadata extent limit (%u) exceeded for %s - "
161 : : "%u required", MAX_PE_TOTAL, pv_dev_name(pv),
162 : : pvd->pe_total);
163 : 0 : dm_free(pvd);
164 : 0 : return 0;
165 : : }
166 : :
167 : 0 : pv->pe_count = pvd->pe_total;
168 : 0 : pv->pe_start = pvd->pe_start;
169 : : /* We can't set pe_size here without breaking LVM1 compatibility */
170 : 0 : dm_free(pvd);
171 : 0 : return 1;
172 : : }
|