1 /*	$NetBSD: import_export.c,v 1.1.1.2 2009/12/02 00:26:50 haad Exp $	*/
2 
3 /*
4  * Copyright (C) 1997-2004 Sistina Software, Inc. All rights reserved.
5  * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
6  *
7  * This file is part of LVM2.
8  *
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.
12  *
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
16  */
17 
18 #include "lib.h"
19 #include "label.h"
20 #include "metadata.h"
21 #include "lvmcache.h"
22 #include "disk_rep.h"
23 #include "sptype_names.h"
24 #include "lv_alloc.h"
25 #include "pv_alloc.h"
26 #include "str_list.h"
27 #include "display.h"
28 #include "segtype.h"
29 #include "toolcontext.h"
30 
31 /* This file contains only imports at the moment... */
32 
33 int import_pool_vg(struct volume_group *vg, struct dm_pool *mem, struct dm_list *pls)
34 {
35 	struct pool_list *pl;
36 
37 	dm_list_iterate_items(pl, pls) {
38 		vg->extent_count +=
39 		    ((pl->pd.pl_blocks) / POOL_PE_SIZE);
40 
41 		vg->free_count = vg->extent_count;
42 		vg->pv_count++;
43 
44 		if (vg->name)
45 			continue;
46 
47 		vg->name = dm_pool_strdup(mem, pl->pd.pl_pool_name);
48 		get_pool_vg_uuid(&vg->id, &pl->pd);
49 		vg->extent_size = POOL_PE_SIZE;
50 		vg->status |= LVM_READ | LVM_WRITE | CLUSTERED | SHARED;
51 		vg->max_lv = 1;
52 		vg->max_pv = POOL_MAX_DEVICES;
53 		vg->alloc = ALLOC_NORMAL;
54 	}
55 
56 	return 1;
57 }
58 
59 int import_pool_lvs(struct volume_group *vg, struct dm_pool *mem, struct dm_list *pls)
60 {
61 	struct pool_list *pl;
62 	struct logical_volume *lv;
63 
64 	if (!(lv = alloc_lv(mem)))
65 		return_0;
66 
67 	lv->status = 0;
68 	lv->alloc = ALLOC_NORMAL;
69 	lv->size = 0;
70 	lv->name = NULL;
71 	lv->le_count = 0;
72 	lv->read_ahead = vg->cmd->default_settings.read_ahead;
73 
74 	dm_list_iterate_items(pl, pls) {
75 		lv->size += pl->pd.pl_blocks;
76 
77 		if (lv->name)
78 			continue;
79 
80 		if (!(lv->name = dm_pool_strdup(mem, pl->pd.pl_pool_name)))
81 			return_0;
82 
83 		get_pool_lv_uuid(lv->lvid.id, &pl->pd);
84 		log_debug("Calculated lv uuid for lv %s: %s", lv->name,
85 			  lv->lvid.s);
86 
87 		lv->status |= VISIBLE_LV | LVM_READ | LVM_WRITE;
88 		lv->major = POOL_MAJOR;
89 
90 		/* for pool a minor of 0 is dynamic */
91 		if (pl->pd.pl_minor) {
92 			lv->status |= FIXED_MINOR;
93 			lv->minor = pl->pd.pl_minor + MINOR_OFFSET;
94 		} else {
95 			lv->minor = -1;
96 		}
97 	}
98 
99 	lv->le_count = lv->size / POOL_PE_SIZE;
100 
101 	return link_lv_to_vg(vg, lv);
102 }
103 
104 int import_pool_pvs(const struct format_type *fmt, struct volume_group *vg,
105 		    struct dm_list *pvs, struct dm_pool *mem, struct dm_list *pls)
106 {
107 	struct pv_list *pvl;
108 	struct pool_list *pl;
109 
110 	dm_list_iterate_items(pl, pls) {
111 		if (!(pvl = dm_pool_zalloc(mem, sizeof(*pvl)))) {
112 			log_error("Unable to allocate pv list structure");
113 			return 0;
114 		}
115 		if (!(pvl->pv = dm_pool_zalloc(mem, sizeof(*pvl->pv)))) {
116 			log_error("Unable to allocate pv structure");
117 			return 0;
118 		}
119 		if (!import_pool_pv(fmt, mem, vg, pvl->pv, pl)) {
120 			return 0;
121 		}
122 		pl->pv = pvl->pv;
123 		pvl->mdas = NULL;
124 		pvl->pe_ranges = NULL;
125 		dm_list_add(pvs, &pvl->list);
126 	}
127 
128 	return 1;
129 }
130 
131 int import_pool_pv(const struct format_type *fmt, struct dm_pool *mem,
132 		   struct volume_group *vg, struct physical_volume *pv,
133 		   struct pool_list *pl)
134 {
135 	struct pool_disk *pd = &pl->pd;
136 
137 	memset(pv, 0, sizeof(*pv));
138 
139 	get_pool_pv_uuid(&pv->id, pd);
140 	pv->fmt = fmt;
141 
142 	pv->dev = pl->dev;
143 	if (!(pv->vg_name = dm_pool_strdup(mem, pd->pl_pool_name))) {
144 		log_error("Unable to duplicate vg_name string");
145 		return 0;
146 	}
147 	if (vg != NULL)
148 		memcpy(&pv->vgid, &vg->id, sizeof(vg->id));
149 	pv->status = 0;
150 	pv->size = pd->pl_blocks;
151 	pv->pe_size = POOL_PE_SIZE;
152 	pv->pe_start = POOL_PE_START;
153 	pv->pe_count = pv->size / POOL_PE_SIZE;
154 	pv->pe_alloc_count = 0;
155 	pv->pe_align = 0;
156 
157 	dm_list_init(&pv->tags);
158 	dm_list_init(&pv->segments);
159 
160 	if (!alloc_pv_segment_whole_pv(mem, pv))
161 		return_0;
162 
163 	return 1;
164 }
165 
166 static const char *_cvt_sptype(uint32_t sptype)
167 {
168 	int i;
169 	for (i = 0; sptype_names[i].name[0]; i++) {
170 		if (sptype == sptype_names[i].label) {
171 			break;
172 		}
173 	}
174 	log_debug("Found sptype %X and converted it to %s",
175 		  sptype, sptype_names[i].name);
176 	return sptype_names[i].name;
177 }
178 
179 static int _add_stripe_seg(struct dm_pool *mem,
180 			   struct user_subpool *usp, struct logical_volume *lv,
181 			   uint32_t *le_cur)
182 {
183 	struct lv_segment *seg;
184 	struct segment_type *segtype;
185 	unsigned j;
186 	uint32_t area_len;
187 
188 	if (usp->striping & (usp->striping - 1)) {
189 		log_error("Stripe size must be a power of 2");
190 		return 0;
191 	}
192 
193 	area_len = (usp->devs[0].blocks) / POOL_PE_SIZE;
194 
195 	if (!(segtype = get_segtype_from_string(lv->vg->cmd,
196 						     "striped")))
197 		return_0;
198 
199 	if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur,
200 				     area_len * usp->num_devs, 0,
201 				     usp->striping, NULL, usp->num_devs,
202 				     area_len, 0, 0, 0))) {
203 		log_error("Unable to allocate striped lv_segment structure");
204 		return 0;
205 	}
206 
207 	for (j = 0; j < usp->num_devs; j++)
208 		if (!set_lv_segment_area_pv(seg, j, usp->devs[j].pv, 0))
209 			return_0;
210 
211 	/* add the subpool type to the segment tag list */
212 	str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
213 
214 	dm_list_add(&lv->segments, &seg->list);
215 
216 	*le_cur += seg->len;
217 
218 	return 1;
219 }
220 
221 static int _add_linear_seg(struct dm_pool *mem,
222 			   struct user_subpool *usp, struct logical_volume *lv,
223 			   uint32_t *le_cur)
224 {
225 	struct lv_segment *seg;
226 	struct segment_type *segtype;
227 	unsigned j;
228 	uint32_t area_len;
229 
230 	if (!(segtype = get_segtype_from_string(lv->vg->cmd, "striped")))
231 		return_0;
232 
233 	for (j = 0; j < usp->num_devs; j++) {
234 		area_len = (usp->devs[j].blocks) / POOL_PE_SIZE;
235 
236 		if (!(seg = alloc_lv_segment(mem, segtype, lv, *le_cur,
237 					     area_len, 0, usp->striping,
238 					     NULL, 1, area_len,
239 					     POOL_PE_SIZE, 0, 0))) {
240 			log_error("Unable to allocate linear lv_segment "
241 				  "structure");
242 			return 0;
243 		}
244 
245 		/* add the subpool type to the segment tag list */
246 		str_list_add(mem, &seg->tags, _cvt_sptype(usp->type));
247 
248 		if (!set_lv_segment_area_pv(seg, 0, usp->devs[j].pv, 0))
249 			return_0;
250 		dm_list_add(&lv->segments, &seg->list);
251 
252 		*le_cur += seg->len;
253 	}
254 
255 	return 1;
256 }
257 
258 int import_pool_segments(struct dm_list *lvs, struct dm_pool *mem,
259 			 struct user_subpool *usp, int subpools)
260 {
261 	struct lv_list *lvl;
262 	struct logical_volume *lv;
263 	uint32_t le_cur = 0;
264 	int i;
265 
266 	dm_list_iterate_items(lvl, lvs) {
267 		lv = lvl->lv;
268 
269 		if (lv->status & SNAPSHOT)
270 			continue;
271 
272 		for (i = 0; i < subpools; i++) {
273 			if (usp[i].striping) {
274 				if (!_add_stripe_seg(mem, &usp[i], lv, &le_cur))
275 					return_0;
276 			} else {
277 				if (!_add_linear_seg(mem, &usp[i], lv, &le_cur))
278 					return_0;
279 			}
280 		}
281 	}
282 
283 	return 1;
284 }
285