~ubuntu-branches/ubuntu/breezy/lvm2/breezy

« back to all changes in this revision

Viewing changes to tools/vgchange.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Caulfield
  • Date: 2004-11-03 09:37:56 UTC
  • Revision ID: james.westby@ubuntu.com-20041103093756-jt0nj8z0v8k1lyiv
Tags: upstream-2.00.25
ImportĀ upstreamĀ versionĀ 2.00.25

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. 
 
3
 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
 
4
 *
 
5
 * This file is part of LVM2.
 
6
 *
 
7
 * This copyrighted material is made available to anyone wishing to use,
 
8
 * modify, copy, or redistribute it subject to the terms and conditions
 
9
 * of the GNU General Public License v.2.
 
10
 *
 
11
 * You should have received a copy of the GNU General Public License
 
12
 * along with this program; if not, write to the Free Software Foundation,
 
13
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
14
 */
 
15
 
 
16
#include "tools.h"
 
17
 
 
18
static int _activate_lvs_in_vg(struct cmd_context *cmd,
 
19
                               struct volume_group *vg, int activate)
 
20
{
 
21
        struct lv_list *lvl;
 
22
        struct logical_volume *lv;
 
23
        const char *pvname;
 
24
        int count = 0;
 
25
 
 
26
        list_iterate_items(lvl, &vg->lvs) {
 
27
                lv = lvl->lv;
 
28
 
 
29
                /* Only request activation of snapshot origin devices */
 
30
                if (lv_is_cow(lv))
 
31
                        continue;
 
32
 
 
33
                /* Can't deactive a pvmove LV */
 
34
                /* FIXME There needs to be a controlled way of doing this */
 
35
                if (((activate == CHANGE_AN) || (activate == CHANGE_ALN)) &&
 
36
                    (lv->status & PVMOVE))
 
37
                        continue;
 
38
 
 
39
                if (activate == CHANGE_AN) {
 
40
                        if (!deactivate_lv(cmd, lv->lvid.s))
 
41
                                continue;
 
42
                } else if (activate == CHANGE_ALN) {
 
43
                        if (!deactivate_lv_local(cmd, lv->lvid.s))
 
44
                                continue;
 
45
                } else if (lv_is_origin(lv) || (activate == CHANGE_AE)) {
 
46
                        if (!activate_lv_excl(cmd, lv->lvid.s))
 
47
                                continue;
 
48
                } else if (activate == CHANGE_ALY) {
 
49
                        if (!activate_lv_local(cmd, lv->lvid.s))
 
50
                                continue;
 
51
                } else if (!activate_lv(cmd, lv->lvid.s))
 
52
                        continue;
 
53
 
 
54
                if ((lv->status & PVMOVE) &&
 
55
                    (pvname = get_pvmove_pvname_from_lv_mirr(lv))) {
 
56
                        log_verbose("Spawning background process for %s %s",
 
57
                                    lv->name, pvname);
 
58
                        pvmove_poll(cmd, pvname, 1);
 
59
                        continue;
 
60
                }
 
61
 
 
62
                count++;
 
63
        }
 
64
 
 
65
        return count;
 
66
}
 
67
 
 
68
static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg)
 
69
{
 
70
        int lv_open, active;
 
71
        int available;
 
72
        int activate = 1;
 
73
 
 
74
        available = arg_uint_value(cmd, available_ARG, 0);
 
75
 
 
76
        if ((available == CHANGE_AN) || (available == CHANGE_ALN))
 
77
                activate = 0;
 
78
 
 
79
        /* FIXME: Force argument to deactivate them? */
 
80
        if (!activate && (lv_open = lvs_in_vg_opened(vg))) {
 
81
                log_error("Can't deactivate volume group \"%s\" with %d open "
 
82
                          "logical volume(s)", vg->name, lv_open);
 
83
                return ECMD_FAILED;
 
84
        }
 
85
 
 
86
        if (activate && (active = lvs_in_vg_activated(vg)))
 
87
                log_verbose("%d logical volume(s) in volume group \"%s\" "
 
88
                            "already active", active, vg->name);
 
89
 
 
90
        if (activate && _activate_lvs_in_vg(cmd, vg, available))
 
91
                log_verbose("Activated logical volumes in "
 
92
                            "volume group \"%s\"", vg->name);
 
93
 
 
94
        if (!activate && _activate_lvs_in_vg(cmd, vg, available))
 
95
                log_verbose("Deactivated logical volumes in "
 
96
                            "volume group \"%s\"", vg->name);
 
97
 
 
98
        log_print("%d logical volume(s) in volume group \"%s\" now active",
 
99
                  lvs_in_vg_activated(vg), vg->name);
 
100
        return ECMD_PROCESSED;
 
101
}
 
