xref: /netbsd-src/external/gpl2/lvm2/dist/tools/pvcreate.c (revision 274254cdae52594c1aa480a736aef78313d15c9c)
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