summaryrefslogtreecommitdiffstats
path: root/tools/vgcreate.c
blob: bba795fc5f422320fe08c22279e8d501baa3ac36 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * Copyright (C) 2001 Sistina Software
 *
 * vgcreate is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * vgcreate is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with LVM; see the file COPYING.  If not, write to
 * the Free Software Foundation, 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 */

#include "tools.h"

/* FIXME From config file? */
#define DEFAULT_PV 256
#define DEFAULT_LV 256

#define DEFAULT_EXTENT 4096	/* In KB */

int vgcreate(struct cmd_context *cmd, int argc, char **argv)
{
	size_t max_lv, max_pv;
	uint32_t extent_size;
	char *vg_name;
	char vg_path[PATH_MAX];
	struct volume_group *vg;

	if (!argc) {
		log_error("Please provide volume group name and "
			  "physical volumes");
		return EINVALID_CMD_LINE;
	}

	if (argc == 1) {
		log_error("Please enter physical volume name(s)");
		return EINVALID_CMD_LINE;
	}

	vg_name = argv[0];
	max_lv = arg_uint_value(cmd, maxlogicalvolumes_ARG, DEFAULT_LV);
	max_pv = arg_uint_value(cmd, maxphysicalvolumes_ARG, DEFAULT_PV);

	if (arg_sign_value(cmd, physicalextentsize_ARG, 0) == SIGN_MINUS) {
		log_error("Physical extent size may not be negative");
		return EINVALID_CMD_LINE;
	}

	/* Units of 512-byte sectors */
	extent_size =
	    arg_uint_value(cmd, physicalextentsize_ARG, DEFAULT_EXTENT) * 2;

	if (max_lv < 1) {
		log_error("maxlogicalvolumes too low");
		return EINVALID_CMD_LINE;
	}

	if (max_pv < 1) {
		log_error("maxphysicalvolumes too low");
		return EINVALID_CMD_LINE;
	}

	if (!extent_size) {
		log_error("Physical extent size may not be zero");
		return EINVALID_CMD_LINE;
	}

	/* Strip dev_dir if present */
	if (!strncmp(vg_name, cmd->dev_dir, strlen(cmd->dev_dir)))
		vg_name += strlen(cmd->dev_dir);

	snprintf(vg_path, PATH_MAX, "%s%s", cmd->dev_dir, vg_name);
	if (path_exists(vg_path)) {
		log_error("%s: already exists in filesystem", vg_path);
		return ECMD_FAILED;
	}

	if (!validate_name(vg_name)) {
		log_error("New volume group name \"%s\" is invalid", vg_name);
		return ECMD_FAILED;
	}

	/* Create the new VG */
	if (!(vg = vg_create(cmd, vg_name, extent_size, max_pv, max_lv,
			     argc - 1, argv + 1)))
		return ECMD_FAILED;

	if (max_lv != vg->max_lv)
		log_error("Warning: Setting maxlogicalvolumes to %d",
			  vg->max_lv);

	if (max_pv != vg->max_pv)
		log_error("Warning: Setting maxphysicalvolumes to %d",
			  vg->max_pv);

	if (!lock_vol(cmd, "", LCK_VG_WRITE)) {
		log_error("Can't get lock for orphan PVs");
		return ECMD_FAILED;
	}

	if (!lock_vol(cmd, vg_name, LCK_VG_WRITE | LCK_NONBLOCK)) {
		log_error("Can't get lock for %s", vg_name);
		unlock_vg(cmd, "");
		return ECMD_FAILED;
	}

	if (!archive(vg)) {
		unlock_vg(cmd, vg_name);
		unlock_vg(cmd, "");
		return ECMD_FAILED;
	}

	/* Store VG on disk(s) */
	if (!vg_write(vg) || !vg_commit(vg)) {
		unlock_vg(cmd, vg_name);
		unlock_vg(cmd, "");
		return ECMD_FAILED;
	}

	unlock_vg(cmd, vg_name);
	unlock_vg(cmd, "");

	backup(vg);

	log_print("Volume group \"%s\" successfully created", vg->name);

	return ECMD_PROCESSED;
}