102
 
 
103
static int _vgchange_alloc(struct cmd_context *cmd, struct volume_group *vg)
 
104
{
 
105
        alloc_policy_t alloc;
 
106
 
 
107
        alloc = (alloc_policy_t) arg_uint_value(cmd, alloc_ARG, ALLOC_NORMAL);
 
108
 
 
109
        if (alloc == ALLOC_INHERIT) {
 
110
                log_error("Volume Group allocation policy cannot inherit "
 
111
                          "from anything");
 
112
                return EINVALID_CMD_LINE;
 
113
        }
 
114
 
 
115
        if (alloc == vg->alloc) {
 
116
                log_error("Volume group allocation policy is already %s",
 
117
                          get_alloc_string(vg->alloc));
 
118
                return ECMD_FAILED;
 
119
        }
 
120
 
 
121
        if (!archive(vg))
 
122
                return ECMD_FAILED;
 
123
 
 
124
        vg->alloc = alloc;
 
125
 
 
126
        if (!vg_write(vg) || !vg_commit(vg))
 
127
                return ECMD_FAILED;
 
128
 
 
129
        backup(vg);
 
130
 
 
131
        log_print("Volume group \"%s\" successfully changed", vg->name);
 
132
 
 
133
        return ECMD_PROCESSED;
 
134
}
 
135
 
 
136
static int _vgchange_resizeable(struct cmd_context *cmd,
 
137
                                struct volume_group *vg)
 
138
{
 
139
        int resizeable = !strcmp(arg_str_value(cmd, resizeable_ARG, "n"), "y");
 
140
 
 
141
        if (resizeable && (vg->status & RESIZEABLE_VG)) {
 
142
                log_error("Volume group \"%s\" is already resizeable",
 
143
                          vg->name);
 
144
                return ECMD_FAILED;
 
145
        }
 
146
 
 
147
        if (!resizeable && !(vg->status & RESIZEABLE_VG)) {
 
148
                log_error("Volume group \"%s\" is already not resizeable",
 
149
                          vg->name);
 
150
                return ECMD_FAILED;
 
151
        }
 
152
 
 
153
        if (!archive(vg))
 
154
                return ECMD_FAILED;
 
155
 
 
156
        if (resizeable)
 
157
                vg->status |= RESIZEABLE_VG;
 
158
        else
 
159
                vg->status &= ~RESIZEABLE_VG;
 
160
 
 
161
        if (!vg_write(vg) || !vg_commit(vg))
 
162
                return ECMD_FAILED;
 
163
 
 
164
        backup(vg);
 
165
 
 
166
        log_print("Volume group \"%s\" successfully changed", vg->name);
 
167
 
 
168
        return ECMD_PROCESSED;
 
169
}
 
170
 
 
171
static int _vgchange_logicalvolume(struct cmd_context *cmd,
 
172
                                   struct volume_group *vg)
 
