Imported Upstream version 2.02.79
[platform/upstream/device-mapper.git] / liblvm / lvm_vg.c
1 /*
2  * Copyright (C) 2008,2009 Red Hat, Inc. All rights reserved.
3  *
4  * This file is part of LVM2.
5  *
6  * This copyrighted material is made available to anyone wishing to use,
7  * modify, copy, or redistribute it subject to the terms and conditions
8  * of the GNU Lesser General Public License v.2.1.
9  *
10  * You should have received a copy of the GNU Lesser General Public License
11  * along with this program; if not, write to the Free Software Foundation,
12  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
13  */
14
15 #include "lib.h"
16 #include "toolcontext.h"
17 #include "metadata.h"
18 #include "archiver.h"
19 #include "locking.h"
20 #include "lvmcache.h"
21 #include "lvm_misc.h"
22 #include "lvm2app.h"
23
24 int lvm_vg_add_tag(vg_t vg, const char *tag)
25 {
26         if (vg_read_error(vg))
27                 return -1;
28
29         if (!vg_check_write_mode(vg))
30                 return -1;
31
32         if (!vg_change_tag(vg, tag, 1))
33                 return -1;
34         return 0;
35 }
36
37
38 int lvm_vg_remove_tag(vg_t vg, const char *tag)
39 {
40         if (vg_read_error(vg))
41                 return -1;
42
43         if (!vg_check_write_mode(vg))
44                 return -1;
45
46         if (!vg_change_tag(vg, tag, 0))
47                 return -1;
48         return 0;
49 }
50
51
52 vg_t lvm_vg_create(lvm_t libh, const char *vg_name)
53 {
54         struct volume_group *vg;
55
56         vg = vg_create((struct cmd_context *)libh, vg_name);
57         /* FIXME: error handling is still TBD */
58         if (vg_read_error(vg)) {
59                 free_vg(vg);
60                 return NULL;
61         }
62         vg->open_mode = 'w';
63         return (vg_t) vg;
64 }
65
66 int lvm_vg_extend(vg_t vg, const char *device)
67 {
68         struct pvcreate_params pp;
69
70         if (vg_read_error(vg))
71                 return -1;
72
73         if (!vg_check_write_mode(vg))
74                 return -1;
75
76         if (!lock_vol(vg->cmd, VG_ORPHANS, LCK_VG_WRITE)) {
77                 log_error("Can't get lock for orphan PVs");
78                 return -1;
79         }
80
81         pvcreate_params_set_defaults(&pp);
82         if (!vg_extend(vg, 1, (char **) &device, &pp)) {
83                 unlock_vg(vg->cmd, VG_ORPHANS);
84                 return -1;
85         }
86         /*
87          * FIXME: Either commit to disk, or keep holding VG_ORPHANS and
88          * release in lvm_vg_close().
89          */
90         unlock_vg(vg->cmd, VG_ORPHANS);
91         return 0;
92 }
93
94 int lvm_vg_reduce(vg_t vg, const char *device)
95 {
96         if (vg_read_error(vg))
97                 return -1;
98         if (!vg_check_write_mode(vg))
99                 return -1;
100
101         if (!vg_reduce(vg, (char *)device))
102                 return -1;
103         return 0;
104 }
105
106 int lvm_vg_set_extent_size(vg_t vg, uint32_t new_size)
107 {
108         if (vg_read_error(vg))
109                 return -1;
110         if (!vg_check_write_mode(vg))
111                 return -1;
112
113         if (!vg_set_extent_size(vg, new_size / SECTOR_SIZE))
114                 return -1;
115         return 0;
116 }
117
118 int lvm_vg_write(vg_t vg)
119 {
120         struct pv_list *pvl;
121
122         if (vg_read_error(vg))
123                 return -1;
124         if (!vg_check_write_mode(vg))
125                 return -1;
126
127         if (dm_list_empty(&vg->pvs)) {
128                 if (!vg_remove(vg))
129                         return -1;
130                 return 0;
131         }
132
133         if (! dm_list_empty(&vg->removed_pvs)) {
134                 if (!lock_vol(vg->cmd, VG_ORPHANS, LCK_VG_WRITE)) {
135                         log_error("Can't get lock for orphan PVs");
136                         return 0;
137                 }
138         }
139
140         if (!archive(vg))
141                 return -1;
142
143         /* Store VG on disk(s) */
144         if (!vg_write(vg) || !vg_commit(vg))
145                 return -1;
146
147         if (! dm_list_empty(&vg->removed_pvs)) {
148                 dm_list_iterate_items(pvl, &vg->removed_pvs) {
149                         pv_write_orphan(vg->cmd, pvl->pv);
150                         /* FIXME: do pvremove / label_remove()? */
151                 }
152                 dm_list_init(&vg->removed_pvs);
153                 unlock_vg(vg->cmd, VG_ORPHANS);
154         }
155
156         return 0;
157 }
158
159 int lvm_vg_close(vg_t vg)
160 {
161         if (vg_read_error(vg) == FAILED_LOCKING)
162                 free_vg(vg);
163         else
164                 unlock_and_free_vg(vg->cmd, vg, vg->name);
165         return 0;
166 }
167
168 int lvm_vg_remove(vg_t vg)
169 {
170         if (vg_read_error(vg))
171                 return -1;
172         if (!vg_check_write_mode(vg))
173                 return -1;
174
175         if (!vg_remove_check(vg))
176                 return -1;
177
178         vg_remove_pvs(vg);
179
180         return 0;
181 }
182
183 vg_t lvm_vg_open(lvm_t libh, const char *vgname, const char *mode,
184                   uint32_t flags)
185 {
186         uint32_t internal_flags = 0;
187         struct volume_group *vg;
188
189         if (!strncmp(mode, "w", 1))
190                 internal_flags |= READ_FOR_UPDATE;
191         else if (strncmp(mode, "r", 1)) {
192                 log_errno(EINVAL, "Invalid VG open mode");
193                 return NULL;
194         }
195
196         vg = vg_read((struct cmd_context *)libh, vgname, NULL, internal_flags);
197         if (vg_read_error(vg)) {
198                 /* FIXME: use log_errno either here in inside vg_read */
199                 free_vg(vg);
200                 return NULL;
201         }
202         /* FIXME: combine this with locking ? */
203         vg->open_mode = mode[0];
204
205         return (vg_t) vg;
206 }
207
208 struct dm_list *lvm_vg_list_pvs(vg_t vg)
209 {
210         struct dm_list *list;
211         pv_list_t *pvs;
212         struct pv_list *pvl;
213
214         if (dm_list_empty(&vg->pvs))
215                 return NULL;
216
217         if (!(list = dm_pool_zalloc(vg->vgmem, sizeof(*list)))) {
218                 log_errno(ENOMEM, "Memory allocation fail for dm_list.");
219                 return NULL;
220         }
221         dm_list_init(list);
222
223         dm_list_iterate_items(pvl, &vg->pvs) {
224                 if (!(pvs = dm_pool_zalloc(vg->vgmem, sizeof(*pvs)))) {
225                         log_errno(ENOMEM,
226                                 "Memory allocation fail for lvm_pv_list.");
227                         return NULL;
228                 }
229                 pvs->pv = pvl->pv;
230                 dm_list_add(list, &pvs->list);
231         }
232         return list;
233 }
234
235 struct dm_list *lvm_vg_list_lvs(vg_t vg)
236 {
237         struct dm_list *list;
238         lv_list_t *lvs;
239         struct lv_list *lvl;
240
241         if (dm_list_empty(&vg->lvs))
242                 return NULL;
243
244         if (!(list = dm_pool_zalloc(vg->vgmem, sizeof(*list)))) {
245                 log_errno(ENOMEM, "Memory allocation fail for dm_list.");
246                 return NULL;
247         }
248         dm_list_init(list);
249
250         dm_list_iterate_items(lvl, &vg->lvs) {
251                 if (!(lvs = dm_pool_zalloc(vg->vgmem, sizeof(*lvs)))) {
252                         log_errno(ENOMEM,
253                                 "Memory allocation fail for lvm_lv_list.");
254                         return NULL;
255                 }
256                 lvs->lv = lvl->lv;
257                 dm_list_add(list, &lvs->list);
258         }
259         return list;
260 }
261
262 struct dm_list *lvm_vg_get_tags(const vg_t vg)
263 {
264         return tag_list_copy(vg->vgmem, &vg->tags);
265 }
266
267 uint64_t lvm_vg_get_seqno(const vg_t vg)
268 {
269         return vg_seqno(vg);
270 }
271
272 uint64_t lvm_vg_is_clustered(const vg_t vg)
273 {
274         return vg_is_clustered(vg);
275 }
276
277 uint64_t lvm_vg_is_exported(const vg_t vg)
278 {
279         return vg_is_exported(vg);
280 }
281
282 uint64_t lvm_vg_is_partial(const vg_t vg)
283 {
284         return (vg_missing_pv_count(vg) != 0);
285 }
286
287 /* FIXME: invalid handle? return INTMAX? */
288 uint64_t lvm_vg_get_size(const vg_t vg)
289 {
290         return SECTOR_SIZE * vg_size(vg);
291 }
292
293 uint64_t lvm_vg_get_free_size(const vg_t vg)
294 {
295         return SECTOR_SIZE * vg_free(vg);
296 }
297
298 uint64_t lvm_vg_get_extent_size(const vg_t vg)
299 {
300         return SECTOR_SIZE * vg_extent_size(vg);
301 }
302
303 uint64_t lvm_vg_get_extent_count(const vg_t vg)
304 {
305         return vg_extent_count(vg);
306 }
307
308 uint64_t lvm_vg_get_free_extent_count(const vg_t vg)
309 {
310         return vg_free_count(vg);
311 }
312
313 uint64_t lvm_vg_get_pv_count(const vg_t vg)
314 {
315         return vg_pv_count(vg);
316 }
317
318 uint64_t lvm_vg_get_max_pv(const vg_t vg)
319 {
320         return vg_max_pv(vg);
321 }
322
323 uint64_t lvm_vg_get_max_lv(const vg_t vg)
324 {
325         return vg_max_lv(vg);
326 }
327
328 const char *lvm_vg_get_uuid(const vg_t vg)
329 {
330         return vg_uuid_dup(vg);
331 }
332
333 const char *lvm_vg_get_name(const vg_t vg)
334 {
335         return dm_pool_strndup(vg->vgmem, (const char *)vg->name, NAME_LEN+1);
336 }
337
338
339 struct lvm_property_value lvm_vg_get_property(const vg_t vg, const char *name)
340 {
341         return get_property(NULL, vg, NULL, NULL, NULL, name);
342 }
343
344 int lvm_vg_set_property(const vg_t vg, const char *name,
345                         struct lvm_property_value *value)
346 {
347         return set_property(NULL, vg, NULL, name, value);
348 }
349
350 struct dm_list *lvm_list_vg_names(lvm_t libh)
351 {
352         return get_vgnames((struct cmd_context *)libh, 0);
353 }
354
355 struct dm_list *lvm_list_vg_uuids(lvm_t libh)
356 {
357         return get_vgids((struct cmd_context *)libh, 0);
358 }
359
360 /*
361  * FIXME: Elaborate on when to use, side-effects, .cache file, etc
362  */
363 int lvm_scan(lvm_t libh)
364 {
365         if (!lvmcache_label_scan((struct cmd_context *)libh, 2))
366                 return -1;
367         return 0;
368 }