1*86d7f5d3SJohn Marino /* $NetBSD: layout.c,v 1.1.1.1 2008/12/22 00:18:00 haad Exp $ */
2*86d7f5d3SJohn Marino
3*86d7f5d3SJohn Marino /*
4*86d7f5d3SJohn Marino * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5*86d7f5d3SJohn Marino * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
6*86d7f5d3SJohn Marino *
7*86d7f5d3SJohn Marino * This file is part of LVM2.
8*86d7f5d3SJohn Marino *
9*86d7f5d3SJohn Marino * This copyrighted material is made available to anyone wishing to use,
10*86d7f5d3SJohn Marino * modify, copy, or redistribute it subject to the terms and conditions
11*86d7f5d3SJohn Marino * of the GNU Lesser General Public License v.2.1.
12*86d7f5d3SJohn Marino *
13*86d7f5d3SJohn Marino * You should have received a copy of the GNU Lesser General Public License
14*86d7f5d3SJohn Marino * along with this program; if not, write to the Free Software Foundation,
15*86d7f5d3SJohn Marino * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16*86d7f5d3SJohn Marino */
17*86d7f5d3SJohn Marino
18*86d7f5d3SJohn Marino #include "lib.h"
19*86d7f5d3SJohn Marino #include "disk-rep.h"
20*86d7f5d3SJohn Marino
21*86d7f5d3SJohn Marino /*
22*86d7f5d3SJohn Marino * Only works with powers of 2.
23*86d7f5d3SJohn Marino */
_round_up(uint32_t n,uint32_t size)24*86d7f5d3SJohn Marino static uint32_t _round_up(uint32_t n, uint32_t size)
25*86d7f5d3SJohn Marino {
26*86d7f5d3SJohn Marino size--;
27*86d7f5d3SJohn Marino return (n + size) & ~size;
28*86d7f5d3SJohn Marino }
29*86d7f5d3SJohn Marino
30*86d7f5d3SJohn Marino /* Unused.
31*86d7f5d3SJohn Marino static uint32_t _div_up(uint32_t n, uint32_t size)
32*86d7f5d3SJohn Marino {
33*86d7f5d3SJohn Marino return _round_up(n, size) / size;
34*86d7f5d3SJohn Marino }
35*86d7f5d3SJohn Marino */
36*86d7f5d3SJohn Marino
37*86d7f5d3SJohn Marino /*
38*86d7f5d3SJohn Marino * Each chunk of metadata should be aligned to
39*86d7f5d3SJohn Marino * METADATA_ALIGN.
40*86d7f5d3SJohn Marino */
_next_base(struct data_area * area)41*86d7f5d3SJohn Marino static uint32_t _next_base(struct data_area *area)
42*86d7f5d3SJohn Marino {
43*86d7f5d3SJohn Marino return _round_up(area->base + area->size, METADATA_ALIGN);
44*86d7f5d3SJohn Marino }
45*86d7f5d3SJohn Marino
46*86d7f5d3SJohn Marino /*
47*86d7f5d3SJohn Marino * Quick calculation based on pe_start.
48*86d7f5d3SJohn Marino */
_adjust_pe_on_disk(struct pv_disk * pvd)49*86d7f5d3SJohn Marino static int _adjust_pe_on_disk(struct pv_disk *pvd)
50*86d7f5d3SJohn Marino {
51*86d7f5d3SJohn Marino uint32_t pe_start = pvd->pe_start << SECTOR_SHIFT;
52*86d7f5d3SJohn Marino
53*86d7f5d3SJohn Marino if (pe_start < pvd->pe_on_disk.base + pvd->pe_on_disk.size)
54*86d7f5d3SJohn Marino return 0;
55*86d7f5d3SJohn Marino
56*86d7f5d3SJohn Marino pvd->pe_on_disk.size = pe_start - pvd->pe_on_disk.base;
57*86d7f5d3SJohn Marino return 1;
58*86d7f5d3SJohn Marino }
59*86d7f5d3SJohn Marino
_calc_simple_layout(struct pv_disk * pvd)60*86d7f5d3SJohn Marino static void _calc_simple_layout(struct pv_disk *pvd)
61*86d7f5d3SJohn Marino {
62*86d7f5d3SJohn Marino pvd->pv_on_disk.base = METADATA_BASE;
63*86d7f5d3SJohn Marino pvd->pv_on_disk.size = PV_SIZE;
64*86d7f5d3SJohn Marino
65*86d7f5d3SJohn Marino pvd->vg_on_disk.base = _next_base(&pvd->pv_on_disk);
66*86d7f5d3SJohn Marino pvd->vg_on_disk.size = VG_SIZE;
67*86d7f5d3SJohn Marino
68*86d7f5d3SJohn Marino pvd->pv_uuidlist_on_disk.base = _next_base(&pvd->vg_on_disk);
69*86d7f5d3SJohn Marino pvd->pv_uuidlist_on_disk.size = MAX_PV * NAME_LEN;
70*86d7f5d3SJohn Marino
71*86d7f5d3SJohn Marino pvd->lv_on_disk.base = _next_base(&pvd->pv_uuidlist_on_disk);
72*86d7f5d3SJohn Marino pvd->lv_on_disk.size = MAX_LV * sizeof(struct lv_disk);
73*86d7f5d3SJohn Marino
74*86d7f5d3SJohn Marino pvd->pe_on_disk.base = _next_base(&pvd->lv_on_disk);
75*86d7f5d3SJohn Marino pvd->pe_on_disk.size = pvd->pe_total * sizeof(struct pe_disk);
76*86d7f5d3SJohn Marino }
77*86d7f5d3SJohn Marino
_check_vg_limits(struct disk_list * dl)78*86d7f5d3SJohn Marino static int _check_vg_limits(struct disk_list *dl)
79*86d7f5d3SJohn Marino {
80*86d7f5d3SJohn Marino if (dl->vgd.lv_max > MAX_LV) {
81*86d7f5d3SJohn Marino log_error("MaxLogicalVolumes of %d exceeds format limit of %d "
82*86d7f5d3SJohn Marino "for VG '%s'", dl->vgd.lv_max, MAX_LV - 1,
83*86d7f5d3SJohn Marino dl->pvd.vg_name);
84*86d7f5d3SJohn Marino return 0;
85*86d7f5d3SJohn Marino }
86*86d7f5d3SJohn Marino
87*86d7f5d3SJohn Marino if (dl->vgd.pv_max > MAX_PV) {
88*86d7f5d3SJohn Marino log_error("MaxPhysicalVolumes of %d exceeds format limit of %d "
89*86d7f5d3SJohn Marino "for VG '%s'", dl->vgd.pv_max, MAX_PV - 1,
90*86d7f5d3SJohn Marino dl->pvd.vg_name);
91*86d7f5d3SJohn Marino return 0;
92*86d7f5d3SJohn Marino }
93*86d7f5d3SJohn Marino
94*86d7f5d3SJohn Marino return 1;
95*86d7f5d3SJohn Marino }
96*86d7f5d3SJohn Marino
97*86d7f5d3SJohn Marino /*
98*86d7f5d3SJohn Marino * This assumes pe_count and pe_start have already
99*86d7f5d3SJohn Marino * been calculated correctly.
100*86d7f5d3SJohn Marino */
calculate_layout(struct disk_list * dl)101*86d7f5d3SJohn Marino int calculate_layout(struct disk_list *dl)
102*86d7f5d3SJohn Marino {
103*86d7f5d3SJohn Marino struct pv_disk *pvd = &dl->pvd;
104*86d7f5d3SJohn Marino
105*86d7f5d3SJohn Marino _calc_simple_layout(pvd);
106*86d7f5d3SJohn Marino if (!_adjust_pe_on_disk(pvd)) {
107*86d7f5d3SJohn Marino log_error("Insufficient space for metadata and PE's.");
108*86d7f5d3SJohn Marino return 0;
109*86d7f5d3SJohn Marino }
110*86d7f5d3SJohn Marino
111*86d7f5d3SJohn Marino if (!_check_vg_limits(dl))
112*86d7f5d3SJohn Marino return 0;
113*86d7f5d3SJohn Marino
114*86d7f5d3SJohn Marino return 1;
115*86d7f5d3SJohn Marino }
116*86d7f5d3SJohn Marino
117*86d7f5d3SJohn Marino /*
118*86d7f5d3SJohn Marino * The number of extents that can fit on a disk is metadata format dependant.
119*86d7f5d3SJohn Marino * pe_start is any existing value for pe_start
120*86d7f5d3SJohn Marino */
calculate_extent_count(struct physical_volume * pv,uint32_t extent_size,uint32_t max_extent_count,uint64_t pe_start)121*86d7f5d3SJohn Marino int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
122*86d7f5d3SJohn Marino uint32_t max_extent_count, uint64_t pe_start)
123*86d7f5d3SJohn Marino {
124*86d7f5d3SJohn Marino struct pv_disk *pvd = dm_malloc(sizeof(*pvd));
125*86d7f5d3SJohn Marino uint32_t end;
126*86d7f5d3SJohn Marino
127*86d7f5d3SJohn Marino if (!pvd)
128*86d7f5d3SJohn Marino return_0;
129*86d7f5d3SJohn Marino
130*86d7f5d3SJohn Marino /*
131*86d7f5d3SJohn Marino * Guess how many extents will fit, bearing in mind that
132*86d7f5d3SJohn Marino * one is going to be knocked off at the start of the
133*86d7f5d3SJohn Marino * next loop.
134*86d7f5d3SJohn Marino */
135*86d7f5d3SJohn Marino if (max_extent_count)
136*86d7f5d3SJohn Marino pvd->pe_total = max_extent_count + 1;
137*86d7f5d3SJohn Marino else
138*86d7f5d3SJohn Marino pvd->pe_total = (pv->size / extent_size);
139*86d7f5d3SJohn Marino
140*86d7f5d3SJohn Marino if (pvd->pe_total < PE_SIZE_PV_SIZE_REL) {
141*86d7f5d3SJohn Marino log_error("Too few extents on %s. Try smaller extent size.",
142*86d7f5d3SJohn Marino pv_dev_name(pv));
143*86d7f5d3SJohn Marino dm_free(pvd);
144*86d7f5d3SJohn Marino return 0;
145*86d7f5d3SJohn Marino }
146*86d7f5d3SJohn Marino
147*86d7f5d3SJohn Marino do {
148*86d7f5d3SJohn Marino pvd->pe_total--;
149*86d7f5d3SJohn Marino _calc_simple_layout(pvd);
150*86d7f5d3SJohn Marino end = ((pvd->pe_on_disk.base + pvd->pe_on_disk.size +
151*86d7f5d3SJohn Marino SECTOR_SIZE - 1) >> SECTOR_SHIFT);
152*86d7f5d3SJohn Marino
153*86d7f5d3SJohn Marino if (pe_start && end < pe_start)
154*86d7f5d3SJohn Marino end = pe_start;
155*86d7f5d3SJohn Marino
156*86d7f5d3SJohn Marino pvd->pe_start = _round_up(end, LVM1_PE_ALIGN);
157*86d7f5d3SJohn Marino
158*86d7f5d3SJohn Marino } while ((pvd->pe_start + (pvd->pe_total * extent_size))
159*86d7f5d3SJohn Marino > pv->size);
160*86d7f5d3SJohn Marino
161*86d7f5d3SJohn Marino if (pvd->pe_total > MAX_PE_TOTAL) {
162*86d7f5d3SJohn Marino log_error("Metadata extent limit (%u) exceeded for %s - "
163*86d7f5d3SJohn Marino "%u required", MAX_PE_TOTAL, pv_dev_name(pv),
164*86d7f5d3SJohn Marino pvd->pe_total);
165*86d7f5d3SJohn Marino dm_free(pvd);
166*86d7f5d3SJohn Marino return 0;
167*86d7f5d3SJohn Marino }
168*86d7f5d3SJohn Marino
169*86d7f5d3SJohn Marino pv->pe_count = pvd->pe_total;
170*86d7f5d3SJohn Marino pv->pe_start = pvd->pe_start;
171*86d7f5d3SJohn Marino /* We can't set pe_size here without breaking LVM1 compatibility */
172*86d7f5d3SJohn Marino dm_free(pvd);
173*86d7f5d3SJohn Marino return 1;
174*86d7f5d3SJohn Marino }
175