173
{
 
174
        uint32_t max_lv = arg_uint_value(cmd, logicalvolume_ARG, 0);
 
175
 
 
176
        if (!(vg->status & RESIZEABLE_VG)) {
 
177
                log_error("Volume group \"%s\" must be resizeable "
 
178
                          "to change MaxLogicalVolume", vg->name);
 
179
                return ECMD_FAILED;
 
180
        }
 
181
 
 
182
        if (!(vg->fid->fmt->features & FMT_UNLIMITED_VOLS)) {
 
183
                if (!max_lv)
 
184
                        max_lv = 255;
 
185
                else if (max_lv > 255) {
 
186
                        log_error("MaxLogicalVolume limit is 255");
 
187
                        return ECMD_FAILED;
 
188
                }
 
189
        }
 
190
 
 
191
        if (max_lv && max_lv < vg->lv_count) {
 
192
                log_error("MaxLogicalVolume is less than the current number "
 
193
                          "%d of logical volume(s) for \"%s\"", vg->lv_count,
 
194
                          vg->name);
 
195
                return ECMD_FAILED;
 
196
        }
 
197
 
 
198
        if (!archive(vg))
 
199
                return ECMD_FAILED;
 
200
 
 
201
        vg->max_lv = max_lv;
 
202
 
 
203
        if (!vg_write(vg) || !vg_commit(vg))
 
204
                return ECMD_FAILED;
 
205
 
 
206
        backup(vg);
 
207
 
 
208
        log_print("Volume group \"%s\" successfully changed", vg->name);
 
209
 
 
210
        return ECMD_PROCESSED;
 
211
}
 
212
 
 
213
static int _vgchange_tag(struct cmd_context *cmd, struct volume_group *vg,
 
214
                         int arg)
 
215
{
 
216
        const char *tag;
 
217
 
 
218
        if (!(tag = arg_str_value(cmd, arg, NULL))) {
 
219
                log_error("Failed to get tag");
 
220
                return ECMD_FAILED;
 
221
        }
 
222
 
 
223
        if (!(vg->fid->fmt->features & FMT_TAGS)) {
 
224
                log_error("Volume group %s does not support tags", vg->name);
 
225
                return ECMD_FAILED;
 
226
        }
 
227
 
 
228
        if (!archive(vg))
 
229
                return ECMD_FAILED;
 
230
 
 
231
        if ((arg == addtag_ARG)) {
 
232
                if (!str_list_add(cmd->mem, &vg->tags, tag)) {
 
233
                        log_error("Failed to add tag %s to volume group %s",
 
234
                                  tag, vg->name);
 
235
                        return ECMD_FAILED;
 
236
                }
 
237
        } else {
 
238
                if (!str_list_del(&vg->tags, tag)) {
 
239
                        log_error("Failed to remove tag %s from volume group "
 
240
                                  "%s", tag, vg->name);
 
241
                        return ECMD_FAILED;
 
242
                }
 
243
        }
 
244
 
 
245
        if (!vg_write(vg) || !vg_commit(vg))
 
246
                return ECMD_FAILED;
 
247
 
 
248
        backup(vg);
 
249
 
 
250
        log_print("Volume group \"%s\" successfully changed", vg->name);
 
251
 
 
252
        return ECMD_PROCESSED;
 
253
}
 
254
 
 
255
static int _vgchange_uuid(struct cmd_context *cmd, struct volume_group *vg)
 
256
{
 
257
        struct lv_list *lvl;
 
258
 
 
259
        if (lvs_in_vg_activated(vg)) {
 
260
                log_error("Volume group has active logical volumes");
 
261
                return ECMD_FAILED;
 
262
        }
 
263
 
 
264
        if (!archive(vg))
 
265
                return ECMD_FAILED;
 
266
 
 
267
        id_create(&vg->id);
 
268
 
 
269
        list_iterate_items(lvl, &vg->lvs) {
 
270
                memcpy(&lvl->lv->lvid, &vg->id, sizeof(vg->id));
 
271
        }
 
272
 
 
273
        if (!vg_write(vg) || !vg_commit(vg))
 
274
                return ECMD_FAILED;
 
275
 
 
276
        backup(vg);
 
277
 
 
278
        log_print("Volume group \"%s\" successfully changed", vg->name);
 
279
 
 
280
        return ECMD_PROCESSED;
 
281
}
 
282
 
 
283
static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
 
284
                           struct volume_group *vg, int consistent,
 
285
                           void *handle)
 
