Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 1997-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 "label.h"
18 : : #include "metadata.h"
19 : : #include "limits.h"
20 : : #include "display.h"
21 : : #include "toolcontext.h"
22 : : #include "lvmcache.h"
23 : : #include "disk_rep.h"
24 : : #include "format_pool.h"
25 : : #include "pool_label.h"
26 : :
27 : : /* Must be called after pvs are imported */
28 : 0 : static struct user_subpool *_build_usp(struct dm_list *pls, struct dm_pool *mem,
29 : : int *sps)
30 : : {
31 : : struct pool_list *pl;
32 : 0 : struct user_subpool *usp = NULL, *cur_sp = NULL;
33 : 0 : struct user_device *cur_dev = NULL;
34 : :
35 : : /*
36 : : * FIXME: Need to do some checks here - I'm tempted to add a
37 : : * user_pool structure and build the entire thing to check against.
38 : : */
39 [ # # ]: 0 : dm_list_iterate_items(pl, pls) {
40 : 0 : *sps = pl->pd.pl_subpools;
41 [ # # ][ # # ]: 0 : if (!usp && (!(usp = dm_pool_zalloc(mem, sizeof(*usp) * (*sps))))) {
42 : 0 : log_error("Unable to allocate %d subpool structures",
43 : : *sps);
44 : 0 : return 0;
45 : : }
46 : :
47 [ # # ]: 0 : if (cur_sp != &usp[pl->pd.pl_sp_id]) {
48 : 0 : cur_sp = &usp[pl->pd.pl_sp_id];
49 : :
50 : 0 : cur_sp->id = pl->pd.pl_sp_id;
51 : 0 : cur_sp->striping = pl->pd.pl_striping;
52 : 0 : cur_sp->num_devs = pl->pd.pl_sp_devs;
53 : 0 : cur_sp->type = pl->pd.pl_sp_type;
54 : 0 : cur_sp->initialized = 1;
55 : : }
56 : :
57 [ # # # # ]: 0 : if (!cur_sp->devs &&
58 : 0 : (!(cur_sp->devs =
59 : 0 : dm_pool_zalloc(mem,
60 : : sizeof(*usp->devs) * pl->pd.pl_sp_devs)))) {
61 : :
62 : 0 : log_error("Unable to allocate %d pool_device "
63 : : "structures", pl->pd.pl_sp_devs);
64 : 0 : return 0;
65 : : }
66 : :
67 : 0 : cur_dev = &cur_sp->devs[pl->pd.pl_sp_devid];
68 : 0 : cur_dev->sp_id = cur_sp->id;
69 : 0 : cur_dev->devid = pl->pd.pl_sp_id;
70 : 0 : cur_dev->blocks = pl->pd.pl_blocks;
71 : 0 : cur_dev->pv = pl->pv;
72 : 0 : cur_dev->initialized = 1;
73 : : }
74 : :
75 : 0 : return usp;
76 : : }
77 : :
78 : 0 : static int _check_usp(char *vgname, struct user_subpool *usp, int sp_count)
79 : : {
80 : : int i;
81 : : unsigned j;
82 : :
83 [ # # ]: 0 : for (i = 0; i < sp_count; i++) {
84 [ # # ]: 0 : if (!usp[i].initialized) {
85 : 0 : log_error("Missing subpool %d in pool %s", i, vgname);
86 : 0 : return 0;
87 : : }
88 [ # # ]: 0 : for (j = 0; j < usp[i].num_devs; j++) {
89 [ # # ]: 0 : if (!usp[i].devs[j].initialized) {
90 : 0 : log_error("Missing device %u for subpool %d"
91 : : " in pool %s", j, i, vgname);
92 : 0 : return 0;
93 : : }
94 : :
95 : : }
96 : : }
97 : :
98 : 0 : return 1;
99 : : }
100 : :
101 : 0 : static struct volume_group *_build_vg_from_pds(struct format_instance
102 : : *fid, struct dm_pool *mem,
103 : : struct dm_list *pds)
104 : : {
105 : 0 : struct dm_pool *smem = fid->fmt->cmd->mem;
106 : 0 : struct volume_group *vg = NULL;
107 : 0 : struct user_subpool *usp = NULL;
108 : : int sp_count;
109 : :
110 [ # # ]: 0 : if (!(vg = dm_pool_zalloc(smem, sizeof(*vg)))) {
111 : 0 : log_error("Unable to allocate volume group structure");
112 : 0 : return NULL;
113 : : }
114 : :
115 : 0 : vg->cmd = fid->fmt->cmd;
116 : 0 : vg->vgmem = mem;
117 : 0 : vg->fid = fid;
118 : 0 : vg->name = NULL;
119 : 0 : vg->status = 0;
120 : 0 : vg->extent_count = 0;
121 : 0 : vg->pv_count = 0;
122 : 0 : vg->seqno = 1;
123 : 0 : vg->system_id = NULL;
124 : 0 : dm_list_init(&vg->pvs);
125 : 0 : dm_list_init(&vg->lvs);
126 : 0 : dm_list_init(&vg->tags);
127 : 0 : dm_list_init(&vg->removed_pvs);
128 : :
129 [ # # ]: 0 : if (!import_pool_vg(vg, smem, pds))
130 : 0 : return_NULL;
131 : :
132 [ # # ]: 0 : if (!import_pool_pvs(fid->fmt, vg, &vg->pvs, smem, pds))
133 : 0 : return_NULL;
134 : :
135 [ # # ]: 0 : if (!import_pool_lvs(vg, smem, pds))
136 : 0 : return_NULL;
137 : :
138 : : /*
139 : : * I need an intermediate subpool structure that contains all the
140 : : * relevant info for this. Then i can iterate through the subpool
141 : : * structures for checking, and create the segments
142 : : */
143 [ # # ]: 0 : if (!(usp = _build_usp(pds, mem, &sp_count)))
144 : 0 : return_NULL;
145 : :
146 : : /*
147 : : * check the subpool structures - we can't handle partial VGs in
148 : : * the pool format, so this will error out if we're missing PVs
149 : : */
150 [ # # ]: 0 : if (!_check_usp(vg->name, usp, sp_count))
151 : 0 : return_NULL;
152 : :
153 [ # # ]: 0 : if (!import_pool_segments(&vg->lvs, smem, usp, sp_count))
154 : 0 : return_NULL;
155 : :
156 : 0 : return vg;
157 : : }
158 : :
159 : 0 : static struct volume_group *_pool_vg_read(struct format_instance *fid,
160 : : const char *vg_name,
161 : : struct metadata_area *mda __attribute((unused)))
162 : : {
163 : 0 : struct dm_pool *mem = dm_pool_create("pool vg_read", VG_MEMPOOL_CHUNK);
164 : : struct dm_list pds;
165 : 0 : struct volume_group *vg = NULL;
166 : :
167 : 0 : dm_list_init(&pds);
168 : :
169 : : /* We can safely ignore the mda passed in */
170 : :
171 [ # # ]: 0 : if (!mem)
172 : 0 : return_NULL;
173 : :
174 : : /* Strip dev_dir if present */
175 : 0 : vg_name = strip_dir(vg_name, fid->fmt->cmd->dev_dir);
176 : :
177 : : /* Read all the pvs in the vg */
178 [ # # ]: 0 : if (!read_pool_pds(fid->fmt, vg_name, mem, &pds))
179 : 0 : goto_out;
180 : :
181 : : /* Do the rest of the vg stuff */
182 [ # # ]: 0 : if (!(vg = _build_vg_from_pds(fid, mem, &pds)))
183 : 0 : goto_out;
184 : :
185 : 0 : return vg;
186 : : out:
187 : 0 : dm_pool_destroy(mem);
188 : 0 : return NULL;
189 : : }
190 : :
191 : 0 : static int _pool_pv_setup(const struct format_type *fmt __attribute((unused)),
192 : : uint64_t pe_start __attribute((unused)),
193 : : uint32_t extent_count __attribute((unused)),
194 : : uint32_t extent_size __attribute((unused)),
195 : : unsigned long data_alignment __attribute((unused)),
196 : : unsigned long data_alignment_offset __attribute((unused)),
197 : : int pvmetadatacopies __attribute((unused)),
198 : : uint64_t pvmetadatasize __attribute((unused)),
199 : : struct dm_list *mdas __attribute((unused)),
200 : : struct physical_volume *pv __attribute((unused)),
201 : : struct volume_group *vg __attribute((unused)))
202 : : {
203 : 0 : return 1;
204 : : }
205 : :
206 : 0 : static int _pool_pv_read(const struct format_type *fmt, const char *pv_name,
207 : : struct physical_volume *pv,
208 : : struct dm_list *mdas __attribute((unused)),
209 : : int scan_label_only __attribute((unused)))
210 : : {
211 : 0 : struct dm_pool *mem = dm_pool_create("pool pv_read", 1024);
212 : : struct pool_list *pl;
213 : : struct device *dev;
214 : 0 : int r = 0;
215 : :
216 : 0 : log_very_verbose("Reading physical volume data %s from disk", pv_name);
217 : :
218 [ # # ]: 0 : if (!mem)
219 : 0 : return_0;
220 : :
221 [ # # ]: 0 : if (!(dev = dev_cache_get(pv_name, fmt->cmd->filter)))
222 : 0 : goto_out;
223 : :
224 : : /*
225 : : * I need to read the disk and populate a pv structure here
226 : : * I'll probably need to abstract some of this later for the
227 : : * vg_read code
228 : : */
229 [ # # ]: 0 : if (!(pl = read_pool_disk(fmt, dev, mem, NULL)))
230 : 0 : goto_out;
231 : :
232 [ # # ]: 0 : if (!import_pool_pv(fmt, fmt->cmd->mem, NULL, pv, pl))
233 : 0 : goto_out;
234 : :
235 : 0 : pv->fmt = fmt;
236 : :
237 : 0 : r = 1;
238 : :
239 : : out:
240 : 0 : dm_pool_destroy(mem);
241 : 0 : return r;
242 : : }
243 : :
244 : : /* *INDENT-OFF* */
245 : : static struct metadata_area_ops _metadata_format_pool_ops = {
246 : : .vg_read = _pool_vg_read,
247 : : };
248 : : /* *INDENT-ON* */
249 : :
250 : 1 : static struct format_instance *_pool_create_instance(const struct format_type *fmt,
251 : : const char *vgname __attribute((unused)),
252 : : const char *vgid __attribute((unused)),
253 : : void *private __attribute((unused)))
254 : : {
255 : : struct format_instance *fid;
256 : : struct metadata_area *mda;
257 : :
258 [ - + ]: 1 : if (!(fid = dm_pool_zalloc(fmt->cmd->mem, sizeof(*fid)))) {
259 : 0 : log_error("Unable to allocate format instance structure for "
260 : : "pool format");
261 : 0 : return NULL;
262 : : }
263 : :
264 : 1 : fid->fmt = fmt;
265 : 1 : dm_list_init(&fid->metadata_areas);
266 : :
267 : : /* Define a NULL metadata area */
268 [ - + ]: 1 : if (!(mda = dm_pool_zalloc(fmt->cmd->mem, sizeof(*mda)))) {
269 : 0 : log_error("Unable to allocate metadata area structure "
270 : : "for pool format");
271 : 0 : dm_pool_free(fmt->cmd->mem, fid);
272 : 0 : return NULL;
273 : : }
274 : :
275 : 1 : mda->ops = &_metadata_format_pool_ops;
276 : 1 : mda->metadata_locn = NULL;
277 : 1 : dm_list_add(&fid->metadata_areas, &mda->list);
278 : :
279 : 1 : return fid;
280 : : }
281 : :
282 : 0 : static void _pool_destroy_instance(struct format_instance *fid __attribute((unused)))
283 : : {
284 : 0 : }
285 : :
286 : 3 : static void _pool_destroy(const struct format_type *fmt)
287 : : {
288 : 3 : dm_free((void *) fmt);
289 : 3 : }
290 : :
291 : : /* *INDENT-OFF* */
292 : : static struct format_handler _format_pool_ops = {
293 : : .pv_read = _pool_pv_read,
294 : : .pv_setup = _pool_pv_setup,
295 : : .create_instance = _pool_create_instance,
296 : : .destroy_instance = _pool_destroy_instance,
297 : : .destroy = _pool_destroy,
298 : : };
299 : : /* *INDENT-ON */
300 : :
301 : : #ifdef POOL_INTERNAL
302 : 3 : struct format_type *init_pool_format(struct cmd_context *cmd)
303 : : #else /* Shared */
304 : : struct format_type *init_format(struct cmd_context *cmd);
305 : : struct format_type *init_format(struct cmd_context *cmd)
306 : : #endif
307 : : {
308 : 3 : struct format_type *fmt = dm_malloc(sizeof(*fmt));
309 : :
310 [ - + ]: 3 : if (!fmt) {
311 : 0 : log_error("Unable to allocate format type structure for pool "
312 : : "format");
313 : 0 : return NULL;
314 : : }
315 : :
316 : 3 : fmt->cmd = cmd;
317 : 3 : fmt->ops = &_format_pool_ops;
318 : 3 : fmt->name = FMT_POOL_NAME;
319 : 3 : fmt->alias = NULL;
320 : 3 : fmt->orphan_vg_name = FMT_POOL_ORPHAN_VG_NAME;
321 : 3 : fmt->features = 0;
322 : 3 : fmt->private = NULL;
323 : :
324 [ - + ]: 3 : if (!(fmt->labeller = pool_labeller_create(fmt))) {
325 : 0 : log_error("Couldn't create pool label handler.");
326 : 0 : return NULL;
327 : : }
328 : :
329 [ - + ]: 3 : if (!(label_register_handler(FMT_POOL_NAME, fmt->labeller))) {
330 : 0 : log_error("Couldn't register pool label handler.");
331 : 0 : return NULL;
332 : : }
333 : :
334 : 3 : log_very_verbose("Initialised format: %s", fmt->name);
335 : :
336 : 3 : return fmt;
337 : : }
|