186d7f5d3SJohn Marino /* $NetBSD: lvm_vg.c,v 1.1.1.1 2009/12/02 00:26:15 haad Exp $ */
286d7f5d3SJohn Marino
386d7f5d3SJohn Marino /*
486d7f5d3SJohn Marino * Copyright (C) 2008,2009 Red Hat, Inc. All rights reserved.
586d7f5d3SJohn Marino *
686d7f5d3SJohn Marino * This file is part of LVM2.
786d7f5d3SJohn Marino *
886d7f5d3SJohn Marino * This copyrighted material is made available to anyone wishing to use,
986d7f5d3SJohn Marino * modify, copy, or redistribute it subject to the terms and conditions
1086d7f5d3SJohn Marino * of the GNU Lesser General Public License v.2.1.
1186d7f5d3SJohn Marino *
1286d7f5d3SJohn Marino * You should have received a copy of the GNU Lesser General Public License
1386d7f5d3SJohn Marino * along with this program; if not, write to the Free Software Foundation,
1486d7f5d3SJohn Marino * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1586d7f5d3SJohn Marino */
1686d7f5d3SJohn Marino
1786d7f5d3SJohn Marino #include "lib.h"
1886d7f5d3SJohn Marino #include "lvm2app.h"
1986d7f5d3SJohn Marino #include "toolcontext.h"
2086d7f5d3SJohn Marino #include "metadata-exported.h"
2186d7f5d3SJohn Marino #include "archiver.h"
2286d7f5d3SJohn Marino #include "locking.h"
2386d7f5d3SJohn Marino #include "lvm-string.h"
2486d7f5d3SJohn Marino #include "lvmcache.h"
2586d7f5d3SJohn Marino #include "metadata.h"
2686d7f5d3SJohn Marino
2786d7f5d3SJohn Marino #include <errno.h>
2886d7f5d3SJohn Marino #include <string.h>
2986d7f5d3SJohn Marino
lvm_vg_create(lvm_t libh,const char * vg_name)3086d7f5d3SJohn Marino vg_t lvm_vg_create(lvm_t libh, const char *vg_name)
3186d7f5d3SJohn Marino {
3286d7f5d3SJohn Marino struct volume_group *vg;
3386d7f5d3SJohn Marino
3486d7f5d3SJohn Marino vg = vg_create((struct cmd_context *)libh, vg_name);
3586d7f5d3SJohn Marino /* FIXME: error handling is still TBD */
3686d7f5d3SJohn Marino if (vg_read_error(vg)) {
3786d7f5d3SJohn Marino vg_release(vg);
3886d7f5d3SJohn Marino return NULL;
3986d7f5d3SJohn Marino }
4086d7f5d3SJohn Marino vg->open_mode = 'w';
4186d7f5d3SJohn Marino return (vg_t) vg;
4286d7f5d3SJohn Marino }
4386d7f5d3SJohn Marino
lvm_vg_extend(vg_t vg,const char * device)4486d7f5d3SJohn Marino int lvm_vg_extend(vg_t vg, const char *device)
4586d7f5d3SJohn Marino {
4686d7f5d3SJohn Marino struct pvcreate_params pp;
4786d7f5d3SJohn Marino
4886d7f5d3SJohn Marino if (vg_read_error(vg))
4986d7f5d3SJohn Marino return -1;
5086d7f5d3SJohn Marino
5186d7f5d3SJohn Marino if (!vg_check_write_mode(vg))
5286d7f5d3SJohn Marino return -1;
5386d7f5d3SJohn Marino
5486d7f5d3SJohn Marino if (!lock_vol(vg->cmd, VG_ORPHANS, LCK_VG_WRITE)) {
5586d7f5d3SJohn Marino log_error("Can't get lock for orphan PVs");
5686d7f5d3SJohn Marino return -1;
5786d7f5d3SJohn Marino }
5886d7f5d3SJohn Marino
5986d7f5d3SJohn Marino pvcreate_params_set_defaults(&pp);
6086d7f5d3SJohn Marino if (!vg_extend(vg, 1, (char **) &device, &pp)) {
6186d7f5d3SJohn Marino unlock_vg(vg->cmd, VG_ORPHANS);
6286d7f5d3SJohn Marino return -1;
6386d7f5d3SJohn Marino }
6486d7f5d3SJohn Marino /*
6586d7f5d3SJohn Marino * FIXME: Either commit to disk, or keep holding VG_ORPHANS and
6686d7f5d3SJohn Marino * release in lvm_vg_close().
6786d7f5d3SJohn Marino */
6886d7f5d3SJohn Marino unlock_vg(vg->cmd, VG_ORPHANS);
6986d7f5d3SJohn Marino return 0;
7086d7f5d3SJohn Marino }
7186d7f5d3SJohn Marino
lvm_vg_reduce(vg_t vg,const char * device)7286d7f5d3SJohn Marino int lvm_vg_reduce(vg_t vg, const char *device)
7386d7f5d3SJohn Marino {
7486d7f5d3SJohn Marino if (vg_read_error(vg))
7586d7f5d3SJohn Marino return -1;
7686d7f5d3SJohn Marino if (!vg_check_write_mode(vg))
7786d7f5d3SJohn Marino return -1;
7886d7f5d3SJohn Marino
7986d7f5d3SJohn Marino if (!vg_reduce(vg, (char *)device))
8086d7f5d3SJohn Marino return -1;
8186d7f5d3SJohn Marino return 0;
8286d7f5d3SJohn Marino }
8386d7f5d3SJohn Marino
lvm_vg_set_extent_size(vg_t vg,uint32_t new_size)8486d7f5d3SJohn Marino int lvm_vg_set_extent_size(vg_t vg, uint32_t new_size)
8586d7f5d3SJohn Marino {
8686d7f5d3SJohn Marino if (vg_read_error(vg))
8786d7f5d3SJohn Marino return -1;
8886d7f5d3SJohn Marino if (!vg_check_write_mode(vg))
8986d7f5d3SJohn Marino return -1;
9086d7f5d3SJohn Marino
9186d7f5d3SJohn Marino if (!vg_set_extent_size(vg, new_size))
9286d7f5d3SJohn Marino return -1;
9386d7f5d3SJohn Marino return 0;
9486d7f5d3SJohn Marino }
9586d7f5d3SJohn Marino
lvm_vg_write(vg_t vg)9686d7f5d3SJohn Marino int lvm_vg_write(vg_t vg)
9786d7f5d3SJohn Marino {
9886d7f5d3SJohn Marino struct pv_list *pvl;
9986d7f5d3SJohn Marino
10086d7f5d3SJohn Marino if (vg_read_error(vg))
10186d7f5d3SJohn Marino return -1;
10286d7f5d3SJohn Marino if (!vg_check_write_mode(vg))
10386d7f5d3SJohn Marino return -1;
10486d7f5d3SJohn Marino
10586d7f5d3SJohn Marino if (dm_list_empty(&vg->pvs)) {
10686d7f5d3SJohn Marino if (!vg_remove(vg))
10786d7f5d3SJohn Marino return -1;
10886d7f5d3SJohn Marino return 0;
10986d7f5d3SJohn Marino }
11086d7f5d3SJohn Marino
11186d7f5d3SJohn Marino if (! dm_list_empty(&vg->removed_pvs)) {
11286d7f5d3SJohn Marino if (!lock_vol(vg->cmd, VG_ORPHANS, LCK_VG_WRITE)) {
11386d7f5d3SJohn Marino log_error("Can't get lock for orphan PVs");
11486d7f5d3SJohn Marino return 0;
11586d7f5d3SJohn Marino }
11686d7f5d3SJohn Marino }
11786d7f5d3SJohn Marino
11886d7f5d3SJohn Marino if (!archive(vg))
11986d7f5d3SJohn Marino return -1;
12086d7f5d3SJohn Marino
12186d7f5d3SJohn Marino /* Store VG on disk(s) */
12286d7f5d3SJohn Marino if (!vg_write(vg) || !vg_commit(vg))
12386d7f5d3SJohn Marino return -1;
12486d7f5d3SJohn Marino
12586d7f5d3SJohn Marino if (! dm_list_empty(&vg->removed_pvs)) {
12686d7f5d3SJohn Marino dm_list_iterate_items(pvl, &vg->removed_pvs) {
12786d7f5d3SJohn Marino pv_write_orphan(vg->cmd, pvl->pv);
12886d7f5d3SJohn Marino /* FIXME: do pvremove / label_remove()? */
12986d7f5d3SJohn Marino }
13086d7f5d3SJohn Marino dm_list_init(&vg->removed_pvs);
13186d7f5d3SJohn Marino unlock_vg(vg->cmd, VG_ORPHANS);
13286d7f5d3SJohn Marino }
13386d7f5d3SJohn Marino
13486d7f5d3SJohn Marino return 0;
13586d7f5d3SJohn Marino }
13686d7f5d3SJohn Marino
lvm_vg_close(vg_t vg)13786d7f5d3SJohn Marino int lvm_vg_close(vg_t vg)
13886d7f5d3SJohn Marino {
13986d7f5d3SJohn Marino if (vg_read_error(vg) == FAILED_LOCKING)
14086d7f5d3SJohn Marino vg_release(vg);
14186d7f5d3SJohn Marino else
14286d7f5d3SJohn Marino unlock_and_release_vg(vg->cmd, vg, vg->name);
14386d7f5d3SJohn Marino return 0;
14486d7f5d3SJohn Marino }
14586d7f5d3SJohn Marino
lvm_vg_remove(vg_t vg)14686d7f5d3SJohn Marino int lvm_vg_remove(vg_t vg)
14786d7f5d3SJohn Marino {
14886d7f5d3SJohn Marino if (vg_read_error(vg))
14986d7f5d3SJohn Marino return -1;
15086d7f5d3SJohn Marino if (!vg_check_write_mode(vg))
15186d7f5d3SJohn Marino return -1;
15286d7f5d3SJohn Marino
15386d7f5d3SJohn Marino if (!vg_remove_check(vg))
15486d7f5d3SJohn Marino return -1;
15586d7f5d3SJohn Marino
15686d7f5d3SJohn Marino return 0;
15786d7f5d3SJohn Marino }
15886d7f5d3SJohn Marino
lvm_vg_open(lvm_t libh,const char * vgname,const char * mode,uint32_t flags)15986d7f5d3SJohn Marino vg_t lvm_vg_open(lvm_t libh, const char *vgname, const char *mode,
16086d7f5d3SJohn Marino uint32_t flags)
16186d7f5d3SJohn Marino {
16286d7f5d3SJohn Marino uint32_t internal_flags = 0;
16386d7f5d3SJohn Marino struct volume_group *vg;
16486d7f5d3SJohn Marino
16586d7f5d3SJohn Marino if (!strncmp(mode, "w", 1))
16686d7f5d3SJohn Marino internal_flags |= READ_FOR_UPDATE;
16786d7f5d3SJohn Marino else if (strncmp(mode, "r", 1)) {
16886d7f5d3SJohn Marino log_errno(EINVAL, "Invalid VG open mode");
16986d7f5d3SJohn Marino return NULL;
17086d7f5d3SJohn Marino }
17186d7f5d3SJohn Marino
17286d7f5d3SJohn Marino vg = vg_read((struct cmd_context *)libh, vgname, NULL, internal_flags);
17386d7f5d3SJohn Marino if (vg_read_error(vg)) {
17486d7f5d3SJohn Marino /* FIXME: use log_errno either here in inside vg_read */
17586d7f5d3SJohn Marino vg_release(vg);
17686d7f5d3SJohn Marino return NULL;
17786d7f5d3SJohn Marino }
17886d7f5d3SJohn Marino /* FIXME: combine this with locking ? */
17986d7f5d3SJohn Marino vg->open_mode = mode[0];
18086d7f5d3SJohn Marino
18186d7f5d3SJohn Marino return (vg_t) vg;
18286d7f5d3SJohn Marino }
18386d7f5d3SJohn Marino
lvm_vg_list_pvs(vg_t vg)18486d7f5d3SJohn Marino struct dm_list *lvm_vg_list_pvs(vg_t vg)
18586d7f5d3SJohn Marino {
18686d7f5d3SJohn Marino struct dm_list *list;
18786d7f5d3SJohn Marino pv_list_t *pvs;
18886d7f5d3SJohn Marino struct pv_list *pvl;
18986d7f5d3SJohn Marino
19086d7f5d3SJohn Marino if (dm_list_empty(&vg->pvs))
19186d7f5d3SJohn Marino return NULL;
19286d7f5d3SJohn Marino
19386d7f5d3SJohn Marino if (!(list = dm_pool_zalloc(vg->vgmem, sizeof(*list)))) {
19486d7f5d3SJohn Marino log_errno(ENOMEM, "Memory allocation fail for dm_list.");
19586d7f5d3SJohn Marino return NULL;
19686d7f5d3SJohn Marino }
19786d7f5d3SJohn Marino dm_list_init(list);
19886d7f5d3SJohn Marino
19986d7f5d3SJohn Marino dm_list_iterate_items(pvl, &vg->pvs) {
20086d7f5d3SJohn Marino if (!(pvs = dm_pool_zalloc(vg->vgmem, sizeof(*pvs)))) {
20186d7f5d3SJohn Marino log_errno(ENOMEM,
20286d7f5d3SJohn Marino "Memory allocation fail for lvm_pv_list.");
20386d7f5d3SJohn Marino return NULL;
20486d7f5d3SJohn Marino }
20586d7f5d3SJohn Marino pvs->pv = pvl->pv;
20686d7f5d3SJohn Marino dm_list_add(list, &pvs->list);
20786d7f5d3SJohn Marino }
20886d7f5d3SJohn Marino return list;
20986d7f5d3SJohn Marino }
21086d7f5d3SJohn Marino
lvm_vg_list_lvs(vg_t vg)21186d7f5d3SJohn Marino struct dm_list *lvm_vg_list_lvs(vg_t vg)
21286d7f5d3SJohn Marino {
21386d7f5d3SJohn Marino struct dm_list *list;
21486d7f5d3SJohn Marino lv_list_t *lvs;
21586d7f5d3SJohn Marino struct lv_list *lvl;
21686d7f5d3SJohn Marino
21786d7f5d3SJohn Marino if (dm_list_empty(&vg->lvs))
21886d7f5d3SJohn Marino return NULL;
21986d7f5d3SJohn Marino
22086d7f5d3SJohn Marino if (!(list = dm_pool_zalloc(vg->vgmem, sizeof(*list)))) {
22186d7f5d3SJohn Marino log_errno(ENOMEM, "Memory allocation fail for dm_list.");
22286d7f5d3SJohn Marino return NULL;
22386d7f5d3SJohn Marino }
22486d7f5d3SJohn Marino dm_list_init(list);
22586d7f5d3SJohn Marino
22686d7f5d3SJohn Marino dm_list_iterate_items(lvl, &vg->lvs) {
22786d7f5d3SJohn Marino if (!(lvs = dm_pool_zalloc(vg->vgmem, sizeof(*lvs)))) {
22886d7f5d3SJohn Marino log_errno(ENOMEM,
22986d7f5d3SJohn Marino "Memory allocation fail for lvm_lv_list.");
23086d7f5d3SJohn Marino return NULL;
23186d7f5d3SJohn Marino }
23286d7f5d3SJohn Marino lvs->lv = lvl->lv;
23386d7f5d3SJohn Marino dm_list_add(list, &lvs->list);
23486d7f5d3SJohn Marino }
23586d7f5d3SJohn Marino return list;
23686d7f5d3SJohn Marino }
23786d7f5d3SJohn Marino
lvm_vg_get_seqno(const vg_t vg)23886d7f5d3SJohn Marino uint64_t lvm_vg_get_seqno(const vg_t vg)
23986d7f5d3SJohn Marino {
24086d7f5d3SJohn Marino return vg_seqno(vg);
24186d7f5d3SJohn Marino }
24286d7f5d3SJohn Marino
lvm_vg_is_clustered(const vg_t vg)24386d7f5d3SJohn Marino uint64_t lvm_vg_is_clustered(const vg_t vg)
24486d7f5d3SJohn Marino {
24586d7f5d3SJohn Marino return vg_is_clustered(vg);
24686d7f5d3SJohn Marino }
24786d7f5d3SJohn Marino
lvm_vg_is_exported(const vg_t vg)24886d7f5d3SJohn Marino uint64_t lvm_vg_is_exported(const vg_t vg)
24986d7f5d3SJohn Marino {
25086d7f5d3SJohn Marino return vg_is_exported(vg);
25186d7f5d3SJohn Marino }
25286d7f5d3SJohn Marino
lvm_vg_is_partial(const vg_t vg)25386d7f5d3SJohn Marino uint64_t lvm_vg_is_partial(const vg_t vg)
25486d7f5d3SJohn Marino {
25586d7f5d3SJohn Marino return (vg_missing_pv_count(vg) != 0);
25686d7f5d3SJohn Marino }
25786d7f5d3SJohn Marino
25886d7f5d3SJohn Marino /* FIXME: invalid handle? return INTMAX? */
lvm_vg_get_size(const vg_t vg)25986d7f5d3SJohn Marino uint64_t lvm_vg_get_size(const vg_t vg)
26086d7f5d3SJohn Marino {
26186d7f5d3SJohn Marino return vg_size(vg);
26286d7f5d3SJohn Marino }
26386d7f5d3SJohn Marino
lvm_vg_get_free_size(const vg_t vg)26486d7f5d3SJohn Marino uint64_t lvm_vg_get_free_size(const vg_t vg)
26586d7f5d3SJohn Marino {
26686d7f5d3SJohn Marino return vg_free(vg);
26786d7f5d3SJohn Marino }
26886d7f5d3SJohn Marino
lvm_vg_get_extent_size(const vg_t vg)26986d7f5d3SJohn Marino uint64_t lvm_vg_get_extent_size(const vg_t vg)
27086d7f5d3SJohn Marino {
27186d7f5d3SJohn Marino return vg_extent_size(vg);
27286d7f5d3SJohn Marino }
27386d7f5d3SJohn Marino
lvm_vg_get_extent_count(const vg_t vg)27486d7f5d3SJohn Marino uint64_t lvm_vg_get_extent_count(const vg_t vg)
27586d7f5d3SJohn Marino {
27686d7f5d3SJohn Marino return vg_extent_count(vg);
27786d7f5d3SJohn Marino }
27886d7f5d3SJohn Marino
lvm_vg_get_free_extent_count(const vg_t vg)27986d7f5d3SJohn Marino uint64_t lvm_vg_get_free_extent_count(const vg_t vg)
28086d7f5d3SJohn Marino {
28186d7f5d3SJohn Marino return vg_free_count(vg);
28286d7f5d3SJohn Marino }
28386d7f5d3SJohn Marino
lvm_vg_get_pv_count(const vg_t vg)28486d7f5d3SJohn Marino uint64_t lvm_vg_get_pv_count(const vg_t vg)
28586d7f5d3SJohn Marino {
28686d7f5d3SJohn Marino return vg_pv_count(vg);
28786d7f5d3SJohn Marino }
28886d7f5d3SJohn Marino
lvm_vg_get_max_pv(const vg_t vg)28986d7f5d3SJohn Marino uint64_t lvm_vg_get_max_pv(const vg_t vg)
29086d7f5d3SJohn Marino {
29186d7f5d3SJohn Marino return vg_max_pv(vg);
29286d7f5d3SJohn Marino }
29386d7f5d3SJohn Marino
lvm_vg_get_max_lv(const vg_t vg)29486d7f5d3SJohn Marino uint64_t lvm_vg_get_max_lv(const vg_t vg)
29586d7f5d3SJohn Marino {
29686d7f5d3SJohn Marino return vg_max_lv(vg);
29786d7f5d3SJohn Marino }
29886d7f5d3SJohn Marino
lvm_vg_get_uuid(const vg_t vg)29986d7f5d3SJohn Marino char *lvm_vg_get_uuid(const vg_t vg)
30086d7f5d3SJohn Marino {
30186d7f5d3SJohn Marino char uuid[64] __attribute((aligned(8)));
30286d7f5d3SJohn Marino
30386d7f5d3SJohn Marino if (!id_write_format(&vg->id, uuid, sizeof(uuid))) {
30486d7f5d3SJohn Marino log_error("Internal error converting uuid");
30586d7f5d3SJohn Marino return NULL;
30686d7f5d3SJohn Marino }
30786d7f5d3SJohn Marino return strndup((const char *)uuid, 64);
30886d7f5d3SJohn Marino }
30986d7f5d3SJohn Marino
lvm_vg_get_name(const vg_t vg)31086d7f5d3SJohn Marino char *lvm_vg_get_name(const vg_t vg)
31186d7f5d3SJohn Marino {
31286d7f5d3SJohn Marino char *name;
31386d7f5d3SJohn Marino
31486d7f5d3SJohn Marino name = dm_malloc(NAME_LEN + 1);
31586d7f5d3SJohn Marino strncpy(name, (const char *)vg->name, NAME_LEN);
31686d7f5d3SJohn Marino name[NAME_LEN] = '\0';
31786d7f5d3SJohn Marino return name;
31886d7f5d3SJohn Marino }
31986d7f5d3SJohn Marino
32086d7f5d3SJohn Marino /*
32186d7f5d3SJohn Marino * FIXME: These functions currently return hidden VGs. We should either filter
32286d7f5d3SJohn Marino * these out and not return them in the list, or export something like
32386d7f5d3SJohn Marino * is_orphan_vg and tell the caller to filter.
32486d7f5d3SJohn Marino */
lvm_list_vg_names(lvm_t libh)32586d7f5d3SJohn Marino struct dm_list *lvm_list_vg_names(lvm_t libh)
32686d7f5d3SJohn Marino {
32786d7f5d3SJohn Marino return get_vgnames((struct cmd_context *)libh, 0);
32886d7f5d3SJohn Marino }
32986d7f5d3SJohn Marino
lvm_list_vg_uuids(lvm_t libh)33086d7f5d3SJohn Marino struct dm_list *lvm_list_vg_uuids(lvm_t libh)
33186d7f5d3SJohn Marino {
33286d7f5d3SJohn Marino return get_vgids((struct cmd_context *)libh, 0);
33386d7f5d3SJohn Marino }
33486d7f5d3SJohn Marino
33586d7f5d3SJohn Marino /*
33686d7f5d3SJohn Marino * FIXME: Elaborate on when to use, side-effects, .cache file, etc
33786d7f5d3SJohn Marino */
lvm_scan(lvm_t libh)33886d7f5d3SJohn Marino int lvm_scan(lvm_t libh)
33986d7f5d3SJohn Marino {
34086d7f5d3SJohn Marino if (!lvmcache_label_scan((struct cmd_context *)libh, 2))
34186d7f5d3SJohn Marino return -1;
34286d7f5d3SJohn Marino return 0;
34386d7f5d3SJohn Marino }
344