Sync usage with man page.
[netbsd-mini2440.git] / external / gpl2 / lvm2 / dist / lib / format1 / layout.c
blobd7ae7b546864514e22d7af5a46069b42c47adf33
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU Lesser General Public License v.2.1.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #include "lib.h"
19 #include "disk-rep.h"
22 * Only works with powers of 2.
24 static uint32_t _round_up(uint32_t n, uint32_t size)
26 size--;
27 return (n + size) & ~size;
30 /* Unused.
31 static uint32_t _div_up(uint32_t n, uint32_t size)
33 return _round_up(n, size) / size;
38 * Each chunk of metadata should be aligned to
39 * METADATA_ALIGN.
41 static uint32_t _next_base(struct data_area *area)
43 return _round_up(area->base + area->size, METADATA_ALIGN);
47 * Quick calculation based on pe_start.
49 static int _adjust_pe_on_disk(struct pv_disk *pvd)
51 uint32_t pe_start = pvd->pe_start << SECTOR_SHIFT;
53 if (pe_start < pvd->pe_on_disk.base + pvd->pe_on_disk.size)
54 return 0;
56 pvd->pe_on_disk.size = pe_start - pvd->pe_on_disk.base;
57 return 1;
60 static void _calc_simple_layout(struct pv_disk *pvd)
62 pvd->pv_on_disk.base = METADATA_BASE;
63 pvd->pv_on_disk.size = PV_SIZE;
65 pvd->vg_on_disk.base = _next_base(&pvd->pv_on_disk);
66 pvd->vg_on_disk.size = VG_SIZE;
68 pvd->pv_uuidlist_on_disk.base = _next_base(&pvd->vg_on_disk);
69 pvd->pv_uuidlist_on_disk.size = MAX_PV * NAME_LEN;
71 pvd->lv_on_disk.base = _next_base(&pvd->pv_uuidlist_on_disk);
72 pvd->lv_on_disk.size = MAX_LV * sizeof(struct lv_disk);
74 pvd->pe_on_disk.base = _next_base(&pvd->lv_on_disk);
75 pvd->pe_on_disk.size = pvd->pe_total * sizeof(struct pe_disk);
78 static int _check_vg_limits(struct disk_list *dl)
80 if (dl->vgd.lv_max > MAX_LV) {
81 log_error("MaxLogicalVolumes of %d exceeds format limit of %d "
82 "for VG '%s'", dl->vgd.lv_max, MAX_LV - 1,
83 dl->pvd.vg_name);
84 return 0;
87 if (dl->vgd.pv_max > MAX_PV) {
88 log_error("MaxPhysicalVolumes of %d exceeds format limit of %d "
89 "for VG '%s'", dl->vgd.pv_max, MAX_PV - 1,
90 dl->pvd.vg_name);
91 return 0;
94 return 1;
98 * This assumes pe_count and pe_start have already
99 * been calculated correctly.
101 int calculate_layout(struct disk_list *dl)
103 struct pv_disk *pvd = &dl->pvd;
105 _calc_simple_layout(pvd);
106 if (!_adjust_pe_on_disk(pvd)) {
107 log_error("Insufficient space for metadata and PE's.");
108 return 0;
111 if (!_check_vg_limits(dl))
112 return 0;
114 return 1;
118 * The number of extents that can fit on a disk is metadata format dependant.
119 * pe_start is any existing value for pe_start
121 int calculate_extent_count(struct physical_volume *pv, uint32_t extent_size,
122 uint32_t max_extent_count, uint64_t pe_start)
124 struct pv_disk *pvd = dm_malloc(sizeof(*pvd));
125 uint32_t end;
127 if (!pvd)
128 return_0;
131 * Guess how many extents will fit, bearing in mind that
132 * one is going to be knocked off at the start of the
133 * next loop.
135 if (max_extent_count)
136 pvd->pe_total = max_extent_count + 1;
137 else
138 pvd->pe_total = (pv->size / extent_size);
140 if (pvd->pe_total < PE_SIZE_PV_SIZE_REL) {
141 log_error("Too few extents on %s. Try smaller extent size.",
142 pv_dev_name(pv));
143 dm_free(pvd);
144 return 0;
147 do {
148 pvd->pe_total--;
149 _calc_simple_layout(pvd);
150 end = ((pvd->pe_on_disk.base + pvd->pe_on_disk.size +
151 SECTOR_SIZE - 1) >> SECTOR_SHIFT);
153 if (pe_start && end < pe_start)
154 end = pe_start;
156 pvd->pe_start = _round_up(end, LVM1_PE_ALIGN);
158 } while ((pvd->pe_start + (pvd->pe_total * extent_size))
159 > pv->size);
161 if (pvd->pe_total > MAX_PE_TOTAL) {
162 log_error("Metadata extent limit (%u) exceeded for %s - "
163 "%u required", MAX_PE_TOTAL, pv_dev_name(pv),
164 pvd->pe_total);
165 dm_free(pvd);
166 return 0;
169 pv->pe_count = pvd->pe_total;
170 pv->pe_start = pvd->pe_start;
171 /* We can't set pe_size here without breaking LVM1 compatibility */
172 dm_free(pvd);
173 return 1;