1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-26 01:44:19 +03:00

Compare commits

...

33 Commits

Author SHA1 Message Date
Alasdair Kergon
81318c7968 Update 2003-09-16 16:15:07 +00:00
Alasdair Kergon
47a2c1c6e5 Fix read-only snapshot creation. 2003-09-16 16:08:05 +00:00
Alasdair Kergon
39cee65c6b Make dev_name optional to show details for all devices.
e.g. 'dmsetup info', 'dmsetup status -v', 'dmsetup table'
2003-09-16 14:13:51 +00:00
Alasdair Kergon
8582ec724e Improve segment merge/split code. 2003-09-15 18:22:50 +00:00
Alasdair Kergon
b0139682e8 Don't install the pvdata stub; update built-in mesg. 2003-09-15 15:05:23 +00:00
Alasdair Kergon
d39c475a6d Ensure more args aren't negative. 2003-09-15 15:04:39 +00:00
Alasdair Kergon
48f38354c6 Missing vg_commit() 2003-09-15 15:03:54 +00:00
Alasdair Kergon
cd5a920ed5 vgcfgrestore -l lists backup file too 2003-09-15 15:03:22 +00:00
Alasdair Kergon
71bc1f378d Prevent cmdline flags that take args getting repeated. 2003-09-15 15:02:24 +00:00
Alasdair Kergon
0ee6c31cff Missing ] in pvmove usage display 2003-09-15 15:01:36 +00:00
Alasdair Kergon
af89a9971e Generalise 'invalid chars' error mesg to just say 'invalid' 2003-09-15 15:01:00 +00:00
Alasdair Kergon
c718a8ef72 Correct order of consistency/exists checks. 2003-09-15 15:00:01 +00:00
Alasdair Kergon
8c8ad0faf0 Don't use !# in randomly-generated uuids. 2003-09-15 14:58:43 +00:00
Alasdair Kergon
314d5bbb7f Fix makefile install mesg displayed for man5 2003-09-15 14:57:15 +00:00
Alasdair Kergon
102255757a Additional validation of LV segments read from metadata. [HM] 2003-09-01 19:55:16 +00:00
Alasdair Kergon
914067a0d0 Fix unsafe list iteration in segment merge code. [HM] 2003-08-27 15:30:39 +00:00
Alasdair Kergon
06e3ae2536 Remove unnecessary file. 2003-08-26 21:12:45 +00:00
Alasdair Kergon
7f9b252556 Cope better when format functions are missing. 2003-08-26 21:12:06 +00:00
Alasdair Kergon
3d700e243f Log each command & args. 2003-08-26 21:00:05 +00:00
Alasdair Kergon
bcfc78ce11 Update. 2003-08-20 15:48:46 +00:00
Alasdair Kergon
09241765d5 Some tidyups and minor fixes. 2003-08-20 15:48:27 +00:00
Alasdair Kergon
671c83c265 Remove small hard-coded activation target line parameter limit. 2003-08-20 12:53:57 +00:00
Alasdair Kergon
772d28b766 Also allow pvmove --abort when pvmove mirror not active (e.g. after a reboot). 2003-08-18 17:21:51 +00:00
Alasdair Kergon
c26fcea58d Missing check for inconsistent VG in pvmove. 2003-08-18 13:52:43 +00:00
Alasdair Kergon
1e5e26dbff update 2003-07-18 00:41:04 +00:00
Alasdair Kergon
742fc54864 Accept signed numbers in config file. 2003-07-15 16:32:20 +00:00
Alasdair Kergon
49738f43c0 update 2003-07-15 01:30:18 +00:00
Alasdair Kergon
9f85f61010 Fix vgimport fix to work outside debug mode. 2003-07-15 01:26:24 +00:00
Alasdair Kergon
239f422039 update 2003-07-13 11:07:50 +00:00
Alasdair Kergon
67af3c37be Fix detection of exported LVM1 volume groups. 2003-07-13 11:07:25 +00:00
Alasdair Kergon
a9442385c4 vsn 2.00.02 (rc3) 2003-07-12 12:02:12 +00:00
Alasdair Kergon
8c9cd10b8b Restrict active lvchange -My with -f 2003-07-11 17:10:19 +00:00
Alasdair Kergon
72542059dd Fix inactive snapshot display. 2003-07-11 17:09:21 +00:00
49 changed files with 749 additions and 336 deletions

10
README
View File

@@ -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

View File

@@ -1 +1 @@
2.00.01-cvs (2003-07-06)
2.00.07-cvs (2003-09-16)

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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)) {

View File

@@ -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

View File

@@ -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,

View File

@@ -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

View File

@@ -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); */

View File

@@ -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,

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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.

View 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;
}

View File

@@ -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
View 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

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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.
*/

View File

@@ -30,6 +30,10 @@ int memlock(void)
{
return 0;
}
void memlock_init(struct cmd_context *cmd)
{
return;
}
#else /* DEVMAPPER_SUPPORT */

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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; \

View File

@@ -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

View File

@@ -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 \

View File

@@ -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;

View File

@@ -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" */

View File

@@ -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, &params);
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, &params);
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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);