mirror of
git://sourceware.org/git/lvm2.git
synced 2025-09-26 01:44:19 +03:00
Compare commits
33 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
81318c7968 | ||
|
47a2c1c6e5 | ||
|
39cee65c6b | ||
|
8582ec724e | ||
|
b0139682e8 | ||
|
d39c475a6d | ||
|
48f38354c6 | ||
|
cd5a920ed5 | ||
|
71bc1f378d | ||
|
0ee6c31cff | ||
|
af89a9971e | ||
|
c718a8ef72 | ||
|
8c8ad0faf0 | ||
|
314d5bbb7f | ||
|
102255757a | ||
|
914067a0d0 | ||
|
06e3ae2536 | ||
|
7f9b252556 | ||
|
3d700e243f | ||
|
bcfc78ce11 | ||
|
09241765d5 | ||
|
671c83c265 | ||
|
772d28b766 | ||
|
c26fcea58d | ||
|
1e5e26dbff | ||
|
742fc54864 | ||
|
49738f43c0 | ||
|
9f85f61010 | ||
|
239f422039 | ||
|
67af3c37be | ||
|
a9442385c4 | ||
|
8c9cd10b8b | ||
|
72542059dd |
10
README
10
README
@@ -1,13 +1,11 @@
|
||||
This directory contains a beta release of LVM2, the new version of
|
||||
the userland LVM tools designed for the new device-mapper for
|
||||
the Linux kernel.
|
||||
This directory contains LVM2, the new version of the userland LVM
|
||||
tools designed for the new device-mapper for the Linux kernel.
|
||||
|
||||
The device-mapper needs to be installed before compiling these LVM2 tools.
|
||||
|
||||
For more information about LVM2 read the WHATS_NEW file.
|
||||
Installation instructions are in INSTALL.
|
||||
|
||||
This is beta-quality software, released for testing purposes only.
|
||||
There is no warranty - see COPYING and COPYING.LIB.
|
||||
|
||||
Tarballs are available from:
|
||||
@@ -20,6 +18,6 @@ To access the CVS tree use:
|
||||
cvs -d :pserver:cvs@tech.sistina.com:/data/cvs checkout LVM2
|
||||
|
||||
Mailing list for discussion/bug reports etc.
|
||||
lvm-devel@sistina.com
|
||||
Subscribe from http://lists.sistina.com/mailman/listinfo/lvm-devel
|
||||
linux-lvm@sistina.com
|
||||
Subscribe from http://lists.sistina.com/mailman/listinfo/linux-lvm
|
||||
|
||||
|
@@ -25,6 +25,7 @@ to provide us with diagnostic information:
|
||||
log {
|
||||
file="/tmp/lvm2.log"
|
||||
level=7
|
||||
activation=1
|
||||
}
|
||||
|
||||
You should schedule regular backups of your configuration file and
|
||||
|
@@ -17,7 +17,6 @@
|
||||
../lib/filters/filter-regex.h
|
||||
../lib/filters/filter.h
|
||||
../lib/format1/format1.h
|
||||
../lib/format1/lvm1-label.h
|
||||
../lib/format_text/format-text.h
|
||||
../lib/label/label.h
|
||||
../lib/locking/locking.h
|
||||
|
@@ -41,6 +41,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define MAX_TARGET_PARAMSIZE 50000
|
||||
|
||||
enum {
|
||||
ACTIVE = 0,
|
||||
RELOAD = 1,
|
||||
@@ -529,7 +531,7 @@ static int _percent_run(struct dev_manager *dm, const char *name,
|
||||
else
|
||||
*percent = 100;
|
||||
|
||||
log_debug("Mirror percent: %f", *percent);
|
||||
log_debug("LV percent: %f", *percent);
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
@@ -765,10 +767,10 @@ static int _resume(struct dev_layer *dl)
|
||||
* Emit a target for a given segment.
|
||||
* FIXME: tidy this function.
|
||||
*/
|
||||
static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
|
||||
struct lv_segment *seg)
|
||||
static int _emit_target_line(struct dev_manager *dm, struct dm_task *dmt,
|
||||
struct lv_segment *seg, char *params,
|
||||
size_t paramsize)
|
||||
{
|
||||
char params[1024];
|
||||
uint64_t esize = seg->lv->vg->extent_size;
|
||||
uint32_t s, start_area = 0u, areas = seg->area_count;
|
||||
int w = 0, tw = 0;
|
||||
@@ -794,7 +796,7 @@ static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
|
||||
target = "linear";
|
||||
else if (areas > 1) {
|
||||
target = "striped";
|
||||
if ((tw = lvm_snprintf(params, sizeof(params), "%u %u ",
|
||||
if ((tw = lvm_snprintf(params, paramsize, "%u %u ",
|
||||
areas, seg->stripe_size)) < 0)
|
||||
goto error;
|
||||
w = tw;
|
||||
@@ -820,8 +822,7 @@ static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
|
||||
break;
|
||||
}
|
||||
target = "mirror";
|
||||
if ((tw = lvm_snprintf(params, sizeof(params),
|
||||
"core 1 %u %u ",
|
||||
if ((tw = lvm_snprintf(params, paramsize, "core 1 %u %u ",
|
||||
dm->mirror_region_size, areas)) < 0)
|
||||
goto error;
|
||||
w = tw;
|
||||
@@ -833,11 +834,11 @@ static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
|
||||
if ((seg->area[s].type == AREA_PV &&
|
||||
(!seg->area[s].u.pv.pv || !seg->area[s].u.pv.pv->dev)) ||
|
||||
(seg->area[s].type == AREA_LV && !seg->area[s].u.lv.lv))
|
||||
tw = lvm_snprintf(params + w, sizeof(params) - w,
|
||||
tw = lvm_snprintf(params + w, paramsize - w,
|
||||
"%s 0%s", dm->stripe_filler,
|
||||
trailing_space);
|
||||
else if (seg->area[s].type == AREA_PV)
|
||||
tw = lvm_snprintf(params + w, sizeof(params) - w,
|
||||
tw = lvm_snprintf(params + w, paramsize - w,
|
||||
"%s %" PRIu64 "%s",
|
||||
dev_name(seg->area[s].u.pv.pv->dev),
|
||||
(seg->area[s].u.pv.pv->pe_start +
|
||||
@@ -855,7 +856,7 @@ static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
|
||||
dl->info.major, dl->info.minor);
|
||||
return 0;
|
||||
}
|
||||
tw = lvm_snprintf(params + w, sizeof(params) - w,
|
||||
tw = lvm_snprintf(params + w, paramsize - w,
|
||||
"%s %" PRIu64 "%s", devbuf,
|
||||
esize * seg->area[s].u.lv.le,
|
||||
trailing_space);
|
||||
@@ -877,7 +878,37 @@ static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
|
||||
return 1;
|
||||
|
||||
error:
|
||||
log_error("Insufficient space in params[] to write target parameters.");
|
||||
log_debug("Insufficient space in params[%" PRIsize_t "] for target "
|
||||
"parameters.", paramsize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _emit_target(struct dev_manager *dm, struct dm_task *dmt,
|
||||
struct lv_segment *seg)
|
||||
{
|
||||
char *params;
|
||||
size_t paramsize = 4096;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
if (!(params = dbg_malloc(paramsize))) {
|
||||
log_error("Insufficient space for target parameters.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = _emit_target_line(dm, dmt, seg, params, paramsize);
|
||||
dbg_free(params);
|
||||
|
||||
if (!ret)
|
||||
stack;
|
||||
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
|
||||
paramsize *= 2;
|
||||
} while (paramsize < MAX_TARGET_PARAMSIZE);
|
||||
|
||||
log_error("Target parameter size too big. Aborting.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -985,8 +1016,8 @@ static int _populate_snapshot(struct dev_manager *dm,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (snprintf(params, sizeof(params), "%s %s P %d",
|
||||
devbufo, devbufc, s->chunk_size) == -1) {
|
||||
if (lvm_snprintf(params, sizeof(params), "%s %s P %d",
|
||||
devbufo, devbufc, s->chunk_size) == -1) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
@@ -1378,6 +1409,7 @@ static int _expand_snapshot(struct dev_manager *dm, struct logical_volume *lv,
|
||||
dl->populate = _populate_vanilla;
|
||||
_clear_flag(dl, VISIBLE);
|
||||
_clear_flag(dl, TOPLEVEL);
|
||||
_set_flag(dl, READWRITE);
|
||||
|
||||
cow_dlid = dl->dlid;
|
||||
|
||||
@@ -1589,8 +1621,7 @@ static int _resume_with_deps(struct dev_manager *dm, struct dev_layer *dl)
|
||||
}
|
||||
}
|
||||
|
||||
if (dl->info.exists & !_get_flag(dl, SUSPENDED) &&
|
||||
!_resume(dl)) {
|
||||
if (dl->info.exists & !_get_flag(dl, SUSPENDED) && !_resume(dl)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -502,7 +502,7 @@ static struct config_value *_value(struct parser *p)
|
||||
|
||||
static struct config_value *_type(struct parser *p)
|
||||
{
|
||||
/* [0-9]+ | [0-9]*\.[0-9]* | ".*" */
|
||||
/* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */
|
||||
struct config_value *v = _create_value(p);
|
||||
|
||||
if (!v)
|
||||
@@ -637,6 +637,8 @@ static void _get_token(struct parser *p, int tok_prev)
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '+':
|
||||
case '-':
|
||||
if (values_allowed) {
|
||||
p->te++;
|
||||
while ((p->te != p->fe) && (*p->te)) {
|
||||
|
@@ -63,26 +63,6 @@ static inline struct list *list_next(struct list *head, struct list *elem)
|
||||
return (list_end(head, elem) ? NULL : elem->n);
|
||||
}
|
||||
|
||||
#define list_iterate(v, head) \
|
||||
for (v = (head)->n; v != head; v = v->n)
|
||||
|
||||
#define list_uniterate(v, head, start) \
|
||||
for (v = (start)->p; v != head; v = v->p)
|
||||
|
||||
#define list_iterate_safe(v, t, head) \
|
||||
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
|
||||
|
||||
static inline unsigned int list_size(const struct list *head)
|
||||
{
|
||||
unsigned int s = 0;
|
||||
const struct list *v;
|
||||
|
||||
list_iterate(v, head)
|
||||
s++;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#define list_item(v, t) \
|
||||
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
|
||||
|
||||
@@ -96,4 +76,28 @@ static inline unsigned int list_size(const struct list *head)
|
||||
/* Given a known element in a known structure, locate the list head */
|
||||
#define list_head(v, t, e) struct_field(v, t, e, list)
|
||||
|
||||
#define list_iterate(v, head) \
|
||||
for (v = (head)->n; v != head; v = v->n)
|
||||
|
||||
#define list_uniterate(v, head, start) \
|
||||
for (v = (start)->p; v != head; v = v->p)
|
||||
|
||||
#define list_iterate_safe(v, t, head) \
|
||||
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
|
||||
|
||||
#define list_iterate_items(v, head) \
|
||||
for (v = list_item((head)->n, typeof(*v)); &v->list != (head); \
|
||||
v = list_item(v->list.n, typeof(*v)))
|
||||
|
||||
static inline unsigned int list_size(const struct list *head)
|
||||
{
|
||||
unsigned int s = 0;
|
||||
const struct list *v;
|
||||
|
||||
list_iterate(v, head)
|
||||
s++;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -390,6 +390,9 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
snap = list_item(slh, struct snapshot_list)->snapshot;
|
||||
snap_active = lv_snapshot_percent(snap->cow,
|
||||
&snap_percent);
|
||||
if (!snap_active || snap_percent < 0 ||
|
||||
snap_percent >= 100)
|
||||
snap_active = 0;
|
||||
log_print(" %s%s/%s [%s]",
|
||||
lv->vg->cmd->dev_dir, lv->vg->name,
|
||||
snap->cow->name,
|
||||
@@ -398,6 +401,8 @@ int lvdisplay_full(struct cmd_context *cmd, struct logical_volume *lv,
|
||||
snap = NULL;
|
||||
} else if ((snap = find_cow(lv))) {
|
||||
snap_active = lv_snapshot_percent(lv, &snap_percent);
|
||||
if (!snap_active || snap_percent < 0 || snap_percent >= 100)
|
||||
snap_active = 0;
|
||||
log_print("LV snapshot status %s destination for %s%s/%s",
|
||||
(snap_active > 0) ? "active" : "INACTIVE",
|
||||
lv->vg->cmd->dev_dir, lv->vg->name,
|
||||
|
@@ -22,7 +22,7 @@ TARGETS=liblvm2format1.so
|
||||
include ../../make.tmpl
|
||||
|
||||
|
||||
install: libformat1.so
|
||||
install: liblvm2format1.so
|
||||
$(INSTALL) -D -o $(OWNER) -g $(GROUP) -m 555 $(STRIP) $< \
|
||||
$(libdir)/liblvm2format1.so.$(LIB_VERSION)
|
||||
$(LN_S) -f liblvm2format1.so.$(LIB_VERSION) $(libdir)/liblvm2format1.so
|
||||
|
@@ -255,21 +255,22 @@ static int _read_extents(struct disk_list *data)
|
||||
/*
|
||||
* If exported, remove "PV_EXP" from end of VG name
|
||||
*/
|
||||
static void _munge_exported_vg(struct disk_list *data)
|
||||
void munge_exported_vg(struct pv_disk *pvd)
|
||||
{
|
||||
int l;
|
||||
size_t s;
|
||||
|
||||
/* Return if PV not in a VG or VG not exported */
|
||||
if ((!*data->pvd.vg_name) || !(data->vgd.vg_status & VG_EXPORTED))
|
||||
/* Return if PV not in a VG */
|
||||
if ((!*pvd->vg_name))
|
||||
return;
|
||||
/* FIXME also check vgd->status & VG_EXPORTED? */
|
||||
|
||||
l = strlen(data->pvd.vg_name);
|
||||
l = strlen(pvd->vg_name);
|
||||
s = sizeof(EXPORTED_TAG);
|
||||
if (!strncmp(data->pvd.vg_name + l - s + 1, EXPORTED_TAG, s))
|
||||
data->pvd.vg_name[l - s + 1] = '\0';
|
||||
if (!strncmp(pvd->vg_name + l - s + 1, EXPORTED_TAG, s))
|
||||
pvd->vg_name[l - s + 1] = '\0';
|
||||
|
||||
data->pvd.pv_status |= VG_EXPORTED;
|
||||
pvd->pv_status |= VG_EXPORTED;
|
||||
}
|
||||
|
||||
static struct disk_list *__read_disk(const struct format_type *fmt,
|
||||
@@ -295,6 +296,9 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* If VG is exported, set VG name back to the real name */
|
||||
munge_exported_vg(&dl->pvd);
|
||||
|
||||
if (!(info = lvmcache_add(fmt->labeller, dl->pvd.pv_uuid, dev,
|
||||
dl->pvd.vg_name, NULL)))
|
||||
stack;
|
||||
@@ -321,9 +325,6 @@ static struct disk_list *__read_disk(const struct format_type *fmt,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* If VG is exported, set VG name back to the real name */
|
||||
_munge_exported_vg(dl);
|
||||
|
||||
/* Update VG cache with what we found */
|
||||
/* vgcache_add(dl->pvd.vg_name, dl->vgd.vg_uuid, dev, fmt); */
|
||||
|
||||
|
@@ -224,6 +224,7 @@ int export_uuids(struct disk_list *dl, struct volume_group *vg);
|
||||
void export_numbers(struct list *pvds, struct volume_group *vg);
|
||||
|
||||
void export_pv_act(struct list *pvds);
|
||||
void munge_exported_vg(struct pv_disk *pvd);
|
||||
|
||||
/* blech */
|
||||
int get_free_vg_number(struct format_instance *fid, struct dev_filter *filter,
|
||||
|
@@ -16,6 +16,8 @@
|
||||
#include "lvm1-label.h"
|
||||
#include "format1.h"
|
||||
|
||||
#define FMT_LVM1_NAME "lvm1"
|
||||
|
||||
/* VG consistency checks */
|
||||
static int _check_vgs(struct list *pvs, int *partial)
|
||||
{
|
||||
@@ -75,9 +77,9 @@ static int _check_vgs(struct list *pvs, int *partial)
|
||||
}
|
||||
|
||||
/* On entry to fn, list known to be non-empty */
|
||||
if (pv_count != dl->vgd.pv_cur) {
|
||||
if (pv_count != first->vgd.pv_cur) {
|
||||
log_error("%d PV(s) found for VG %s: expected %d",
|
||||
pv_count, dl->pvd.vg_name, dl->vgd.pv_cur);
|
||||
pv_count, first->pvd.vg_name, first->vgd.pv_cur);
|
||||
if (!partial_mode())
|
||||
return 0;
|
||||
*partial = 1;
|
||||
|
@@ -9,8 +9,6 @@
|
||||
|
||||
#include "metadata.h"
|
||||
|
||||
#define FMT_LVM1_NAME "lvm1"
|
||||
|
||||
#ifdef LVM1_INTERNAL
|
||||
struct format_type *init_lvm1_format(struct cmd_context *cmd);
|
||||
#endif
|
||||
|
@@ -51,8 +51,11 @@ static int _read(struct labeller *l, struct device *dev, char *buf,
|
||||
struct pv_disk *pvd = (struct pv_disk *) buf;
|
||||
struct lvmcache_info *info;
|
||||
|
||||
if (!(info = lvmcache_add(l, pvd->pv_uuid, dev, pvd->vg_name, NULL)))
|
||||
munge_exported_vg(pvd);
|
||||
if (!(info = lvmcache_add(l, pvd->pv_uuid, dev, pvd->vg_name, NULL))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
*label = info->label;
|
||||
|
||||
info->device_size = xlate32(pvd->pv_size) << SECTOR_SHIFT;
|
||||
|
@@ -50,7 +50,7 @@ struct archive_file {
|
||||
/*
|
||||
* Extract vg name and version number from a filename.
|
||||
*/
|
||||
static int _split_vg(const char *filename, char *vg, size_t vg_size,
|
||||
static int _split_vg(const char *filename, char *vgname, size_t vg_size,
|
||||
uint32_t *ix)
|
||||
{
|
||||
size_t len, vg_len;
|
||||
@@ -74,8 +74,8 @@ static int _split_vg(const char *filename, char *vg, size_t vg_size,
|
||||
if (vg_len + 1 > vg_size)
|
||||
return 0;
|
||||
|
||||
strncpy(vg, filename, vg_len);
|
||||
vg[vg_len] = '\0';
|
||||
strncpy(vgname, filename, vg_len);
|
||||
vgname[vg_len] = '\0';
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -121,10 +121,10 @@ static char *_join(struct pool *mem, const char *dir, const char *name)
|
||||
* Returns a list of archive_files.
|
||||
*/
|
||||
static struct list *_scan_archive(struct pool *mem,
|
||||
const char *vg, const char *dir)
|
||||
const char *vgname, const char *dir)
|
||||
{
|
||||
int i, count, ix;
|
||||
char vg_name[64], *path;
|
||||
char vgname_found[64], *path;
|
||||
struct dirent **dirent;
|
||||
struct archive_file *af;
|
||||
struct list *results;
|
||||
@@ -148,12 +148,12 @@ static struct list *_scan_archive(struct pool *mem,
|
||||
continue;
|
||||
|
||||
/* check the name is the correct format */
|
||||
if (!_split_vg(dirent[i]->d_name, vg_name, sizeof(vg_name),
|
||||
&ix))
|
||||
if (!_split_vg(dirent[i]->d_name, vgname_found,
|
||||
sizeof(vgname_found), &ix))
|
||||
continue;
|
||||
|
||||
/* is it the vg we're interested in ? */
|
||||
if (strcmp(vg, vg_name))
|
||||
if (strcmp(vgname, vgname_found))
|
||||
continue;
|
||||
|
||||
if (!(path = _join(mem, dir, dirent[i]->d_name))) {
|
||||
@@ -304,7 +304,8 @@ static void _display_archive(struct cmd_context *cmd, struct archive_file *af)
|
||||
char *desc;
|
||||
void *context;
|
||||
|
||||
log_print("path:\t\t%s", af->path);
|
||||
log_print(" ");
|
||||
log_print("File:\t\t%s", af->path);
|
||||
|
||||
if (!(context = create_text_context(cmd, af->path, NULL)) ||
|
||||
!(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL,
|
||||
@@ -324,34 +325,50 @@ static void _display_archive(struct cmd_context *cmd, struct archive_file *af)
|
||||
return;
|
||||
}
|
||||
|
||||
log_print("description:\t%s", desc ? desc : "<No description>");
|
||||
log_print("time:\t\t%s", ctime(&when));
|
||||
log_print("VG name: \t%s", vg->name);
|
||||
log_print("Description:\t%s", desc ? desc : "<No description>");
|
||||
log_print("Backup Time:\t%s", ctime(&when));
|
||||
|
||||
pool_free(cmd->mem, vg);
|
||||
tf->fmt->ops->destroy_instance(tf);
|
||||
}
|
||||
|
||||
int archive_list(struct cmd_context *cmd, const char *dir, const char *vg)
|
||||
int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname)
|
||||
{
|
||||
struct list *archives, *ah;
|
||||
struct archive_file *af;
|
||||
|
||||
if (!(archives = _scan_archive(cmd->mem, vg, dir))) {
|
||||
if (!(archives = _scan_archive(cmd->mem, vgname, dir))) {
|
||||
log_err("Couldn't scan the archive directory (%s).", dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (list_empty(archives))
|
||||
log_print("No archives found.");
|
||||
log_print("No archives found in %s.", dir);
|
||||
|
||||
list_iterate(ah, archives) {
|
||||
af = list_item(ah, struct archive_file);
|
||||
|
||||
_display_archive(cmd, af);
|
||||
log_print(" ");
|
||||
}
|
||||
|
||||
pool_free(cmd->mem, archives);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname)
|
||||
{
|
||||
struct archive_file af;
|
||||
|
||||
if (!(af.path = _join(cmd->mem, dir, vgname))) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (path_exists(af.path))
|
||||
_display_archive(cmd, &af);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@@ -321,7 +321,6 @@ static int _print_pvs(struct formatter *f, struct volume_group *vg)
|
||||
_inc_indent(f);
|
||||
|
||||
list_iterate(pvh, &vg->pvs) {
|
||||
|
||||
pv = list_item(pvh, struct pv_list)->pv;
|
||||
|
||||
if (!(name = _get_pv_name(f, pv))) {
|
||||
@@ -522,7 +521,7 @@ static int _print_snapshots(struct formatter *f, struct volume_group *vg)
|
||||
|
||||
static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
||||
{
|
||||
struct list *lvh, *segh;
|
||||
struct list *lvh;
|
||||
struct logical_volume *lv;
|
||||
struct lv_segment *seg;
|
||||
char buffer[256];
|
||||
@@ -571,9 +570,7 @@ static int _print_lvs(struct formatter *f, struct volume_group *vg)
|
||||
f->nl(f);
|
||||
|
||||
seg_count = 1;
|
||||
list_iterate(segh, &lv->segments) {
|
||||
seg = list_item(segh, struct lv_segment);
|
||||
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
if (!_print_segment(f, vg, seg_count++, seg)) {
|
||||
stack;
|
||||
return 0;
|
||||
|
@@ -28,6 +28,9 @@
|
||||
#include <dirent.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define FMT_TEXT_NAME "lvm2"
|
||||
#define FMT_TEXT_ALIAS "text"
|
||||
|
||||
static struct format_instance *_create_text_instance(const struct format_type
|
||||
*fmt, const char *vgname,
|
||||
void *context);
|
||||
|
@@ -11,9 +11,6 @@
|
||||
#include "metadata.h"
|
||||
#include "pool.h"
|
||||
|
||||
#define FMT_TEXT_NAME "lvm2"
|
||||
#define FMT_TEXT_ALIAS "text"
|
||||
|
||||
/*
|
||||
* Archives a vg config. 'retain_days' is the minimum number of
|
||||
* days that an archive file must be held for. 'min_archives' is
|
||||
@@ -27,7 +24,8 @@ int archive_vg(struct volume_group *vg,
|
||||
/*
|
||||
* Displays a list of vg backups in a particular archive directory.
|
||||
*/
|
||||
int archive_list(struct cmd_context *cmd, const char *dir, const char *vg);
|
||||
int archive_list(struct cmd_context *cmd, const char *dir, const char *vgname);
|
||||
int backup_list(struct cmd_context *cmd, const char *dir, const char *vgname);
|
||||
|
||||
/*
|
||||
* The text format can read and write a volume_group to a file.
|
||||
|
@@ -56,8 +56,8 @@ static int _write(struct label *label, char *buf)
|
||||
}
|
||||
|
||||
/* NULL-termination */
|
||||
pvh_dlocn_xl->offset = xlate64(0);
|
||||
pvh_dlocn_xl->size = xlate64(0);
|
||||
pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
|
||||
pvh_dlocn_xl->size = xlate64(UINT64_C(0));
|
||||
pvh_dlocn_xl++;
|
||||
|
||||
/* List of metadata area header locations */
|
||||
@@ -74,8 +74,8 @@ static int _write(struct label *label, char *buf)
|
||||
}
|
||||
|
||||
/* NULL-termination */
|
||||
pvh_dlocn_xl->offset = xlate64(0);
|
||||
pvh_dlocn_xl->size = xlate64(0);
|
||||
pvh_dlocn_xl->offset = xlate64(UINT64_C(0));
|
||||
pvh_dlocn_xl->size = xlate64(UINT64_C(0));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@@ -280,6 +280,11 @@ int label_write(struct device *dev, struct label *label)
|
||||
struct label_header *lh = (struct label_header *) buf;
|
||||
int r = 1;
|
||||
|
||||
if (!label->labeller->ops->write) {
|
||||
log_err("Label handler does not support label writes");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((LABEL_SIZE + (label->sector << SECTOR_SHIFT)) > LABEL_SCAN_SIZE) {
|
||||
log_error("Label sector %" PRIu64 " beyond range (%ld)",
|
||||
label->sector, LABEL_SCAN_SECTORS);
|
||||
@@ -292,8 +297,10 @@ int label_write(struct device *dev, struct label *label)
|
||||
lh->sector_xl = xlate64(label->sector);
|
||||
lh->offset_xl = xlate32(sizeof(*lh));
|
||||
|
||||
if (!label->labeller->ops->write(label, buf))
|
||||
if (!label->labeller->ops->write(label, buf)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
lh->crc_xl = xlate32(calc_crc(INITIAL_CRC, &lh->offset_xl, LABEL_SIZE -
|
||||
((void *) &lh->offset_xl - (void *) lh)));
|
||||
@@ -327,7 +334,7 @@ int label_verify(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return l->ops->verify(l, buf, sector);
|
||||
return ((l->ops->verify) ? l->ops->verify(l, buf, sector) : 1);
|
||||
}
|
||||
|
||||
void label_destroy(struct label *label)
|
||||
|
14
lib/metadata/lv_alloc.h
Normal file
14
lib/metadata/lv_alloc.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) 2003 Sistina Software (UK) Limited.
|
||||
*
|
||||
* This file is released under the LGPL.
|
||||
*
|
||||
* This is the in core representation of a volume group and its
|
||||
* associated physical and logical volumes.
|
||||
*/
|
||||
|
||||
#ifndef _LVM_LV_ALLOC_H
|
||||
#include "pool.h"
|
||||
|
||||
struct lv_segment *alloc_lv_segment(struct pool *mem, uint32_t stripes);
|
||||
#endif
|
@@ -10,6 +10,7 @@
|
||||
#include "pv_map.h"
|
||||
#include "lvm-string.h"
|
||||
#include "toolcontext.h"
|
||||
#include "lv_alloc.h"
|
||||
|
||||
/*
|
||||
* These functions adjust the pe counts in pv's
|
||||
@@ -49,7 +50,7 @@ static void _put_extents(struct lv_segment *seg)
|
||||
}
|
||||
}
|
||||
|
||||
static struct lv_segment *_alloc_segment(struct pool *mem, uint32_t stripes)
|
||||
struct lv_segment *alloc_lv_segment(struct pool *mem, uint32_t stripes)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
uint32_t len = sizeof(*seg) + (stripes * sizeof(seg->area[0]));
|
||||
@@ -75,7 +76,7 @@ static int _alloc_stripe_area(struct logical_volume *lv, uint32_t stripes,
|
||||
if (smallest < area_len)
|
||||
area_len = smallest;
|
||||
|
||||
if (!(seg = _alloc_segment(lv->vg->cmd->mem, stripes))) {
|
||||
if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, stripes))) {
|
||||
log_err("Couldn't allocate new stripe segment.");
|
||||
return 0;
|
||||
}
|
||||
@@ -188,7 +189,7 @@ static int _alloc_linear_area(struct logical_volume *lv, uint32_t *ix,
|
||||
if (count > remaining)
|
||||
count = remaining;
|
||||
|
||||
if (!(seg = _alloc_segment(lv->vg->cmd->mem, 1))) {
|
||||
if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, 1))) {
|
||||
log_err("Couldn't allocate new stripe segment.");
|
||||
return 0;
|
||||
}
|
||||
@@ -224,7 +225,7 @@ static int _alloc_mirrored_area(struct logical_volume *lv, uint32_t *ix,
|
||||
if (count > remaining)
|
||||
count = remaining;
|
||||
|
||||
if (!(seg = _alloc_segment(lv->vg->cmd->mem, 2))) {
|
||||
if (!(seg = alloc_lv_segment(lv->vg->cmd->mem, 2))) {
|
||||
log_err("Couldn't allocate new mirrored segment.");
|
||||
return 0;
|
||||
}
|
||||
@@ -731,8 +732,11 @@ int lock_lvs(struct cmd_context *cmd, struct list *lvs, int flags)
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
if (!lock_vol(cmd, lv->lvid.s, flags)) {
|
||||
log_error("Failed to lock %s", lv->name);
|
||||
/* FIXME Only unlock the locked ones */
|
||||
unlock_lvs(cmd, lvs);
|
||||
list_uniterate(lvh, lvs, lvh) {
|
||||
lv = list_item(lvh, struct lv_list)->lv;
|
||||
unlock_lv(cmd, lv->lvid.s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@@ -6,38 +6,55 @@
|
||||
|
||||
#include "lib.h"
|
||||
#include "metadata.h"
|
||||
#include "toolcontext.h"
|
||||
#include "lv_alloc.h"
|
||||
|
||||
/*
|
||||
* Returns success if the segments were
|
||||
* successfully merged. If the do merge, 'first'
|
||||
* will be adjusted to contain both areas.
|
||||
* Test whether two segments could be merged by the current merging code
|
||||
*/
|
||||
static int _merge(struct lv_segment *first, struct lv_segment *second)
|
||||
static int _segments_compatible(struct lv_segment *first,
|
||||
struct lv_segment *second)
|
||||
{
|
||||
unsigned int s;
|
||||
uint32_t width;
|
||||
unsigned s;
|
||||
|
||||
if (!first ||
|
||||
(first->type != SEG_STRIPED) ||
|
||||
(first->type != second->type) ||
|
||||
/* FIXME Relax the seg type restriction */
|
||||
if (!first || !second ||
|
||||
(first->type != SEG_STRIPED) || (second->type != first->type) ||
|
||||
(first->area_count != second->area_count) ||
|
||||
(first->stripe_size != second->stripe_size))
|
||||
return 0;
|
||||
|
||||
for (s = 0; s < first->area_count; s++) {
|
||||
width = first->area_len;
|
||||
|
||||
/* FIXME Relax this to first type != second type ? */
|
||||
if (first->area[s].type != AREA_PV ||
|
||||
second->area[s].type != AREA_PV)
|
||||
/* FIXME Relax this to first area type != second area type */
|
||||
/* plus the additional AREA_LV checks needed */
|
||||
if ((first->area[s].type != AREA_PV) ||
|
||||
(second->area[s].type != AREA_PV))
|
||||
return 0;
|
||||
|
||||
width = first->area_len;
|
||||
|
||||
if ((first->area[s].u.pv.pv != second->area[s].u.pv.pv) ||
|
||||
(first->area[s].u.pv.pe + width != second->area[s].u.pv.pe))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* we should merge */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to merge two adjacent segments.
|
||||
* Currently only supports SEG_STRIPED on AREA_PV.
|
||||
* Returns success if successful, in which case 'first'
|
||||
* gets adjusted to contain both areas.
|
||||
*/
|
||||
static int _merge(struct lv_segment *first, struct lv_segment *second)
|
||||
{
|
||||
|
||||
if (!_segments_compatible(first, second))
|
||||
return 0;
|
||||
|
||||
first->len += second->len;
|
||||
first->area_len += second->area_len;
|
||||
|
||||
@@ -46,10 +63,10 @@ static int _merge(struct lv_segment *first, struct lv_segment *second)
|
||||
|
||||
int lv_merge_segments(struct logical_volume *lv)
|
||||
{
|
||||
struct list *segh;
|
||||
struct list *segh, *t;
|
||||
struct lv_segment *current, *prev = NULL;
|
||||
|
||||
list_iterate(segh, &lv->segments) {
|
||||
list_iterate_safe(segh, t, &lv->segments) {
|
||||
current = list_item(segh, struct lv_segment);
|
||||
|
||||
if (_merge(prev, current))
|
||||
@@ -61,7 +78,113 @@ int lv_merge_segments(struct logical_volume *lv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that an LV's segments are consecutive, complete and don't overlap.
|
||||
*/
|
||||
int lv_check_segments(struct logical_volume *lv)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
uint32_t le = 0;
|
||||
unsigned seg_count = 0;
|
||||
|
||||
list_iterate_items(seg, &lv->segments) {
|
||||
seg_count++;
|
||||
if (seg->le != le) {
|
||||
log_error("LV %s invalid: segment %u should begin at "
|
||||
"LE %" PRIu32 " (found %" PRIu32 ").",
|
||||
lv->name, seg_count, le, seg->le);
|
||||
return 0;
|
||||
}
|
||||
|
||||
le += seg->len;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Split the supplied segment at the supplied logical extent
|
||||
*/
|
||||
static int _lv_split_segment(struct logical_volume *lv, struct lv_segment *seg,
|
||||
uint32_t le)
|
||||
{
|
||||
size_t len;
|
||||
struct lv_segment *split_seg;
|
||||
uint32_t s;
|
||||
uint32_t offset = le - seg->le;
|
||||
|
||||
if (seg->type == SEG_SNAPSHOT) {
|
||||
log_error("Unable to split the snapshot segment at LE %" PRIu32
|
||||
" in LV %s", le, lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Clone the existing segment */
|
||||
if (!(split_seg = alloc_lv_segment(lv->vg->cmd->mem,
|
||||
seg->area_count))) {
|
||||
log_error("Couldn't allocate new LV segment.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = sizeof(*seg) + (seg->area_count * sizeof(seg->area[0]));
|
||||
memcpy(split_seg, seg, len);
|
||||
|
||||
/* In case of a striped segment, the offset has to be / stripes */
|
||||
if (seg->type == SEG_STRIPED)
|
||||
offset /= seg->area_count;
|
||||
|
||||
/* Adjust the PV mapping */
|
||||
for (s = 0; s < seg->area_count; s++) {
|
||||
/* Split area at the offset */
|
||||
switch (seg->area[s].type) {
|
||||
case AREA_LV:
|
||||
split_seg->area[s].u.lv.le =
|
||||
seg->area[s].u.lv.le + offset;
|
||||
break;
|
||||
|
||||
case AREA_PV:
|
||||
split_seg->area[s].u.pv.pe =
|
||||
seg->area[s].u.pv.pe + offset;
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("Unrecognised segment type %u",
|
||||
seg->area[s].type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
split_seg->area_len = seg->area_len - offset;
|
||||
seg->area_len = offset;
|
||||
|
||||
/* Add split off segment to the list _after_ the original one */
|
||||
list_add_h(&seg->list, &split_seg->list);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure there's a segment boundary at the given logical extent
|
||||
*/
|
||||
int lv_split_segment(struct logical_volume *lv, uint32_t le)
|
||||
{
|
||||
struct lv_segment *seg;
|
||||
|
||||
if (!(seg = find_seg_by_le(lv, le))) {
|
||||
log_error("Segment with extent %" PRIu32 " in LV %s not found",
|
||||
le, lv->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is a segment start already */
|
||||
if (le == seg->le)
|
||||
return 1;
|
||||
|
||||
if (!_lv_split_segment(lv, seg, le)) {
|
||||
stack;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@@ -217,7 +217,8 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (!vg->fid->fmt->ops->vg_setup(vg->fid, vg)) {
|
||||
if (vg->fid->fmt->ops->vg_setup &&
|
||||
!vg->fid->fmt->ops->vg_setup(vg->fid, vg)) {
|
||||
log_error("Format specific setup of volume group '%s' failed.",
|
||||
vg_name);
|
||||
goto bad;
|
||||
@@ -463,6 +464,19 @@ int vg_write(struct volume_group *vg)
|
||||
/* Write to each copy of the metadata area */
|
||||
list_iterate(mdah, &vg->fid->metadata_areas) {
|
||||
mda = list_item(mdah, struct metadata_area);
|
||||
if(!mda->ops->vg_write) {
|
||||
log_error("Format does not support writing volume"
|
||||
"group metadata areas");
|
||||
/* Revert */
|
||||
list_uniterate(mdah2, &vg->fid->metadata_areas, mdah) {
|
||||
mda = list_item(mdah2, struct metadata_area);
|
||||
if (mda->ops->vg_revert &&
|
||||
!mda->ops->vg_revert(vg->fid, vg, mda)) {
|
||||
stack;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (!mda->ops->vg_write(vg->fid, vg, mda)) {
|
||||
stack;
|
||||
/* Revert */
|
||||
@@ -666,7 +680,7 @@ struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname,
|
||||
|
||||
if ((correct_vg->status & PVMOVE) && !pvmove_mode()) {
|
||||
log_error("WARNING: Interrupted pvmove detected in "
|
||||
"volume group %s", vg->name);
|
||||
"volume group %s", correct_vg->name);
|
||||
log_error("Please restore the metadata by running "
|
||||
"vgcfgrestore.");
|
||||
return NULL;
|
||||
@@ -869,6 +883,11 @@ struct list *get_pvs(struct cmd_context *cmd)
|
||||
int pv_write(struct cmd_context *cmd, struct physical_volume *pv,
|
||||
struct list *mdas, int64_t label_sector)
|
||||
{
|
||||
if (!pv->fmt->ops->pv_write) {
|
||||
log_error("Format does not support writing physical volumes");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*pv->vg_name || pv->pe_alloc_count) {
|
||||
log_error("Assertion failed: can't _pv_write non-orphan PV "
|
||||
"(in VG %s)", pv->vg_name);
|
||||
|
@@ -468,6 +468,11 @@ int lv_check_segments(struct logical_volume *lv);
|
||||
*/
|
||||
int lv_merge_segments(struct logical_volume *lv);
|
||||
|
||||
/*
|
||||
* Ensure there's a segment boundary at a given LE, splitting if necessary
|
||||
*/
|
||||
int lv_split_segment(struct logical_volume *lv, uint32_t le);
|
||||
|
||||
/*
|
||||
* Useful functions for managing snapshots.
|
||||
*/
|
||||
|
@@ -30,6 +30,10 @@ int memlock(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void memlock_init(struct cmd_context *cmd)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#else /* DEVMAPPER_SUPPORT */
|
||||
|
||||
|
@@ -13,31 +13,43 @@
|
||||
# define xlate16(x) __cpu_to_le16((x))
|
||||
# define xlate32(x) __cpu_to_le32((x))
|
||||
# define xlate64(x) __cpu_to_le64((x))
|
||||
# define xlate16_be(x) __cpu_to_be16((x))
|
||||
# define xlate32_be(x) __cpu_to_be32((x))
|
||||
# define xlate64_be(x) __cpu_to_be64((x))
|
||||
#else
|
||||
# include <machine/endian.h>
|
||||
# if !defined(BYTE_ORDER) || \
|
||||
(BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN)
|
||||
# error "Undefined or unrecognised BYTE_ORDER";
|
||||
# endif
|
||||
# define __xlate16(x) (((x) & 0x00ffU) << 8 | \
|
||||
((x) & 0xff00U) >> 8)
|
||||
# define __xlate32(x) (((x) & 0x000000ffU) << 24 | \
|
||||
((x) & 0xff000000U) >> 24 | \
|
||||
((x) & 0x0000ff00U) << 8 | \
|
||||
((x) & 0x00ff0000U) >> 8)
|
||||
# define __xlate64(x) (((x) & 0x00000000000000ffU) << 56 | \
|
||||
((x) & 0xff00000000000000U) >> 56 | \
|
||||
((x) & 0x000000000000ff00U) << 40 | \
|
||||
((x) & 0x00ff000000000000U) >> 40 | \
|
||||
((x) & 0x0000000000ff0000U) << 24 | \
|
||||
((x) & 0x0000ff0000000000U) >> 24 | \
|
||||
((x) & 0x00000000ff000000U) << 8 | \
|
||||
((x) & 0x000000ff00000000U) >> 8)
|
||||
# if BYTE_ORDER == LITTLE_ENDIAN
|
||||
# define xlate16(x) (x)
|
||||
# define xlate32(x) (x)
|
||||
# define xlate64(x) (x)
|
||||
# define xlate16_be(x) __xlate16(x)
|
||||
# define xlate32_be(x) __xlate32(x)
|
||||
# define xlate64_be(x) __xlate64(x)
|
||||
# else
|
||||
# define xlate16(x) (((x) & 0x00ffU) << 8 | \
|
||||
((x) & 0xff00U) >> 8)
|
||||
# define xlate32(x) (((x) & 0x000000ffU) << 24 | \
|
||||
((x) & 0xff000000U) >> 24 | \
|
||||
((x) & 0x0000ff00U) << 8 | \
|
||||
((x) & 0x00ff0000U) >> 8)
|
||||
# define xlate64(x) (((x) & 0x00000000000000ffU) << 56 | \
|
||||
((x) & 0xff00000000000000U) >> 56 | \
|
||||
((x) & 0x000000000000ff00U) << 40 | \
|
||||
((x) & 0x00ff000000000000U) >> 40 | \
|
||||
((x) & 0x0000000000ff0000U) << 24 | \
|
||||
((x) & 0x0000ff0000000000U) >> 24 | \
|
||||
((x) & 0x00000000ff000000U) << 8 | \
|
||||
((x) & 0x000000ff00000000U) >> 8)
|
||||
# define xlate16(x) __xlate16(x)
|
||||
# define xlate32(x) __xlate32(x)
|
||||
# define xlate64(x) __xlate64(x)
|
||||
# define xlate16_be(x) (x)
|
||||
# define xlate32_be(x) (x)
|
||||
# define xlate64_be(x) (x)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
@@ -12,7 +12,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
static unsigned char _c[] =
|
||||
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#";
|
||||
|
||||
static int _built_inverse;
|
||||
static unsigned char _inverse_c[256];
|
||||
@@ -73,8 +73,12 @@ int id_create(struct id *id)
|
||||
}
|
||||
close(randomfile);
|
||||
|
||||
/*
|
||||
* Skip out the last 2 chars in randomized creation for LVM1
|
||||
* backwards compatibility.
|
||||
*/
|
||||
for (i = 0; i < len; i++)
|
||||
id->uuid[i] = _c[id->uuid[i] % (sizeof(_c) - 1)];
|
||||
id->uuid[i] = _c[id->uuid[i] % (sizeof(_c) - 3)];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@@ -63,26 +63,6 @@ static inline struct list *list_next(struct list *head, struct list *elem)
|
||||
return (list_end(head, elem) ? NULL : elem->n);
|
||||
}
|
||||
|
||||
#define list_iterate(v, head) \
|
||||
for (v = (head)->n; v != head; v = v->n)
|
||||
|
||||
#define list_uniterate(v, head, start) \
|
||||
for (v = (start)->p; v != head; v = v->p)
|
||||
|
||||
#define list_iterate_safe(v, t, head) \
|
||||
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
|
||||
|
||||
static inline unsigned int list_size(const struct list *head)
|
||||
{
|
||||
unsigned int s = 0;
|
||||
const struct list *v;
|
||||
|
||||
list_iterate(v, head)
|
||||
s++;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#define list_item(v, t) \
|
||||
((t *)((uintptr_t)(v) - (uintptr_t)&((t *) 0)->list))
|
||||
|
||||
@@ -96,4 +76,28 @@ static inline unsigned int list_size(const struct list *head)
|
||||
/* Given a known element in a known structure, locate the list head */
|
||||
#define list_head(v, t, e) struct_field(v, t, e, list)
|
||||
|
||||
#define list_iterate(v, head) \
|
||||
for (v = (head)->n; v != head; v = v->n)
|
||||
|
||||
#define list_uniterate(v, head, start) \
|
||||
for (v = (start)->p; v != head; v = v->p)
|
||||
|
||||
#define list_iterate_safe(v, t, head) \
|
||||
for (v = (head)->n, t = v->n; v != head; v = t, t = v->n)
|
||||
|
||||
#define list_iterate_items(v, head) \
|
||||
for (v = list_item((head)->n, typeof(*v)); &v->list != (head); \
|
||||
v = list_item(v->list.n, typeof(*v)))
|
||||
|
||||
static inline unsigned int list_size(const struct list *head)
|
||||
{
|
||||
unsigned int s = 0;
|
||||
const struct list *v;
|
||||
|
||||
list_iterate(v, head)
|
||||
s++;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -40,7 +40,7 @@ install:
|
||||
@INSTALL@ -D -o $(OWNER) -g $(GROUP) -m 444 $$f $(MAN8DIR)/$$f; \
|
||||
done
|
||||
|
||||
@echo "Installing $(MAN5) in $(MAN8DIR)"
|
||||
@echo "Installing $(MAN5) in $(MAN5DIR)"
|
||||
@for f in $(MAN5); \
|
||||
do \
|
||||
$(RM) $(MAN5DIR)/$$f; \
|
||||
|
18
man/pvmove.8
18
man/pvmove.8
@@ -3,9 +3,10 @@
|
||||
pvmove \- move physical extents
|
||||
.SH SYNOPSIS
|
||||
.B pvmove
|
||||
[\-\-abort]
|
||||
[\-d/\-\-debug] [\-h/\-\-help] [\-i/\-\-interval Seconds] [\-v/\-\-verbose]
|
||||
[\-n/\-\-name LogicalVolume] SourcePhysicalVolume
|
||||
[DestinationPhysicalVolume[:PE[-PE]...]...]
|
||||
[\-n/\-\-name LogicalVolume]
|
||||
[SourcePhysicalVolume [DestinationPhysicalVolume[:PE[-PE]...]...]]
|
||||
.SH DESCRIPTION
|
||||
.B pvmove
|
||||
allows you to move the allocated physical extents (PEs) on
|
||||
@@ -20,15 +21,16 @@ If no
|
||||
.I DestinationPhysicalVolume
|
||||
is specifed, the normal allocation rules for the volume group are used.
|
||||
|
||||
If \fBpvmove\fP gets interrupted for any reason, it will probably be
|
||||
necessary to run \fBvgcfgrestore\fP to restore the volume group's metadata to
|
||||
the state it was before the \fBpvmove\fP began.
|
||||
|
||||
\fBpvmove\fP locks the volume group and other LVM2 commands can't access
|
||||
the volume group metadata until \fBpvmove\fP has completed.
|
||||
If \fBpvmove\fP gets interrupted for any reason (e.g. the machine crashes)
|
||||
then run \fBpvmove\fP again without any PhysicalVolume arguments to
|
||||
continue with any moves that were in progress or use \fBpvmove --abort\fP to
|
||||
abort them.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.I \-\-abort
|
||||
Abort any moves currently in progress.
|
||||
.TP
|
||||
.I \-i, \-\-interval Seconds
|
||||
Report progress as a percentage at regular intervals.
|
||||
.TP
|
||||
|
@@ -81,7 +81,7 @@ lvm: $(OBJECTS) $(top_srcdir)/lib/liblvm.a
|
||||
|
||||
.commands: commands.h cmdnames.h Makefile
|
||||
$(CC) -E -P cmdnames.h 2> /dev/null | \
|
||||
egrep -v '^ *(|#.*|help|version) *$$' > .commands
|
||||
egrep -v '^ *(|#.*|help|pvdata|version) *$$' > .commands
|
||||
|
||||
install: $(TARGETS)
|
||||
$(INSTALL) -D -o $(OWNER) -g $(GROUP) -m 555 $(STRIP) lvm \
|
||||
|
@@ -14,6 +14,12 @@ static struct {
|
||||
|
||||
} _archive_params;
|
||||
|
||||
static struct {
|
||||
int enabled;
|
||||
char *dir;
|
||||
|
||||
} _backup_params;
|
||||
|
||||
int archive_init(const char *dir, unsigned int keep_days, unsigned int keep_min)
|
||||
{
|
||||
_archive_params.dir = NULL;
|
||||
@@ -103,15 +109,16 @@ int archive(struct volume_group *vg)
|
||||
|
||||
int archive_display(struct cmd_context *cmd, const char *vg_name)
|
||||
{
|
||||
return archive_list(cmd, _archive_params.dir, vg_name);
|
||||
int r1, r2;
|
||||
|
||||
init_partial(1);
|
||||
r1 = archive_list(cmd, _archive_params.dir, vg_name);
|
||||
r2 = backup_list(cmd, _backup_params.dir, vg_name);
|
||||
init_partial(0);
|
||||
|
||||
return r1 && r2;
|
||||
}
|
||||
|
||||
static struct {
|
||||
int enabled;
|
||||
char *dir;
|
||||
|
||||
} _backup_params;
|
||||
|
||||
int backup_init(const char *dir)
|
||||
{
|
||||
_backup_params.dir = NULL;
|
||||
|
@@ -54,6 +54,7 @@ xx(lvchange,
|
||||
"\t[-a|--available y|n]\n"
|
||||
"\t[-C|--contiguous y|n]\n"
|
||||
"\t[-d|--debug]\n"
|
||||
"\t[-f|--force]\n"
|
||||
"\t[-h|--help]\n"
|
||||
"\t[--ignorelockingfailure]\n"
|
||||
"\t[-M|--persistent y|n] [--major major] [--minor minor]\n"
|
||||
@@ -65,7 +66,7 @@ xx(lvchange,
|
||||
"\t[--version]" "\n"
|
||||
"\tLogicalVolume[Path] [LogicalVolume[Path]...]\n",
|
||||
|
||||
autobackup_ARG, available_ARG, contiguous_ARG,
|
||||
autobackup_ARG, available_ARG, contiguous_ARG, force_ARG,
|
||||
ignorelockingfailure_ARG, major_ARG, minor_ARG, partial_ARG, permission_ARG,
|
||||
persistent_ARG, readahead_ARG, test_ARG)
|
||||
|
||||
@@ -411,7 +412,7 @@ xx(pvmove,
|
||||
"\t[-t|--test]\n "
|
||||
"\t[-v|--verbose]\n "
|
||||
"\t[--version]\n"
|
||||
"\t[{-n|--name} LogicalVolume\n"
|
||||
"\t[{-n|--name} LogicalVolume]\n"
|
||||
/* "\t[{-n|--name} LogicalVolume[:LogicalExtent[-LogicalExtent]...]]\n" */
|
||||
"\tSourcePhysicalVolume\n"
|
||||
/* "\tSourcePhysicalVolume[:PhysicalExtent[-PhysicalExtent]...]}\n" */
|
||||
|
328
tools/dmsetup.c
328
tools/dmsetup.c
@@ -167,7 +167,7 @@ static int _load(int task, const char *name, const char *file, const char *uuid)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _create(int argc, char **argv)
|
||||
static int _create(int argc, char **argv, void *data)
|
||||
{
|
||||
if (argc == 1)
|
||||
return _load(DM_DEVICE_CREATE, argv[1], NULL, NULL);
|
||||
@@ -176,12 +176,12 @@ static int _create(int argc, char **argv)
|
||||
(argc == 3) ? argv[3] : NULL);
|
||||
}
|
||||
|
||||
static int _reload(int argc, char **argv)
|
||||
static int _reload(int argc, char **argv, void *data)
|
||||
{
|
||||
return _load(DM_DEVICE_RELOAD, argv[1], argv[2], NULL);
|
||||
}
|
||||
|
||||
static int _rename(int argc, char **argv)
|
||||
static int _rename(int argc, char **argv, void *data)
|
||||
{
|
||||
int r = 0;
|
||||
struct dm_task *dmt;
|
||||
@@ -206,7 +206,7 @@ static int _rename(int argc, char **argv)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _version(int argc, char **argv)
|
||||
static int _version(int argc, char **argv, void *data)
|
||||
{
|
||||
int r = 0;
|
||||
struct dm_task *dmt;
|
||||
@@ -258,155 +258,38 @@ static int _simple(int task, const char *name, int display)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _remove_all(int argc, char **argv)
|
||||
static int _remove_all(int argc, char **argv, void *data)
|
||||
{
|
||||
return _simple(DM_DEVICE_REMOVE_ALL, "", 0);
|
||||
}
|
||||
|
||||
static int _remove(int argc, char **argv)
|
||||
static int _remove(int argc, char **argv, void *data)
|
||||
{
|
||||
return _simple(DM_DEVICE_REMOVE, argv[1], 0);
|
||||
}
|
||||
|
||||
static int _suspend(int argc, char **argv)
|
||||
static int _suspend(int argc, char **argv, void *data)
|
||||
{
|
||||
return _simple(DM_DEVICE_SUSPEND, argv[1], 1);
|
||||
}
|
||||
|
||||
static int _resume(int argc, char **argv)
|
||||
static int _resume(int argc, char **argv, void *data)
|
||||
{
|
||||
return _simple(DM_DEVICE_RESUME, argv[1], 1);
|
||||
}
|
||||
|
||||
static int _clear(int argc, char **argv)
|
||||
static int _clear(int argc, char **argv, void *data)
|
||||
{
|
||||
return _simple(DM_DEVICE_CLEAR, argv[1], 1);
|
||||
}
|
||||
|
||||
static int _wait(int argc, char **argv)
|
||||
static int _wait(int argc, char **argv, void *data)
|
||||
{
|
||||
return _simple(DM_DEVICE_WAITEVENT, argv[1], 2);
|
||||
}
|
||||
|
||||
static int _status(int argc, char **argv)
|
||||
{
|
||||
int r = 0;
|
||||
struct dm_task *dmt;
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
int cmd;
|
||||
|
||||
if (!strcmp(argv[0], "status"))
|
||||
cmd = DM_DEVICE_STATUS;
|
||||
else
|
||||
cmd = DM_DEVICE_TABLE;
|
||||
|
||||
if (!(dmt = dm_task_create(cmd)))
|
||||
return 0;
|
||||
|
||||
if (!dm_task_set_name(dmt, argv[1]))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
if (_switches[VERBOSE_ARG])
|
||||
_display_info(dmt);
|
||||
|
||||
/* Fetch targets and print 'em */
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
if (target_type) {
|
||||
printf("%" PRIu64 " %" PRIu64 " %s %s\n",
|
||||
start, length, target_type, params);
|
||||
}
|
||||
} while (next);
|
||||
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
static int _info(int argc, char **argv)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
/* remove <dev_name> */
|
||||
struct dm_task *dmt;
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
|
||||
return 0;
|
||||
|
||||
if (!dm_task_set_name(dmt, argv[1]))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
_display_info(dmt);
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _deps(int argc, char **argv)
|
||||
{
|
||||
int r = 0;
|
||||
uint32_t i;
|
||||
struct dm_deps *deps;
|
||||
|
||||
/* remove <dev_name> */
|
||||
struct dm_task *dmt;
|
||||
struct dm_info info;
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
|
||||
return 0;
|
||||
|
||||
if (!dm_task_set_name(dmt, argv[1]))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_get_info(dmt, &info))
|
||||
goto out;
|
||||
|
||||
if (!(deps = dm_task_get_deps(dmt)))
|
||||
goto out;
|
||||
|
||||
if (!info.exists) {
|
||||
printf("Device does not exist.\n");
|
||||
r = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (_switches[VERBOSE_ARG])
|
||||
_display_info(dmt);
|
||||
|
||||
printf("%d dependencies\t:", deps->count);
|
||||
|
||||
for (i = 0; i < deps->count; i++)
|
||||
printf(" (%d, %d)",
|
||||
(int) MAJOR(deps->device[i]),
|
||||
(int) MINOR(deps->device[i]));
|
||||
printf("\n");
|
||||
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _ls(int argc, char **argv)
|
||||
static int _process_all(int argc, char **argv,
|
||||
int (*fn)(int argc, char **argv, void *data))
|
||||
{
|
||||
int r = 0;
|
||||
struct dm_names *names;
|
||||
@@ -431,8 +314,8 @@ static int _ls(int argc, char **argv)
|
||||
|
||||
do {
|
||||
names = (void *) names + next;
|
||||
printf("%s\t(%d, %d)\n", names->name,
|
||||
(int) MAJOR(names->dev), (int) MINOR(names->dev));
|
||||
if (!fn(argc, argv, (void *)names))
|
||||
r = 0;
|
||||
next = names->next;
|
||||
} while (next);
|
||||
|
||||
@@ -441,10 +324,181 @@ static int _ls(int argc, char **argv)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _status(int argc, char **argv, void *data)
|
||||
{
|
||||
int r = 0;
|
||||
struct dm_task *dmt;
|
||||
void *next = NULL;
|
||||
uint64_t start, length;
|
||||
char *target_type = NULL;
|
||||
char *params;
|
||||
int cmd;
|
||||
struct dm_names *names = (struct dm_names *)data;
|
||||
char *name;
|
||||
|
||||
if (argc == 1 && !data)
|
||||
return _process_all(argc, argv, _status);
|
||||
|
||||
if (data)
|
||||
name = names->name;
|
||||
else
|
||||
name = argv[1];
|
||||
|
||||
if (!strcmp(argv[0], "status"))
|
||||
cmd = DM_DEVICE_STATUS;
|
||||
else
|
||||
cmd = DM_DEVICE_TABLE;
|
||||
|
||||
if (!(dmt = dm_task_create(cmd)))
|
||||
return 0;
|
||||
|
||||
if (!dm_task_set_name(dmt, name))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
if (_switches[VERBOSE_ARG])
|
||||
_display_info(dmt);
|
||||
|
||||
/* Fetch targets and print 'em */
|
||||
do {
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target_type, ¶ms);
|
||||
if (data && !_switches[VERBOSE_ARG])
|
||||
printf("%s: ", name);
|
||||
if (target_type) {
|
||||
printf("%" PRIu64 " %" PRIu64 " %s %s\n",
|
||||
start, length, target_type, params);
|
||||
}
|
||||
} while (next);
|
||||
|
||||
if (data && _switches[VERBOSE_ARG])
|
||||
printf("\n");
|
||||
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
static int _info(int argc, char **argv, void *data)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
struct dm_task *dmt;
|
||||
struct dm_names *names = (struct dm_names *)data;
|
||||
char *name;
|
||||
|
||||
if (argc == 1 && !data)
|
||||
return _process_all(argc, argv, _info);
|
||||
|
||||
if (data)
|
||||
name = names->name;
|
||||
else
|
||||
name = argv[1];
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
|
||||
return 0;
|
||||
|
||||
if (!dm_task_set_name(dmt, name))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
_display_info(dmt);
|
||||
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _deps(int argc, char **argv, void *data)
|
||||
{
|
||||
int r = 0;
|
||||
uint32_t i;
|
||||
struct dm_deps *deps;
|
||||
struct dm_task *dmt;
|
||||
struct dm_info info;
|
||||
struct dm_names *names = (struct dm_names *)data;
|
||||
char *name;
|
||||
|
||||
if (argc == 1 && !data)
|
||||
return _process_all(argc, argv, _deps);
|
||||
|
||||
if (data)
|
||||
name = names->name;
|
||||
else
|
||||
name = argv[1];
|
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
|
||||
return 0;
|
||||
|
||||
if (!dm_task_set_name(dmt, name))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_run(dmt))
|
||||
goto out;
|
||||
|
||||
if (!dm_task_get_info(dmt, &info))
|
||||
goto out;
|
||||
|
||||
if (!(deps = dm_task_get_deps(dmt)))
|
||||
goto out;
|
||||
|
||||
if (!info.exists) {
|
||||
printf("Device does not exist.\n");
|
||||
r = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (_switches[VERBOSE_ARG])
|
||||
_display_info(dmt);
|
||||
|
||||
if (data && !_switches[VERBOSE_ARG])
|
||||
printf("%s: ", name);
|
||||
printf("%d dependencies\t:", deps->count);
|
||||
|
||||
for (i = 0; i < deps->count; i++)
|
||||
printf(" (%d, %d)",
|
||||
(int) MAJOR(deps->device[i]),
|
||||
(int) MINOR(deps->device[i]));
|
||||
printf("\n");
|
||||
|
||||
if (data && _switches[VERBOSE_ARG])
|
||||
printf("\n");
|
||||
|
||||
r = 1;
|
||||
|
||||
out:
|
||||
dm_task_destroy(dmt);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int _display_name(int argc, char **argv, void *data)
|
||||
{
|
||||
struct dm_names *names = (struct dm_names *)data;
|
||||
|
||||
printf("%s\t(%d, %d)\n", names->name,
|
||||
(int) MAJOR(names->dev), (int) MINOR(names->dev));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _ls(int argc, char **argv, void *data)
|
||||
{
|
||||
return _process_all(argc, argv, _display_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* dispatch table
|
||||
*/
|
||||
typedef int (*command_fn) (int argc, char **argv);
|
||||
typedef int (*command_fn) (int argc, char **argv, void *data);
|
||||
|
||||
struct command {
|
||||
const char *name;
|
||||
@@ -465,10 +519,10 @@ static struct command _commands[] = {
|
||||
{"reload", "<dev_name> <table_file>", 2, 2, _reload},
|
||||
{"rename", "<dev_name> <new_name>", 2, 2, _rename},
|
||||
{"ls", "", 0, 0, _ls},
|
||||
{"info", "<dev_name>", 1, 1, _info},
|
||||
{"deps", "<dev_name>", 1, 1, _deps},
|
||||
{"status", "<dev_name>", 1, 1, _status},
|
||||
{"table", "<dev_name>", 1, 1, _status},
|
||||
{"info", "[<dev_name>]", 0, 1, _info},
|
||||
{"deps", "[<dev_name>]", 0, 1, _deps},
|
||||
{"status", "[<dev_name>]", 0, 1, _status},
|
||||
{"table", "[<dev_name>]", 0, 1, _status},
|
||||
{"wait", "<dev_name>", 1, 1, _wait},
|
||||
{"version", "", 0, 0, _version},
|
||||
{NULL, NULL, 0, 0, NULL}
|
||||
@@ -575,7 +629,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
doit:
|
||||
if (!c->fn(argc, argv)) {
|
||||
if (!c->fn(argc, argv, NULL)) {
|
||||
fprintf(stderr, "Command failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
@@ -227,6 +227,7 @@ static int lvchange_readahead(struct cmd_context *cmd,
|
||||
static int lvchange_persistent(struct cmd_context *cmd,
|
||||
struct logical_volume *lv)
|
||||
{
|
||||
struct lvinfo info;
|
||||
|
||||
if (!strcmp(arg_str_value(cmd, persistent_ARG, "n"), "n")) {
|
||||
if (!(lv->status & FIXED_MINOR)) {
|
||||
@@ -248,8 +249,19 @@ static int lvchange_persistent(struct cmd_context *cmd,
|
||||
log_error("Major number must be specified with -My");
|
||||
return 0;
|
||||
}
|
||||
log_verbose("Ensuring %s is inactive. Reactivate with -ay.",
|
||||
lv->name);
|
||||
if (lv_info(lv, &info) && info.exists &&
|
||||
!arg_count(cmd, force_ARG)) {
|
||||
if (yes_no_prompt("Logical volume %s will be "
|
||||
"deactivated first. "
|
||||
"Continue? [y/n]: ",
|
||||
lv->name) == 'n') {
|
||||
log_print("%s device number not changed.",
|
||||
lv->name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
log_print("Ensuring %s is inactive. "
|
||||
"(Reactivate using lvchange -ay.)", lv->name);
|
||||
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_DEACTIVATE)) {
|
||||
log_error("%s: deactivation failed", lv->name);
|
||||
return 0;
|
||||
|
@@ -119,8 +119,8 @@ static int _read_name_params(struct lvcreate_params *lp,
|
||||
}
|
||||
|
||||
if (!validate_name(lp->lv_name)) {
|
||||
log_error("Logical volume name \"%s\" has invalid "
|
||||
"characters", lp->lv_name);
|
||||
log_error("Logical volume name \"%s\" is invalid",
|
||||
lp->lv_name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -148,12 +148,22 @@ static int _read_size_params(struct lvcreate_params *lp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (arg_count(cmd, extents_ARG))
|
||||
if (arg_count(cmd, extents_ARG)) {
|
||||
if (arg_sign_value(cmd, extents_ARG, 0) == SIGN_MINUS) {
|
||||
log_error("Negative number of extents is invalid");
|
||||
return 0;
|
||||
}
|
||||
lp->extents = arg_uint_value(cmd, extents_ARG, 0);
|
||||
}
|
||||
|
||||
/* Size returned in kilobyte units; held in sectors */
|
||||
if (arg_count(cmd, size_ARG))
|
||||
if (arg_count(cmd, size_ARG)) {
|
||||
if (arg_sign_value(cmd, size_ARG, 0) == SIGN_MINUS) {
|
||||
log_error("Negative size is invalid");
|
||||
return 0;
|
||||
}
|
||||
lp->size = arg_uint64_value(cmd, size_ARG, UINT64_C(0)) * 2;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -172,8 +182,13 @@ static int _read_stripe_params(struct lvcreate_params *lp,
|
||||
log_print("Redundant stripes argument: default is 1");
|
||||
}
|
||||
|
||||
if (arg_count(cmd, stripesize_ARG))
|
||||
if (arg_count(cmd, stripesize_ARG)) {
|
||||
if (arg_sign_value(cmd, stripesize_ARG, 0) == SIGN_MINUS) {
|
||||
log_error("Negative stripesize is invalid");
|
||||
return 0;
|
||||
}
|
||||
lp->stripe_size = 2 * arg_uint_value(cmd, stripesize_ARG, 0);
|
||||
}
|
||||
|
||||
if (lp->stripes == 1 && lp->stripe_size) {
|
||||
log_print("Ignoring stripesize argument with single stripe");
|
||||
@@ -222,6 +237,10 @@ static int _read_params(struct lvcreate_params *lp, struct cmd_context *cmd,
|
||||
log_error("-s and -Z are incompatible");
|
||||
return 0;
|
||||
}
|
||||
if (arg_sign_value(cmd, chunksize_ARG, 0) == SIGN_MINUS) {
|
||||
log_error("Negative chunk size is invalid");
|
||||
return 0;
|
||||
}
|
||||
lp->chunk_size = 2 * arg_uint_value(cmd, chunksize_ARG, 8);
|
||||
log_verbose("Setting chunksize to %d sectors.", lp->chunk_size);
|
||||
} else {
|
||||
@@ -434,6 +453,8 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
"supported yet");
|
||||
return 0;
|
||||
}
|
||||
/* Must zero cow */
|
||||
status |= LVM_WRITE;
|
||||
}
|
||||
|
||||
if (!(lv = lv_create(vg->fid, lp->lv_name, status, alloc,
|
||||
@@ -493,6 +514,9 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp)
|
||||
}
|
||||
|
||||
if (lp->snapshot) {
|
||||
/* Reset permission after zeroing */
|
||||
if (!(lp->permission & LVM_WRITE))
|
||||
lv->status &= ~LVM_WRITE;
|
||||
if (!lock_vol(cmd, lv->lvid.s, LCK_LV_DEACTIVATE)) {
|
||||
log_err("Couldn't unlock snapshot.");
|
||||
return 0;
|
||||
|
11
tools/lvm.c
11
tools/lvm.c
@@ -485,6 +485,15 @@ static int _process_command_line(struct cmd_context *cmd, int *argc,
|
||||
}
|
||||
|
||||
if (a->fn) {
|
||||
if (a->count) {
|
||||
log_error("Option%s%c%s%s may not be repeated",
|
||||
a->short_arg ? " -" : "",
|
||||
a->short_arg ? : ' ',
|
||||
(a->short_arg && a->long_arg) ?
|
||||
"/" : "",
|
||||
a->long_arg ? : "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!optarg) {
|
||||
log_error("Option requires argument.");
|
||||
@@ -714,6 +723,8 @@ static int _run_command(struct cmd_context *cmd, int argc, char **argv)
|
||||
if (!(cmd->cmd_line = _copy_command_line(cmd, argc, argv)))
|
||||
return ECMD_FAILED;
|
||||
|
||||
log_debug("Processing: %s", cmd->cmd_line);
|
||||
|
||||
if (!(cmd->command = _find_command(argv[0])))
|
||||
return ENO_SUCH_CMD;
|
||||
|
||||
|
@@ -96,8 +96,7 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
|
||||
}
|
||||
|
||||
if (!validate_name(lv_name_new)) {
|
||||
log_error
|
||||
("New logical volume name \"%s\" has invalid characters",
|
||||
log_error("New logical volume name \"%s\" is invalid",
|
||||
lv_name_new);
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
@@ -133,6 +133,10 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
|
||||
}
|
||||
|
||||
if (arg_count(cmd, stripesize_ARG)) {
|
||||
if (arg_sign_value(cmd, stripesize_ARG, 0) == SIGN_MINUS) {
|
||||
log_error("Stripesize may not be negative.");
|
||||
goto error;
|
||||
}
|
||||
if (vg->fid->fmt->features & FMT_SEGMENTS)
|
||||
ssize = 2 * arg_uint_value(cmd, stripesize_ARG, 0);
|
||||
else
|
||||
|
@@ -130,8 +130,16 @@ static void pvcreate_single(struct cmd_context *cmd, const char *pv_name,
|
||||
if (!pvcreate_check(cmd, pv_name))
|
||||
goto error;
|
||||
|
||||
if (arg_sign_value(cmd, physicalvolumesize_ARG, 0) == SIGN_MINUS) {
|
||||
log_error("Physical volume size may not be negative");
|
||||
goto error;
|
||||
}
|
||||
size = arg_uint64_value(cmd, physicalvolumesize_ARG, UINT64_C(0)) * 2;
|
||||
|
||||
if (arg_sign_value(cmd, metadatasize_ARG, 0) == SIGN_MINUS) {
|
||||
log_error("Metadata size may not be negative");
|
||||
goto error;
|
||||
}
|
||||
pvmetadatasize = arg_uint64_value(cmd, metadatasize_ARG, UINT64_C(0))
|
||||
* 2;
|
||||
if (!pvmetadatasize)
|
||||
|
@@ -182,7 +182,7 @@ static struct list *_get_allocatable_pvs(struct cmd_context *cmd, int argc,
|
||||
pvl = list_item(pvh, struct pv_list);
|
||||
if ((pvl->pv->dev == pv->dev) ||
|
||||
(pvl->pv->pe_count == pvl->pv->pe_alloc_count))
|
||||
list_del(&pvl->list);
|
||||
list_del(&pvl->list);
|
||||
}
|
||||
|
||||
if (list_empty(allocatable_pvs)) {
|
||||
@@ -483,6 +483,16 @@ static int _check_pvmove_status(struct cmd_context *cmd,
|
||||
|
||||
*finished = 1;
|
||||
|
||||
if (parms->aborting) {
|
||||
if (!(lvs_changed = lvs_using_lv(cmd, vg, lv_mirr))) {
|
||||
log_error("Failed to generate list of moved LVs: "
|
||||
"can't abort.");
|
||||
return 0;
|
||||
}
|
||||
_finish_pvmove(cmd, vg, lv_mirr, lvs_changed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!lv_mirror_percent(lv_mirr, !parms->interval, &segment_percent,
|
||||
&event_nr)) {
|
||||
log_error("ABORTING: Mirror percentage check failed.");
|
||||
@@ -495,7 +505,7 @@ static int _check_pvmove_status(struct cmd_context *cmd,
|
||||
else
|
||||
log_verbose("%s: Moved: %.1f%%", pv_name, overall_percent);
|
||||
|
||||
if (segment_percent < 100.0 && !parms->aborting) {
|
||||
if (segment_percent < 100.0) {
|
||||
*finished = 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -505,11 +515,6 @@ static int _check_pvmove_status(struct cmd_context *cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (parms->aborting) {
|
||||
_finish_pvmove(cmd, vg, lv_mirr, lvs_changed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (overall_percent >= 100.0) {
|
||||
if (!_finish_pvmove(cmd, vg, lv_mirr, lvs_changed))
|
||||
return 0;
|
||||
@@ -576,6 +581,17 @@ static int _poll_pvmove_vgs(struct cmd_context *cmd, const char *vgname,
|
||||
struct physical_volume *pv;
|
||||
int finished;
|
||||
|
||||
if (!vg) {
|
||||
log_error("Couldn't read volume group %s", vgname);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!consistent) {
|
||||
log_error("Volume Group %s inconsistent - skipping", vgname);
|
||||
/* FIXME Should we silently recover it here or not? */
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (vg->status & EXPORTED_VG) {
|
||||
log_error("Volume group \"%s\" is exported", vg->name);
|
||||
return ECMD_FAILED;
|
||||
@@ -623,9 +639,11 @@ int pvmove_poll(struct cmd_context *cmd, const char *pv_name,
|
||||
log_verbose("Checking progress every %u seconds",
|
||||
parms.interval);
|
||||
|
||||
if (parms.interval == 0) {
|
||||
parms.interval = DEFAULT_INTERVAL;
|
||||
if (!parms.interval) {
|
||||
parms.progress_display = 0;
|
||||
|
||||
if (!pv_name)
|
||||
parms.interval = DEFAULT_INTERVAL;
|
||||
}
|
||||
|
||||
if (parms.background) {
|
||||
@@ -653,8 +671,9 @@ int pvmove(struct cmd_context *cmd, int argc, char **argv)
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if ((ret = _set_up_pvmove(cmd, pv_name, argc, argv)) !=
|
||||
ECMD_PROCESSED) {
|
||||
if (!arg_count(cmd, abort_ARG) &&
|
||||
(ret = _set_up_pvmove(cmd, pv_name, argc, argv)) !=
|
||||
ECMD_PROCESSED) {
|
||||
stack;
|
||||
return ret;
|
||||
}
|
||||
|
10
tools/stub.h
10
tools/stub.h
@@ -6,9 +6,17 @@
|
||||
|
||||
#define unimplemented \
|
||||
{ log_error("Command not implemented yet."); return ECMD_FAILED;}
|
||||
|
||||
/*int e2fsadm(struct cmd_context *cmd, int argc, char **argv) unimplemented*/
|
||||
int lvmsadc(struct cmd_context *cmd, int argc, char **argv) unimplemented
|
||||
int lvmsar(struct cmd_context *cmd, int argc, char **argv) unimplemented
|
||||
int pvdata(struct cmd_context *cmd, int argc, char **argv) unimplemented
|
||||
int pvresize(struct cmd_context *cmd, int argc, char **argv) unimplemented
|
||||
int vgmknodes(struct cmd_context *cmd, int argc, char **argv) unimplemented
|
||||
|
||||
int pvdata(struct cmd_context *cmd, int argc, char **argv) {
|
||||
log_error("There's no 'pvdata' command in LVM2.");
|
||||
log_error("Use lvs, pvs, vgs instead; or use vgcfgbackup and read the text file backup.");
|
||||
log_error("Metadata in LVM1 format can still be displayed using LVM1's pvdata command.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
|
@@ -21,8 +21,7 @@ int vgcfgrestore(struct cmd_context *cmd, int argc, char **argv)
|
||||
vg_name += strlen(cmd->dev_dir);
|
||||
|
||||
if (!validate_name(vg_name)) {
|
||||
log_error("Volume group name \"%s\" has invalid characters",
|
||||
vg_name);
|
||||
log_error("Volume group name \"%s\" is invalid", vg_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
|
@@ -23,13 +23,13 @@
|
||||
static int vgck_single(struct cmd_context *cmd, const char *vg_name,
|
||||
struct volume_group *vg, int consistent, void *handle)
|
||||
{
|
||||
if (!consistent) {
|
||||
log_error("Volume group \"%s\" inconsistent", vg_name);
|
||||
if (!vg) {
|
||||
log_error("Volume group \"%s\" not found", vg_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!vg) {
|
||||
log_error("Volume group \"%s\" not found", vg_name);
|
||||
if (!consistent) {
|
||||
log_error("Volume group \"%s\" inconsistent", vg_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
|
@@ -62,6 +62,11 @@ static int vgconvert_single(struct cmd_context *cmd, const char *vg_name,
|
||||
}
|
||||
|
||||
if (cmd->fmt->features & FMT_MDAS) {
|
||||
if (arg_sign_value(cmd, metadatasize_ARG, 0) == SIGN_MINUS) {
|
||||
log_error("Metadata size may not be negative");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
pvmetadatasize = arg_uint64_value(cmd, metadatasize_ARG,
|
||||
UINT64_C(0)) * 2;
|
||||
if (!pvmetadatasize)
|
||||
|
@@ -49,6 +49,11 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
|
||||
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;
|
||||
@@ -74,8 +79,7 @@ int vgcreate(struct cmd_context *cmd, int argc, char **argv)
|
||||
}
|
||||
|
||||
if (!validate_name(vg_name)) {
|
||||
log_error("New volume group name \"%s\" has invalid characters",
|
||||
vg_name);
|
||||
log_error("New volume group name \"%s\" is invalid", vg_name);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
|
@@ -57,7 +57,7 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
|
||||
}
|
||||
|
||||
if (!validate_name(vg_name_new)) {
|
||||
log_error("New volume group name \"%s\" has invalid characters",
|
||||
log_error("New volume group name \"%s\" is invalid",
|
||||
vg_name_new);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
@@ -279,7 +279,7 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
|
||||
|
||||
vg_to->status &= ~EXPORTED_VG;
|
||||
|
||||
if (!vg_write(vg_to) || !vg_write(vg_to))
|
||||
if (!vg_write(vg_to) || !vg_commit(vg_to))
|
||||
goto error;
|
||||
|
||||
backup(vg_to);
|
||||
|
Reference in New Issue
Block a user