1 /* $NetBSD: pvcreate.c,v 1.1.1.1 2008/12/22 00:19:06 haad Exp $ */ 2 3 /* 4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. 5 * Copyright (C) 2004-2007 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 "tools.h" 19 #include "metadata.h" 20 21 struct pvcreate_params { 22 int zero; 23 uint64_t size; 24 int pvmetadatacopies; 25 uint64_t pvmetadatasize; 26 int64_t labelsector; 27 struct id id; /* FIXME: redundant */ 28 struct id *idp; /* 0 if no --uuid option */ 29 uint64_t pe_start; 30 uint32_t extent_count; 31 uint32_t extent_size; 32 const char *restorefile; /* 0 if no --restorefile option */ 33 force_t force; 34 unsigned yes; 35 }; 36 37 const char _really_init[] = 38 "Really INITIALIZE physical volume \"%s\" of volume group \"%s\" [y/n]? "; 39 40 /* 41 * See if we may pvcreate on this device. 42 * 0 indicates we may not. 43 */ 44 static int pvcreate_check(struct cmd_context *cmd, const char *name, 45 struct pvcreate_params *pp) 46 { 47 struct physical_volume *pv; 48 struct device *dev; 49 uint64_t md_superblock; 50 51 /* FIXME Check partition type is LVM unless --force is given */ 52 53 /* Is there a pv here already? */ 54 pv = pv_read(cmd, name, NULL, NULL, 0); 55 56 /* 57 * If a PV has no MDAs it may appear to be an orphan until the 58 * metadata is read off another PV in the same VG. Detecting 59 * this means checking every VG by scanning every PV on the 60 * system. 61 */ 62 if (pv && is_orphan(pv)) { 63 if (!scan_vgs_for_pvs(cmd)) 64 return_0; 65 pv = pv_read(cmd, name, NULL, NULL, 0); 66 } 67 68 /* Allow partial & exported VGs to be destroyed. */ 69 /* We must have -ff to overwrite a non orphan */ 70 if (pv && !is_orphan(pv) && pp->force != DONT_PROMPT_OVERRIDE) { 71 log_error("Can't initialize physical volume \"%s\" of " 72 "volume group \"%s\" without -ff", name, pv_vg_name(pv)); 73 return 0; 74 } 75 76 /* prompt */ 77 if (pv && !is_orphan(pv) && !pp->yes && 78 yes_no_prompt(_really_init, name, pv_vg_name(pv)) == 'n') { 79 log_print("%s: physical volume not initialized", name); 80 return 0; 81 } 82 83 if (sigint_caught()) 84 return 0; 85 86 dev = dev_cache_get(name, cmd->filter); 87 88 /* Is there an md superblock here? */ 89 if (!dev && md_filtering()) { 90 unlock_vg(cmd, VG_ORPHANS); 91 92 persistent_filter_wipe(cmd->filter); 93 lvmcache_destroy(cmd, 1); 94 95 init_md_filtering(0); 96 if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) { 97 log_error("Can't get lock for orphan PVs"); 98 init_md_filtering(1); 99 return 0; 100 } 101 dev = dev_cache_get(name, cmd->filter); 102 init_md_filtering(1); 103 } 104 105 if (!dev) { 106 log_error("Device %s not found (or ignored by filtering).", name); 107 return 0; 108 } 109 110 /* 111 * This test will fail if the device belongs to an MD array. 112 */ 113 if (!dev_test_excl(dev)) { 114 /* FIXME Detect whether device-mapper itself is still using it */ 115 log_error("Can't open %s exclusively. Mounted filesystem?", 116 name); 117 return 0; 118 } 119 120 /* Wipe superblock? */ 121 if (dev_is_md(dev, &md_superblock) && 122 ((!pp->idp && !pp->restorefile) || pp->yes || 123 (yes_no_prompt("Software RAID md superblock " 124 "detected on %s. Wipe it? [y/n] ", name) == 'y'))) { 125 log_print("Wiping software RAID md superblock on %s", name); 126 if (!dev_set(dev, md_superblock, 4, 0)) { 127 log_error("Failed to wipe RAID md superblock on %s", 128 name); 129 return 0; 130 } 131 } 132 133 if (sigint_caught()) 134 return 0; 135 136 if (pv && !is_orphan(pv) && pp->force) { 137 log_warn("WARNING: Forcing physical volume creation on " 138 "%s%s%s%s", name, 139 !is_orphan(pv) ? " of volume group \"" : "", 140 !is_orphan(pv) ? pv_vg_name(pv) : "", 141 !is_orphan(pv) ? "\"" : ""); 142 } 143 144 return 1; 145 } 146 147 static int pvcreate_single(struct cmd_context *cmd, const char *pv_name, 148 void *handle) 149 { 150 struct pvcreate_params *pp = (struct pvcreate_params *) handle; 151 void *pv; 152 struct device *dev; 153 struct dm_list mdas; 154 155 if (pp->idp) { 156 if ((dev = device_from_pvid(cmd, pp->idp)) && 157 (dev != dev_cache_get(pv_name, cmd->filter))) { 158 log_error("uuid %s already in use on \"%s\"", 159 pp->idp->uuid, dev_name(dev)); 160 return 0; 161 } 162 } 163 164 if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) { 165 log_error("Can't get lock for orphan PVs"); 166 return 0; 167 } 168 169 if (!pvcreate_check(cmd, pv_name, pp)) 170 goto error; 171 172 if (sigint_caught()) 173 goto error; 174 175 if (!(dev = dev_cache_get(pv_name, cmd->filter))) { 176 log_error("%s: Couldn't find device. Check your filters?", 177 pv_name); 178 goto error; 179 } 180 181 dm_list_init(&mdas); 182 if (!(pv = pv_create(cmd, dev, pp->idp, pp->size, pp->pe_start, 183 pp->extent_count, pp->extent_size, 184 pp->pvmetadatacopies, 185 pp->pvmetadatasize,&mdas))) { 186 log_error("Failed to setup physical volume \"%s\"", pv_name); 187 goto error; 188 } 189 190 log_verbose("Set up physical volume for \"%s\" with %" PRIu64 191 " available sectors", pv_name, pv_size(pv)); 192 193 /* Wipe existing label first */ 194 if (!label_remove(pv_dev(pv))) { 195 log_error("Failed to wipe existing label on %s", pv_name); 196 goto error; 197 } 198 199 if (pp->zero) { 200 log_verbose("Zeroing start of device %s", pv_name); 201 if (!dev_open_quiet(dev)) { 202 log_error("%s not opened: device not zeroed", pv_name); 203 goto error; 204 } 205 206 if (!dev_set(dev, UINT64_C(0), (size_t) 2048, 0)) { 207 log_error("%s not wiped: aborting", pv_name); 208 dev_close(dev); 209 goto error; 210 } 211 dev_close(dev); 212 } 213 214 log_very_verbose("Writing physical volume data to disk \"%s\"", 215 pv_name); 216 if (!(pv_write(cmd, (struct physical_volume *)pv, &mdas, 217 pp->labelsector))) { 218 log_error("Failed to write physical volume \"%s\"", pv_name); 219 goto error; 220 } 221 222 log_print("Physical volume \"%s\" successfully created", pv_name); 223 224 unlock_vg(cmd, VG_ORPHANS); 225 return 1; 226 227 error: 228 unlock_vg(cmd, VG_ORPHANS); 229 return 0; 230 } 231 232 /* 233 * Intial sanity checking of command-line arguments and fill in 'pp' fields. 234 * 235 * Input arguments: 236 * cmd, argc, argv 237 * 238 * Output arguments: 239 * pp: structure allocated by caller, fields written / validated here 240 */ 241 static int pvcreate_validate_params(struct cmd_context *cmd, 242 int argc, char **argv, 243 struct pvcreate_params *pp) 244 { 245 const char *uuid = NULL; 246 void *existing_pv; 247 struct volume_group *vg; 248 249 memset(pp, 0, sizeof(*pp)); 250 251 if (!argc) { 252 log_error("Please enter a physical volume path"); 253 return 0; 254 } 255 256 if (arg_count(cmd, restorefile_ARG) && !arg_count(cmd, uuidstr_ARG)) { 257 log_error("--uuid is required with --restorefile"); 258 return 0; 259 } 260 261 if (arg_count(cmd, uuidstr_ARG) && argc != 1) { 262 log_error("Can only set uuid on one volume at once"); 263 return 0; 264 } 265 266 if (arg_count(cmd, uuidstr_ARG)) { 267 uuid = arg_str_value(cmd, uuidstr_ARG, ""); 268 if (!id_read_format(&pp->id, uuid)) 269 return 0; 270 pp->idp = &pp->id; 271 } 272 273 if (arg_count(cmd, restorefile_ARG)) { 274 pp->restorefile = arg_str_value(cmd, restorefile_ARG, ""); 275 /* The uuid won't already exist */ 276 if (!(vg = backup_read_vg(cmd, NULL, pp->restorefile))) { 277 log_error("Unable to read volume group from %s", 278 pp->restorefile); 279 return 0; 280 } 281 if (!(existing_pv = find_pv_in_vg_by_uuid(vg, pp->idp))) { 282 log_error("Can't find uuid %s in backup file %s", 283 uuid, pp->restorefile); 284 return 0; 285 } 286 pp->pe_start = pv_pe_start(existing_pv); 287 pp->extent_size = pv_pe_size(existing_pv); 288 pp->extent_count = pv_pe_count(existing_pv); 289 } 290 291 if (arg_count(cmd, yes_ARG) && !arg_count(cmd, force_ARG)) { 292 log_error("Option y can only be given with option f"); 293 return 0; 294 } 295 296 pp->yes = arg_count(cmd, yes_ARG); 297 pp->force = arg_count(cmd, force_ARG); 298 299 if (arg_int_value(cmd, labelsector_ARG, 0) >= LABEL_SCAN_SECTORS) { 300 log_error("labelsector must be less than %lu", 301 LABEL_SCAN_SECTORS); 302 return 0; 303 } else { 304 pp->labelsector = arg_int64_value(cmd, labelsector_ARG, 305 DEFAULT_LABELSECTOR); 306 } 307 308 if (!(cmd->fmt->features & FMT_MDAS) && 309 (arg_count(cmd, metadatacopies_ARG) || 310 arg_count(cmd, metadatasize_ARG))) { 311 log_error("Metadata parameters only apply to text format"); 312 return 0; 313 } 314 315 if (arg_count(cmd, metadatacopies_ARG) && 316 arg_int_value(cmd, metadatacopies_ARG, -1) > 2) { 317 log_error("Metadatacopies may only be 0, 1 or 2"); 318 return 0; 319 } 320 321 if (arg_count(cmd, zero_ARG)) 322 pp->zero = strcmp(arg_str_value(cmd, zero_ARG, "y"), "n"); 323 else if (arg_count(cmd, restorefile_ARG) || arg_count(cmd, uuidstr_ARG)) 324 pp->zero = 0; 325 else 326 pp->zero = 1; 327 328 if (arg_sign_value(cmd, physicalvolumesize_ARG, 0) == SIGN_MINUS) { 329 log_error("Physical volume size may not be negative"); 330 return 0; 331 } 332 pp->size = arg_uint64_value(cmd, physicalvolumesize_ARG, UINT64_C(0)); 333 334 if (arg_sign_value(cmd, metadatasize_ARG, 0) == SIGN_MINUS) { 335 log_error("Metadata size may not be negative"); 336 return 0; 337 } 338 339 pp->pvmetadatasize = arg_uint64_value(cmd, metadatasize_ARG, UINT64_C(0)); 340 if (!pp->pvmetadatasize) 341 pp->pvmetadatasize = find_config_tree_int(cmd, 342 "metadata/pvmetadatasize", 343 DEFAULT_PVMETADATASIZE); 344 345 pp->pvmetadatacopies = arg_int_value(cmd, metadatacopies_ARG, -1); 346 if (pp->pvmetadatacopies < 0) 347 pp->pvmetadatacopies = find_config_tree_int(cmd, 348 "metadata/pvmetadatacopies", 349 DEFAULT_PVMETADATACOPIES); 350 351 return 1; 352 } 353 354 355 int pvcreate(struct cmd_context *cmd, int argc, char **argv) 356 { 357 int i; 358 int ret = ECMD_PROCESSED; 359 struct pvcreate_params pp; 360 361 if (!pvcreate_validate_params(cmd, argc, argv, &pp)) { 362 return EINVALID_CMD_LINE; 363 } 364 365 for (i = 0; i < argc; i++) { 366 if (!pvcreate_single(cmd, argv[i], &pp)) 367 ret = ECMD_FAILED; 368 369 if (sigint_caught()) 370 return ret; 371 } 372 373 return ret; 374 } 375