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 
import_pool_vg(struct volume_group * vg,struct dm_pool * mem,struct dm_list * pls)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 
import_pool_lvs(struct volume_group * vg,struct dm_pool * mem,struct dm_list * pls)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 
import_pool_pvs(const struct format_type * fmt,struct volume_group * vg,struct dm_list * pvs,struct dm_pool * mem,struct dm_list * pls)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 
import_pool_pv(const struct format_type * fmt,struct dm_pool * mem,struct volume_group * vg,struct physical_volume * pv,struct pool_list * pl)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 
_cvt_sptype(uint32_t sptype)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 
_add_stripe_seg(struct dm_pool * mem,struct user_subpool * usp,struct logical_volume * lv,uint32_t * le_cur)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 
_add_linear_seg(struct dm_pool * mem,struct user_subpool * usp,struct logical_volume * lv,uint32_t * le_cur)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 
import_pool_segments(struct dm_list * lvs,struct dm_pool * mem,struct user_subpool * usp,int subpools)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