286
{
 
287
        int r = ECMD_FAILED;
 
288
 
 
289
        if (!vg) {
 
290
                log_error("Unable to find volume group \"%s\"", vg_name);
 
291
                return ECMD_FAILED;
 
292
        }
 
293
 
 
294
        if (!consistent) {
 
295
                unlock_vg(cmd, vg_name);
 
296
                dev_close_all();
 
297
                log_error("Volume group \"%s\" inconsistent", vg_name);
 
298
                if (!(vg = recover_vg(cmd, vg_name, LCK_VG_WRITE)))
 
299
                        return ECMD_FAILED;
 
300
        }
 
301
 
 
302
        if (!(vg->status & LVM_WRITE) && !arg_count(cmd, available_ARG)) {
 
303
                log_error("Volume group \"%s\" is read-only", vg->name);
 
304
                return ECMD_FAILED;
 
305
        }
 
306
 
 
307
        if (vg->status & EXPORTED_VG) {
 
308
                log_error("Volume group \"%s\" is exported", vg_name);
 
309
                return ECMD_FAILED;
 
310
        }
 
311
 
 
312
        if (arg_count(cmd, available_ARG))
 
313
                r = _vgchange_available(cmd, vg);
 
314
 
 
315
        else if (arg_count(cmd, resizeable_ARG))
 
316
                r = _vgchange_resizeable(cmd, vg);
 
317
 
 
318
        else if (arg_count(cmd, logicalvolume_ARG))
 
319
                r = _vgchange_logicalvolume(cmd, vg);
 
320
 
 
321
        else if (arg_count(cmd, addtag_ARG))
 
322
                r = _vgchange_tag(cmd, vg, addtag_ARG);
 
323
 
 
324
        else if (arg_count(cmd, deltag_ARG))
 
325
                r = _vgchange_tag(cmd, vg, deltag_ARG);
 
326
 
 
327
        else if (arg_count(cmd, uuid_ARG))
 
328
                r = _vgchange_uuid(cmd, vg);
 
329
 
 
330
        else if (arg_count(cmd, alloc_ARG))
 
331
                r = _vgchange_alloc(cmd, vg);
 
332
 
 
333
        return r;
 
334
}
 
335
 
 
336
int vgchange(struct cmd_context *cmd, int argc, char **argv)
 
337
{
 
338
        if (!
 
339
            (arg_count(cmd, available_ARG) + arg_count(cmd, logicalvolume_ARG) +
 
340
             arg_count(cmd, resizeable_ARG) + arg_count(cmd, deltag_ARG) +
 
341
             arg_count(cmd, addtag_ARG) + arg_count(cmd, uuid_ARG) +
 
342
             arg_count(cmd, alloc_ARG))) {
 
343
                log_error("One of -a, -l, -x, --alloc, --addtag, --deltag "
 
344
                          "or --uuid required");
 
345
                return EINVALID_CMD_LINE;
 
346
        }
 
347
 
 
348
        /* FIXME Cope with several changes at once! */
 
349
        if (arg_count(cmd, available_ARG) + arg_count(cmd, logicalvolume_ARG) +
 
350
            arg_count(cmd, resizeable_ARG) + arg_count(cmd, deltag_ARG) +
 
351
            arg_count(cmd, addtag_ARG) + arg_count(cmd, alloc_ARG) +
 
352
            arg_count(cmd, uuid_ARG) > 1) {
 
353
                log_error("Only one of -a, -l, -x, --alloc, --addtag, --deltag "
 
354
                          "or --uuid allowed");
 
355
                return EINVALID_CMD_LINE;
 
356
        }
 
357
 
 
358
        if (arg_count(cmd, ignorelockingfailure_ARG) &&
 
359
            !arg_count(cmd, available_ARG)) {
 
360
                log_error("--ignorelockingfailure only available with -a");
 
361
                return EINVALID_CMD_LINE;
 
362
        }
 
363
 
 
364
        if (arg_count(cmd, available_ARG) == 1
 
365
            && arg_count(cmd, autobackup_ARG)) {
 
366
                log_error("-A option not necessary with -a option");
 
367
                return EINVALID_CMD_LINE;
 
368
        }
 
369
 
 
370
        return process_each_vg(cmd, argc, argv,
 
371
                               (arg_count(cmd, available_ARG)) ?
 
372
                               LCK_VG_READ : LCK_VG_WRITE, 0, NULL,
 
373
                               &vgchange_single);
 
374
}