Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 : : * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
4 : : * Copyright (C) 2005 Zak Kipling. All rights reserved.
5 : : *
6 : : * This file is part of LVM2.
7 : : *
8 : : * This copyrighted material is made available to anyone wishing to use,
9 : : * modify, copy, or redistribute it subject to the terms and conditions
10 : : * of the GNU Lesser General Public License v.2.1.
11 : : *
12 : : * You should have received a copy of the GNU Lesser General Public License
13 : : * along with this program; if not, write to the Free Software Foundation,
14 : : * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 : : */
16 : :
17 : : #include "tools.h"
18 : :
19 : : struct pvresize_params {
20 : : uint64_t new_size;
21 : :
22 : : unsigned done;
23 : : unsigned total;
24 : : };
25 : :
26 : 0 : static int _pv_resize_single(struct cmd_context *cmd,
27 : : struct volume_group *vg,
28 : : struct physical_volume *pv,
29 : : const uint64_t new_size)
30 : : {
31 : : struct pv_list *pvl;
32 : 0 : uint64_t size = 0;
33 : 0 : uint32_t new_pe_count = 0;
34 : 0 : int r = 0;
35 : : struct dm_list mdas;
36 : 0 : const char *pv_name = pv_dev_name(pv);
37 : : const char *vg_name;
38 : : struct lvmcache_info *info;
39 : 0 : int mda_count = 0;
40 : 0 : struct volume_group *old_vg = vg;
41 : :
42 : 0 : dm_list_init(&mdas);
43 : :
44 [ # # ]: 0 : if (is_orphan_vg(pv_vg_name(pv))) {
45 : 0 : vg_name = VG_ORPHANS;
46 [ # # ]: 0 : if (!lock_vol(cmd, vg_name, LCK_VG_WRITE)) {
47 : 0 : log_error("Can't get lock for orphans");
48 : 0 : return 0;
49 : : }
50 : :
51 [ # # ]: 0 : if (!(pv = pv_read(cmd, pv_name, &mdas, NULL, 1, 0))) {
52 : 0 : unlock_vg(cmd, vg_name);
53 : 0 : log_error("Unable to read PV \"%s\"", pv_name);
54 : 0 : return 0;
55 : : }
56 : :
57 : 0 : mda_count = dm_list_size(&mdas);
58 : : } else {
59 : 0 : vg_name = pv_vg_name(pv);
60 : :
61 : 0 : vg = vg_read_for_update(cmd, vg_name, NULL, 0);
62 : :
63 [ # # ]: 0 : if (vg_read_error(vg)) {
64 : 0 : vg_release(vg);
65 : 0 : log_error("Unable to read volume group \"%s\".",
66 : : vg_name);
67 : 0 : return 0;
68 : : }
69 : :
70 [ # # ]: 0 : if (!(pvl = find_pv_in_vg(vg, pv_name))) {
71 : 0 : log_error("Unable to find \"%s\" in volume group \"%s\"",
72 : : pv_name, vg->name);
73 : 0 : goto bad;
74 : : }
75 : :
76 : 0 : pv = pvl->pv;
77 : :
78 [ # # ]: 0 : if (!(info = info_from_pvid(pv->dev->pvid, 0))) {
79 : 0 : log_error("Can't get info for PV %s in volume group %s",
80 : : pv_name, vg->name);
81 : 0 : goto bad;
82 : : }
83 : :
84 : 0 : mda_count = dm_list_size(&info->mdas);
85 : :
86 [ # # ]: 0 : if (!archive(vg))
87 : 0 : goto bad;
88 : : }
89 : :
90 : : /* FIXME Create function to test compatibility properly */
91 [ # # ]: 0 : if (mda_count > 1) {
92 : 0 : log_error("%s: too many metadata areas for pvresize", pv_name);
93 : 0 : goto bad;
94 : : }
95 : :
96 [ # # ]: 0 : if (!(pv->fmt->features & FMT_RESIZE_PV)) {
97 : 0 : log_error("Physical volume %s format does not support resizing.",
98 : : pv_name);
99 : 0 : goto bad;
100 : : }
101 : :
102 : : /* Get new size */
103 [ # # ]: 0 : if (!dev_get_size(pv_dev(pv), &size)) {
104 : 0 : log_error("%s: Couldn't get size.", pv_name);
105 : 0 : goto bad;
106 : : }
107 : :
108 [ # # ]: 0 : if (new_size) {
109 [ # # ]: 0 : if (new_size > size)
110 : 0 : log_warn("WARNING: %s: Overriding real size. "
111 : : "You could lose data.", pv_name);
112 : 0 : log_verbose("%s: Pretending size is %" PRIu64 " not %" PRIu64
113 : : " sectors.", pv_name, new_size, pv_size(pv));
114 : 0 : size = new_size;
115 : : }
116 : :
117 [ # # ]: 0 : if (size < PV_MIN_SIZE) {
118 : 0 : log_error("%s: Size must exceed minimum of %ld sectors.",
119 : : pv_name, PV_MIN_SIZE);
120 : 0 : goto bad;
121 : : }
122 : :
123 [ # # ]: 0 : if (size < pv_pe_start(pv)) {
124 : 0 : log_error("%s: Size must exceed physical extent start of "
125 : : "%" PRIu64 " sectors.", pv_name, pv_pe_start(pv));
126 : 0 : goto bad;
127 : : }
128 : :
129 : 0 : pv->size = size;
130 : :
131 [ # # ]: 0 : if (vg) {
132 : 0 : pv->size -= pv_pe_start(pv);
133 : 0 : new_pe_count = pv_size(pv) / vg->extent_size;
134 : :
135 [ # # ]: 0 : if (!new_pe_count) {
136 : 0 : log_error("%s: Size must leave space for at "
137 : : "least one physical extent of "
138 : : "%" PRIu32 " sectors.", pv_name,
139 : : pv_pe_size(pv));
140 : 0 : goto bad;
141 : : }
142 : :
143 [ # # ]: 0 : if (!pv_resize(pv, vg, new_pe_count))
144 : 0 : goto_bad;
145 : : }
146 : :
147 : 0 : log_verbose("Resizing volume \"%s\" to %" PRIu64 " sectors.",
148 : : pv_name, pv_size(pv));
149 : :
150 : 0 : log_verbose("Updating physical volume \"%s\"", pv_name);
151 [ # # ]: 0 : if (!is_orphan_vg(pv_vg_name(pv))) {
152 [ # # ][ # # ]: 0 : if (!vg_write(vg) || !vg_commit(vg)) {
153 : 0 : log_error("Failed to store physical volume \"%s\" in "
154 : : "volume group \"%s\"", pv_name, vg->name);
155 : 0 : goto bad;
156 : : }
157 : 0 : backup(vg);
158 [ # # ]: 0 : } else if (!(pv_write(cmd, pv, NULL, INT64_C(-1)))) {
159 : 0 : log_error("Failed to store physical volume \"%s\"",
160 : : pv_name);
161 : 0 : goto bad;;
162 : : }
163 : :
164 : 0 : log_print("Physical volume \"%s\" changed", pv_name);
165 : 0 : r = 1;
166 : :
167 : : bad:
168 : 0 : unlock_vg(cmd, vg_name);
169 [ # # ]: 0 : if (!old_vg)
170 : 0 : vg_release(vg);
171 : 0 : return r;
172 : : }
173 : :
174 : 0 : static int _pvresize_single(struct cmd_context *cmd,
175 : : struct volume_group *vg,
176 : : struct physical_volume *pv,
177 : : void *handle)
178 : : {
179 : 0 : struct pvresize_params *params = (struct pvresize_params *) handle;
180 : :
181 : 0 : params->total++;
182 : :
183 [ # # ]: 0 : if (!_pv_resize_single(cmd, vg, pv, params->new_size)) {
184 : 0 : stack;
185 : 0 : return ECMD_FAILED;
186 : : }
187 : :
188 : 0 : params->done++;
189 : :
190 : 0 : return ECMD_PROCESSED;
191 : : }
192 : :
193 : 0 : int pvresize(struct cmd_context *cmd, int argc, char **argv)
194 : : {
195 : : struct pvresize_params params;
196 : : int ret;
197 : :
198 [ # # ]: 0 : if (!argc) {
199 : 0 : log_error("Please supply physical volume(s)");
200 : 0 : return EINVALID_CMD_LINE;
201 : : }
202 : :
203 [ # # ]: 0 : if (arg_sign_value(cmd, physicalvolumesize_ARG, 0) == SIGN_MINUS) {
204 : 0 : log_error("Physical volume size may not be negative");
205 : 0 : return 0;
206 : : }
207 : :
208 : 0 : params.new_size = arg_uint64_value(cmd, physicalvolumesize_ARG,
209 : : UINT64_C(0));
210 : :
211 : 0 : params.done = 0;
212 : 0 : params.total = 0;
213 : :
214 : 0 : ret = process_each_pv(cmd, argc, argv, NULL, READ_FOR_UPDATE, 0, ¶ms,
215 : : _pvresize_single);
216 : :
217 : 0 : log_print("%d physical volume(s) resized / %d physical volume(s) "
218 : : "not resized", params.done, params.total - params.done);
219 : :
220 : 0 : return ret;
221 : : }
|