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