1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-12-27 00:23:49 +03:00

Compare commits

...

23 Commits

Author SHA1 Message Date
Alasdair Kergon
83edf68ff9 pre-release 2007-02-13 16:12:24 +00:00
Alasdair Kergon
c7588f91dd Correct -b and -P on a couple of man pages.
Add global/units to example.conf.
2007-02-13 16:04:01 +00:00
Alasdair Kergon
30b432adc5 Fix loading of segment_libraries. [gentoo] 2007-02-08 17:31:02 +00:00
Alasdair Kergon
7c9733eb5d If a PV reappears after it was removed from its VG, make it an orphan. 2007-02-07 13:29:52 +00:00
Alasdair Kergon
a223c3fea3 Improve dmeventd messaging protocol: drain pipe and tag messages. 2007-02-02 17:08:51 +00:00
Alasdair Kergon
d5250f4901 Fix some &->&& vgreduce cmdline validation. [Andre Noll] 2007-01-31 16:26:23 +00:00
Alasdair Kergon
25f29f4712 post-release 2007-01-30 21:37:18 +00:00
Alasdair Kergon
382af5563d pre-release 2007-01-30 18:08:17 +00:00
Alasdair Kergon
8cf3d165d3 Add warning to lvm2_monitoring_init_rhel4 if attempting to stop monitoring. 2007-01-30 18:02:15 +00:00
Alasdair Kergon
0fd6ce546f Fix vgsplit to handle mirrors.
Reorder fields in reporting field definitions.
2007-01-29 23:01:18 +00:00
Alasdair Kergon
b881c372bc post-release 2007-01-29 20:25:19 +00:00
Alasdair Kergon
94c5e7deb0 pre-release 2007-01-29 19:57:24 +00:00
Alasdair Kergon
c344766f3c Add recent reporting options to dmsetup man page.
Revise some report fields names.
2007-01-29 19:35:24 +00:00
Alasdair Kergon
67895de0bc help on help 2007-01-29 18:45:08 +00:00
Alasdair Kergon
ff00cb6990 help unused attr 2007-01-29 18:43:27 +00:00
Alasdair Kergon
2cc75c11ed add help -c for field list 2007-01-29 18:37:57 +00:00
Alasdair Kergon
cd79e58eda Add dmsetup 'help' command and update usage text. 2007-01-29 18:18:41 +00:00
Alasdair Kergon
6fa801f3d8 reorder report field definitions 2007-01-29 17:45:32 +00:00
Alasdair Kergon
684eecba1d Use fixed-size fields in report interface. 2007-01-29 17:23:54 +00:00
Alasdair Kergon
da9cf7e5de fix pvsegs report too 2007-01-27 02:32:31 +00:00
Alasdair Kergon
f57e7445fd Fix vgs to treat args as VGs even when PV fields are displayed. 2007-01-27 02:09:06 +00:00
Alasdair Kergon
fba1388719 Fix md signature check to handle both endiannesses. 2007-01-26 17:15:16 +00:00
Alasdair Kergon
80ed029c17 post-release 2007-01-25 23:40:33 +00:00
22 changed files with 444 additions and 110 deletions

View File

@@ -1 +1 @@
2.02.20-cvs (2007-01-25)
2.02.22-cvs (2007-02-13)

View File

@@ -1,3 +1,20 @@
Version 2.02.22 - 13th February 2007
====================================
Correct -b and -P on a couple of man pages.
Add global/units to example.conf.
Fix loading of segment_libraries.
If a PV reappears after it was removed from its VG, make it an orphan.
Don't update metadata automatically if VGIDs don't match.
Fix some vgreduce --removemissing command line validation.
Version 2.02.21 - 30th January 2007
===================================
Add warning to lvm2_monitoring_init_rhel4 if attempting to stop monitoring.
Fix vgsplit to handle mirrors.
Reorder fields in reporting field definitions.
Fix vgs to treat args as VGs even when PV fields are displayed.
Fix md signature check to handle both endiannesses.
Version 2.02.20 - 25th January 2007
===================================
dmeventd mirror sets ignore_suspended_devices and avoids scanning mirrors.

View File

@@ -1,3 +1,14 @@
Version 1.02.18 - 13th February 2007
====================================
Improve dmeventd messaging protocol: drain pipe and tag messages.
Version 1.02.17 - 29th January 2007
===================================
Add recent reporting options to dmsetup man page.
Revise some report fields names.
Add dmsetup 'help' command and update usage text.
Use fixed-size fields in report interface and reorder.
Version 1.02.16 - 25th January 2007
===================================
Add some missing close() and fclose() return value checks.

View File

@@ -146,6 +146,7 @@ static LIST_INIT(_dso_registry);
/* Structure to keep parsed register variables from client message. */
struct message_data {
char *id;
char *dso_name; /* Name of DSO. */
char *device_uuid; /* Mapped device path. */
union {
@@ -320,6 +321,8 @@ static int _fetch_string(char **ptr, char **src, const int delimiter)
/* Free message memory. */
static void _free_message(struct message_data *message_data)
{
if (message_data->id)
dm_free(message_data->id);
if (message_data->dso_name)
dm_free(message_data->dso_name);
@@ -342,7 +345,8 @@ static int _parse_message(struct message_data *message_data)
* Retrieve application identifier, mapped device
* path and events # string from message.
*/
if (_fetch_string(&message_data->dso_name, &p, ' ') &&
if (_fetch_string(&message_data->id, &p, ' ') &&
_fetch_string(&message_data->dso_name, &p, ' ') &&
_fetch_string(&message_data->device_uuid, &p, ' ') &&
_fetch_string(&message_data->events.str, &p, ' ') &&
_fetch_string(&message_data->timeout.str, &p, ' ')) {
@@ -875,8 +879,8 @@ static struct dso_data *_load_dso(struct message_data *data)
syslog(LOG_ERR, "dmeventd %s dlopen failed: %s", data->dso_name,
dlerr);
data->msg->size =
dm_asprintf(&(data->msg->data), "%s dlopen failed: %s",
data->dso_name, dlerr);
dm_asprintf(&(data->msg->data), "%s %s dlopen failed: %s",
data->id, data->dso_name, dlerr);
return NULL;
}
@@ -1056,7 +1060,8 @@ static int _registered_device(struct message_data *message_data,
{
struct dm_event_daemon_message *msg = message_data->msg;
const char *fmt = "%s %s %u";
const char *fmt = "%s %s %s %u";
const char *id = message_data->id;
const char *dso = thread->dso_data->dso_name;
const char *dev = thread->device.uuid;
unsigned events = ((thread->status == DM_THREAD_RUNNING)
@@ -1066,7 +1071,7 @@ static int _registered_device(struct message_data *message_data,
if (msg->data)
dm_free(msg->data);
msg->size = dm_asprintf(&(msg->data), fmt, dso, dev, events);
msg->size = dm_asprintf(&(msg->data), fmt, id, dso, dev, events);
_unlock_mutex();
@@ -1180,7 +1185,8 @@ static int _get_timeout(struct message_data *message_data)
_lock_mutex();
if ((thread = _lookup_thread_status(message_data))) {
msg->size =
dm_asprintf(&(msg->data), "%" PRIu32, thread->timeout);
dm_asprintf(&(msg->data), "%s %" PRIu32, message_data->id,
thread->timeout);
} else {
msg->data = NULL;
msg->size = 0;
@@ -1375,17 +1381,32 @@ static int _handle_request(struct dm_event_daemon_message *msg,
static int _do_process_request(struct dm_event_daemon_message *msg)
{
int ret;
char *answer;
static struct message_data message_data;
/* Parse the message. */
memset(&message_data, 0, sizeof(message_data));
message_data.msg = msg;
if (msg->cmd != DM_EVENT_CMD_ACTIVE && !_parse_message(&message_data)) {
if (msg->cmd == DM_EVENT_CMD_HELLO) {
ret = 0;
answer = dm_strdup(msg->data);
if (answer) {
msg->size = dm_asprintf(&(msg->data), "%s HELLO", answer);
dm_free(answer);
} else {
msg->size = 0;
msg->data = NULL;
}
} else if (msg->cmd != DM_EVENT_CMD_ACTIVE && !_parse_message(&message_data)) {
stack;
ret = -EINVAL;
} else
ret = _handle_request(msg, &message_data);
msg->cmd = ret;
if (!msg->data)
msg->size = dm_asprintf(&(msg->data), "%s %s", message_data.id, strerror(-ret));
_free_message(&message_data);
return ret;
@@ -1405,16 +1426,9 @@ static void _process_request(struct dm_event_fifos *fifos)
if (!_client_read(fifos, &msg))
return;
msg.cmd = _do_process_request(&msg);
if (!msg.data) {
msg.data = dm_strdup(strerror(-msg.cmd));
if (msg.data)
msg.size = strlen(msg.data) + 1;
else {
msg.size = 0;
stack;
}
}
/* _do_process_request fills in msg (if memory allows for
data, otherwise just cmd and size = 0) */
_do_process_request(&msg);
if (!_client_write(fifos, &msg))
stack;

View File

@@ -20,6 +20,7 @@ enum dm_event_command {
DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE,
DM_EVENT_CMD_SET_TIMEOUT,
DM_EVENT_CMD_GET_TIMEOUT,
DM_EVENT_CMD_HELLO,
};
/* Message passed between client and daemon. */

View File

@@ -30,6 +30,8 @@
#include <sys/wait.h>
#include <arpa/inet.h> /* for htonl, ntohl */
static int _sequence_nr = 0;
struct dm_event_handler {
char *dso;
@@ -182,6 +184,21 @@ enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler
return dmevh->mask;
}
static int _check_message_id(struct dm_event_daemon_message *msg)
{
int pid, seq_nr;
if ((sscanf(msg->data, "%d:%d", &pid, &seq_nr) != 2) ||
(pid != getpid()) || (seq_nr != _sequence_nr)) {
log_error("Ignoring out-of-sequence reply from dmeventd. "
"Expected %d:%d but received %s", getpid(),
_sequence_nr, msg->data);
return 0;
}
return 1;
}
/*
* daemon_read
* @fifos
@@ -260,11 +277,28 @@ static int _daemon_write(struct dm_event_fifos *fifos,
size_t size = 2 * sizeof(uint32_t) + msg->size;
char *buf = alloca(size);
char drainbuf[128];
struct timeval tval = { 0, 0 };
*((uint32_t *)buf) = htonl(msg->cmd);
*((uint32_t *)buf + 1) = htonl(msg->size);
memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);
/* drain the answer fifo */
while (1) {
FD_ZERO(&fds);
FD_SET(fifos->server, &fds);
tval.tv_usec = 100;
ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
if ((ret < 0) && (errno != EINTR)) {
log_error("Unable to talk to event daemon");
return 0;
}
if (ret == 0)
break;
read(fifos->server, drainbuf, 127);
}
while (bytes < size) {
do {
/* Watch daemon write FIFO to be ready for output. */
@@ -301,7 +335,7 @@ static int _daemon_talk(struct dm_event_fifos *fifos,
{
const char *dso = dso_name ? dso_name : "";
const char *dev = dev_name ? dev_name : "";
const char *fmt = "%s %s %u %" PRIu32;
const char *fmt = "%d:%d %s %s %u %" PRIu32;
int msg_size;
memset(msg, 0, sizeof(*msg));
@@ -310,8 +344,10 @@ static int _daemon_talk(struct dm_event_fifos *fifos,
* into ASCII message string.
*/
msg->cmd = cmd;
if ((msg_size = dm_asprintf(&(msg->data), fmt, dso, dev, evmask,
timeout)) < 0) {
if (cmd == DM_EVENT_CMD_HELLO)
fmt = "%d:%d HELLO";
if ((msg_size = dm_asprintf(&(msg->data), fmt, getpid(), _sequence_nr,
dso, dev, evmask, timeout)) < 0) {
log_error("_daemon_talk: message allocation failed");
return -ENOMEM;
}
@@ -326,10 +362,14 @@ static int _daemon_talk(struct dm_event_fifos *fifos,
return -EIO;
}
if (!_daemon_read(fifos, msg)) {
stack;
return -EIO;
}
do {
if (!_daemon_read(fifos, msg)) {
stack;
return -EIO;
}
} while (!_check_message_id(msg));
_sequence_nr++;
return (int32_t) msg->cmd;
}
@@ -507,7 +547,9 @@ static int _do_event(int cmd, struct dm_event_daemon_message *msg,
return -ESRCH;
}
ret = _daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
ret = _daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, 0, 0, 0, 0);
if (!ret)
ret = _daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
/* what is the opposite of init? */
_dtr_client(&fifos);
@@ -521,7 +563,7 @@ int dm_event_register_handler(const struct dm_event_handler *dmevh)
int ret = 1, err;
const char *uuid;
struct dm_task *dmt;
struct dm_event_daemon_message msg;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!(dmt = _get_device_info(dmevh))) {
stack;
@@ -551,7 +593,7 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
int ret = 1, err;
const char *uuid;
struct dm_task *dmt;
struct dm_event_daemon_message msg;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!(dmt = _get_device_info(dmevh))) {
stack;
@@ -598,15 +640,20 @@ static char *_fetch_string(char **src, const int delimiter)
static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
char **uuid, enum dm_event_mask *evmask)
{
char *id = NULL;
char *p = msg->data;
if ((*dso_name = _fetch_string(&p, ' ')) &&
if ((id = _fetch_string(&p, ' ')) &&
(*dso_name = _fetch_string(&p, ' ')) &&
(*uuid = _fetch_string(&p, ' '))) {
*evmask = atoi(p);
dm_free(id);
return 0;
}
if (id)
dm_free(id);
return -ENOMEM;
}
@@ -621,12 +668,12 @@ static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
*/
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
{
int ret;
int ret = 0;
const char *uuid = NULL;
char *reply_dso = NULL, *reply_uuid = NULL;
enum dm_event_mask reply_mask;
struct dm_task *dmt;
struct dm_event_daemon_message msg;
enum dm_event_mask reply_mask = 0;
struct dm_task *dmt = NULL;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!(dmt = _get_device_info(dmevh))) {
stack;
@@ -696,9 +743,17 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
#if 0 /* left out for now */
static char *_skip_string(char *src, const int delimiter)
{
src = srtchr(src, delimiter);
if (src && *(src + 1))
return src + 1;
return NULL;
}
int dm_event_set_timeout(const char *device_path, uint32_t timeout)
{
struct dm_event_daemon_message msg;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!device_exists(device_path))
return -ENODEV;
@@ -710,13 +765,20 @@ int dm_event_set_timeout(const char *device_path, uint32_t timeout)
int dm_event_get_timeout(const char *device_path, uint32_t *timeout)
{
int ret;
struct dm_event_daemon_message msg;
struct dm_event_daemon_message msg = { 0, 0, NULL };
if (!device_exists(device_path))
return -ENODEV;
if (!(ret = _do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path,
0, 0)))
*timeout = atoi(msg.data);
0, 0))) {
char *p = _skip_string(msg.data, ' ');
if (!p) {
log_error("malformed reply from dmeventd '%s'\n",
msg.data);
return -EIO;
}
*timeout = atoi(p);
}
if (msg.data)
dm_free(msg.data);
return ret;

View File

@@ -188,6 +188,9 @@ global {
# command. Defaults to off.
test = 0
# Default value for --units argument
units = "h"
# Whether or not to communicate with the kernel device-mapper.
# Set to 0 if you want to use the tools to manipulate LVM metadata
# without activating any logical volumes.

View File

@@ -754,7 +754,6 @@ static int _init_segtypes(struct cmd_context *cmd)
struct config_value *cv;
struct segment_type *(*init_segtype_fn) (struct cmd_context *);
void *lib;
struct list *sgtl, *tmp;
struct segment_type *segtype2;
for (cv = cn->v; cv; cv = cv->next) {
@@ -781,18 +780,16 @@ static int _init_segtypes(struct cmd_context *cmd)
segtype->library = lib;
list_add(&cmd->segtypes, &segtype->list);
list_iterate_safe(sgtl, tmp, &cmd->segtypes) {
segtype2 = list_item(sgtl, struct segment_type);
if (!strcmp(segtype2->name, segtype->name)) {
log_error("Duplicate segment type %s: "
"unloading shared library %s",
segtype->name, cv->v.str);
list_del(&segtype->list);
segtype->ops->destroy(segtype);
dlclose(lib);
break;
}
list_iterate_items(segtype2, &cmd->segtypes) {
if ((segtype == segtype2) ||
strcmp(segtype2->name, segtype->name))
continue;
log_error("Duplicate segment type %s: "
"unloading shared library %s",
segtype->name, cv->v.str);
list_del(&segtype->list);
segtype->ops->destroy(segtype);
dlclose(lib);
}
}
}

View File

@@ -53,8 +53,10 @@ int dev_is_md(struct device *dev, uint64_t *sb)
sb_offset = MD_NEW_SIZE_SECTORS(size) << SECTOR_SHIFT;
/* Check if it is an md component device. */
/* Version 1 is little endian; version 0.90.0 is machine endian */
if (dev_read(dev, sb_offset, sizeof(uint32_t), &md_magic) &&
(md_magic == xlate32(MD_SB_MAGIC))) {
((md_magic == xlate32(MD_SB_MAGIC)) ||
(md_magic == MD_SB_MAGIC))) {
if (sb)
*sb = sb_offset;
ret = 1;

View File

@@ -963,6 +963,30 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd)
return vg;
}
static int _update_pv_list(struct list *all_pvs, struct volume_group *vg)
{
struct pv_list *pvl, *pvl2;
list_iterate_items(pvl, &vg->pvs) {
list_iterate_items(pvl2, all_pvs) {
if (pvl->pv->dev == pvl2->pv->dev)
goto next_pv;
}
/* PV is not on list so add it. Note that we don't copy it. */
if (!(pvl2 = dm_pool_zalloc(vg->cmd->mem, sizeof(*pvl2)))) {
log_error("pv_list allocation for '%s' failed",
dev_name(pvl->pv->dev));
return 0;
}
pvl2->pv = pvl->pv;
list_add(all_pvs, &pvl2->list);
next_pv:
;
}
return 1;
}
/* Caller sets consistent to 1 if it's safe for vg_read to correct
* inconsistent metadata on disk (i.e. the VG write lock is held).
* This guarantees only consistent metadata is returned unless PARTIAL_VG.
@@ -982,9 +1006,12 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
struct volume_group *vg, *correct_vg = NULL;
struct metadata_area *mda;
int inconsistent = 0;
int inconsistent_vgid = 0;
int use_precommitted = precommitted;
struct list *pvids;
struct pv_list *pvl;
struct pv_list *pvl, *pvl2;
struct list all_pvs;
char uuid[64] __attribute((aligned(8)));
if (!*vgname) {
if (use_precommitted) {
@@ -1069,6 +1096,8 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
}
}
list_init(&all_pvs);
/* Failed to find VG where we expected it - full scan and retry */
if (!correct_vg) {
inconsistent = 0;
@@ -1104,13 +1133,25 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
}
if (!correct_vg) {
correct_vg = vg;
if (!_update_pv_list(&all_pvs, correct_vg))
return_NULL;
continue;
}
if (strncmp((char *)vg->id.uuid,
(char *)correct_vg->id.uuid, ID_LEN)) {
inconsistent = 1;
inconsistent_vgid = 1;
}
/* FIXME Also ensure contents same - checksums same? */
if (correct_vg->seqno != vg->seqno) {
inconsistent = 1;
if (vg->seqno > correct_vg->seqno)
if (vg->seqno > correct_vg->seqno) {
if (!_update_pv_list(&all_pvs, vg))
return_NULL;
correct_vg = vg;
}
}
}
@@ -1143,17 +1184,42 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
return correct_vg;
}
log_print("Inconsistent metadata copies found - updating "
"to use version %u", correct_vg->seqno);
/* Don't touch if vgids didn't match */
if (inconsistent_vgid) {
log_error("Inconsistent metadata UUIDs found for "
"volume group %s", vgname);
*consistent = 0;
return correct_vg;
}
log_print("Inconsistent metadata found for VG %s - updating "
"to use version %u", vgname, correct_vg->seqno);
if (!vg_write(correct_vg)) {
log_error("Automatic metadata correction failed");
return NULL;
}
if (!vg_commit(correct_vg)) {
log_error("Automatic metadata correction commit "
"failed");
return NULL;
}
list_iterate_items(pvl, &all_pvs) {
list_iterate_items(pvl2, &correct_vg->pvs) {
if (pvl->pv->dev == pvl2->pv->dev)
goto next_pv;
}
if (!id_write_format(&pvl->pv->id, uuid, sizeof(uuid)))
return_NULL;
log_error("Removing PV %s (%s) that no longer belongs to VG %s",
dev_name(pvl->pv->dev), uuid, correct_vg->name);
if (!pv_write_orphan(cmd, pvl->pv))
return_NULL;
next_pv:
;
}
}
if ((correct_vg->status & PVMOVE) && !pvmove_mode()) {
@@ -1433,3 +1499,25 @@ int pv_write(struct cmd_context *cmd __attribute((unused)), struct physical_volu
return 1;
}
int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv)
{
const char *old_vg_name = pv->vg_name;
pv->vg_name = ORPHAN;
pv->status = ALLOCATABLE_PV;
if (!dev_get_size(pv->dev, &pv->size)) {
log_error("%s: Couldn't get size.", dev_name(pv->dev));
return 0;
}
if (!pv_write(cmd, pv, NULL, INT64_C(-1))) {
log_error("Failed to clear metadata from physical "
"volume \"%s\" after removal from \"%s\"",
dev_name(pv->dev), old_vg_name);
return 0;
}
return 1;
}

View File

@@ -423,6 +423,7 @@ struct list *get_vgids(struct cmd_context *cmd, int full_scan);
int pv_write(struct cmd_context *cmd, struct physical_volume *pv,
struct list *mdas, int64_t label_sector);
int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv);
/* pe_start and pe_end relate to any existing data so that new metadata
* areas can avoid overlap */

View File

@@ -868,11 +868,11 @@ static const struct dm_report_object_type _report_types[] = {
#define STR DM_REPORT_FIELD_TYPE_STRING
#define NUM DM_REPORT_FIELD_TYPE_NUMBER
#define FIELD(type, strct, sorttype, head, field, width, func, id, desc) {type, id, (off_t)((void *)&_dummy._ ## strct.field - (void *)&_dummy._ ## strct), head, width, sorttype, &_ ## func ## _disp, desc},
#define FIELD(type, strct, sorttype, head, field, width, func, id, desc) {type, sorttype, (off_t)((void *)&_dummy._ ## strct.field - (void *)&_dummy._ ## strct), width, id, head, &_ ## func ## _disp, desc},
static struct dm_report_field_type _fields[] = {
#include "columns.h"
{0, "", 0, "", 0, 0, NULL, NULL},
{0, 0, 0, 0, "", "", NULL, NULL},
};
#undef STR

View File

@@ -657,11 +657,11 @@ struct dm_report_field;
struct dm_report;
struct dm_report_field_type {
uint32_t type; /* object type id */
const char id[32]; /* string used to specify the field */
unsigned int offset; /* byte offset in the object */
const char heading[32]; /* string printed in header */
int width; /* default width */
uint32_t flags; /* DM_REPORT_FIELD_* */
uint32_t offset; /* byte offset in the object */
int32_t width; /* default width */
const char id[32]; /* string used to specify the field */
const char heading[32]; /* string printed in header */
int (*report_fn)(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data,
void *private);

View File

@@ -60,7 +60,7 @@ struct field_properties {
struct list list;
uint32_t field_num;
uint32_t sort_posn;
unsigned width;
int32_t width;
const struct dm_report_object_type *type;
uint32_t flags;
};
@@ -750,7 +750,7 @@ int dm_report_output(struct dm_report *rh)
struct dm_report_field *field;
const char *repstr;
char buf[4096];
unsigned width;
int32_t width;
uint32_t align;
if (list_empty(&rh->rows))

View File

@@ -3,6 +3,9 @@
dmsetup \- low level logical volume management
.SH SYNOPSIS
.ad l
.B dmsetup help
.I [-c|-C|--columns]
.br
.B dmsetup create
.I device_name [-u uuid] [--notable | --table <table> | table_file]
.br
@@ -33,21 +36,25 @@ dmsetup \- low level logical volume management
.B dmsetup message
.I device_name sector message
.br
.B dmsetup ls [--target target_type] [--exec command] [--tree [-o options]]
.B dmsetup ls
.I [--target target_type] [--exec command] [--tree [-o options]]
.br
.B dmsetup info
.I [device_name]
.br
.B dmsetup info -c|-C|--columns [--noheadings] [-o name]
.B dmsetup info -c|-C|--columns
.I [--noheadings] [--separator separator] [-o fields] [-O|--sort sort_fields]
.I [device_name]
.br
.B dmsetup deps
.I [device_name]
.br
.B dmsetup status [--target target_type]
.B dmsetup status
.I [--target target_type]
.I [device_name]
.br
.B dmsetup table [--target target_type]
.B dmsetup table
.I [--target target_type]
.I [device_name]
.br
.B dmsetup wait
@@ -103,7 +110,7 @@ Tell the kernel not to supply the open reference count for the device.
When creating a device, don't load any table.
.IP \fB-o|--options
.br
Specify which fields to display. Only \fB-o\ name\fP is supported.
Specify which fields to display.
.IP \fB-r|--readonly
.br
Set the table being loaded read-only.
@@ -136,6 +143,11 @@ See below for information on the table format.
.br
Outputs a list of (major, minor) pairs for devices referenced by the
live table for the specified device.
.IP \fBhelp
.I [-c|-C|--columns]
.br
Outputs a summary of the commands available, optionally including
the list of report fields.
.IP \fBinfo
.I [device_name]
.br
@@ -154,6 +166,17 @@ Outputs some brief information about the device in the form:
Number of targets in the live table
.br
UUID
.IP \fBinfo -c|-C|--columns
.I [--noheadings] [--separator separator] [-o fields] [-O|--sort sort_fields]
.I [device_name]
.br
Output you can customise.
Fields are comma-separated and chosen from the following list:
name, major, minor, attr, open, segments, events, uuid.
Attributes are: (L)ive, (I)nactive, (s)uspended, (r)ead-only, read-(w)rite.
Precede the list with '+' to append
to the default selection of columns instead of replacing it.
Precede any sort_field with - for a reverse sort on that column.
.IP \fBls
.I [--target target_type]
.I [--exec command]

View File

@@ -12,7 +12,7 @@ lvchange \- change attributes of a logical volume
[\-\-ignorelockingfailure]
[\-\-monitor {y|n}]
[\-M/\-\-persistent y/n] [\-\-minor minor]
[\-P/\-\-partial y/n]
[\-P/\-\-partial]
[\-p/\-\-permission r/w] [\-r/\-\-readahead ReadAheadSectors]
[\-\-refresh]
[\-t/\-\-test]

View File

@@ -5,7 +5,7 @@ pvmove \- move physical extents
.B pvmove
[\-\-abort]
[\-\-alloc AllocationPolicy]
[\-\-background]
[\-b/\-\-background]
[\-d/\-\-debug] [\-h/\-\-help] [\-i/\-\-interval Seconds] [\-v/\-\-verbose]
[\-n/\-\-name LogicalVolume]
[SourcePhysicalVolume[:PE[-PE]...] [DestinationPhysicalVolume[:PE[-PE]...]...]]
@@ -73,7 +73,7 @@ type of on-disk metadata. Metadata can be converted using \fBvgconvert\fP(8).
.I \-\-abort
Abort any moves in progress.
.TP
.I \-\-background
.I \-b, \-\-background
Run the daemon in the background.
.TP
.I \-i, \-\-interval Seconds

View File

@@ -25,11 +25,11 @@
. /etc/init.d/functions
VGCHANGE="/usr/sbin/vgchange"
WARN=1
start()
{
for ret in 0
do
ret=0
# TODO do we want to separate out already active groups only?
VGS=`vgs --noheadings -o name`
for vg in $VGS
@@ -40,50 +40,58 @@ start()
fi
done
done
return $ret
return $ret
}
stop()
{
for ret in 0
do
ret=0
# TODO do we want to separate out already active groups only?
if test "$WARN" = "1"; then
echo "Not stopping monitoring, this is a dangerous operation. Please use force-stop to override."
return 1
fi
VGS=`vgs --noheadings -o name`
for vg in $VGS
do
if ! action "Starting monitoring for VG $vg:" $VGCHANGE --monitor n $vg
if ! action "Stopping monitoring for VG $vg:" $VGCHANGE --monitor n $vg
then
ret=$?
fi
done
done
return $ret
}
ret=1
result=1
# See how we were called.
case "$1" in
start)
start
ret=$?
result=$?
;;
force-stop)
WARN=0
stop
result=$?
;;
stop)
test "$runlevel" = "0" && WARN=0
test "$runlevel" = "6" && WARN=0
stop
ret=$?
result=$?
;;
restart)
WARN=0
if stop
then
start
fi
ret=$?
result=$?
;;
status)
@@ -91,8 +99,8 @@ case "$1" in
;;
*)
echo $"Usage: $0 {start|stop|restart|status}"
echo $"Usage: $0 {start|stop|restart|status|force-stop}"
;;
esac
exit $ret
exit $result

View File

@@ -1561,20 +1561,20 @@ static const struct dm_report_object_type _report_types[] = {
#define OFFSET_OF(strct, field) ((unsigned int) &((struct strct *)NULL)->field)
#define STR (DM_REPORT_FIELD_TYPE_STRING)
#define NUM (DM_REPORT_FIELD_TYPE_NUMBER)
#define FIELD_O(type, strct, sorttype, head, field, width, func, id, desc) {DR_ ## type, id, OFFSET_OF(strct, field), head, width, sorttype, &_ ## func ## _disp, desc},
#define FIELD_F(type, sorttype, head, width, func, id, desc) {DR_ ## type, id, 0, head, width, sorttype, &_ ## func ## _disp, desc},
#define FIELD_O(type, strct, sorttype, head, field, width, func, id, desc) {DR_ ## type, sorttype, OFFSET_OF(strct, field), width, id, head, &_ ## func ## _disp, desc},
#define FIELD_F(type, sorttype, head, width, func, id, desc) {DR_ ## type, sorttype, 0, width, id, head, &_ ## func ## _disp, desc},
static const struct dm_report_field_type _report_fields[] = {
/* *INDENT-OFF* */
FIELD_F(TASK, STR, "Name", 16, dm_name, "name", "Name of mapped device.")
FIELD_F(TASK, STR, "UUID", 32, dm_uuid, "uuid", "Unique identifier for mapped device (optional).")
FIELD_F(INFO, STR, "Stat", 4, dm_info_status, "status", "Attributes.")
FIELD_O(INFO, dm_info, NUM, "Maj", major, 3, int32, "major", "Major number.")
FIELD_O(INFO, dm_info, NUM, "Min", minor, 3, int32, "minor", "Minor number.")
FIELD_O(INFO, dm_info, NUM, "Open", open_count, 4, int32, "open_count", "Number of references to open device, if requested.")
FIELD_O(INFO, dm_info, NUM, "Targ", target_count, 4, int32, "target_count", "Number of segments in live table, if present.")
FIELD_O(INFO, dm_info, NUM, "Event", event_nr, 6, uint32, "event_nr", "Current event number.")
{0, "", 0, "", 0, 0, NULL, NULL},
FIELD_F(TASK, STR, "UUID", 32, dm_uuid, "uuid", "Unique (optional) identifier for mapped device.")
FIELD_F(INFO, STR, "Stat", 4, dm_info_status, "attr", "(L)ive, (I)nactive, (s)uspended, (r)ead-only, read-(w)rite.")
FIELD_O(INFO, dm_info, NUM, "Maj", major, 3, int32, "major", "Block device major number.")
FIELD_O(INFO, dm_info, NUM, "Min", minor, 3, int32, "minor", "Block device minor number.")
FIELD_O(INFO, dm_info, NUM, "Open", open_count, 4, int32, "open", "Number of references to open device, if requested.")
FIELD_O(INFO, dm_info, NUM, "Targ", target_count, 4, int32, "segments", "Number of segments in live table, if present.")
FIELD_O(INFO, dm_info, NUM, "Event", event_nr, 6, uint32, "events", "Number of most recent event.")
{0, 0, 0, 0, "", "", NULL, NULL},
/* *INDENT-ON* */
};
@@ -1583,7 +1583,7 @@ FIELD_O(INFO, dm_info, NUM, "Event", event_nr, 6, uint32, "event_nr", "Current e
#undef FIELD_O
#undef FIELD_F
static const char *default_report_options = "name,major,minor,status,open_count,target_count,event_nr,uuid";
static const char *default_report_options = "name,major,minor,attr,open,segments,events,uuid";
static int _report_init(struct command *c)
{
@@ -1625,7 +1625,7 @@ static int _report_init(struct command *c)
if (_switches[SORT_ARG] && _string_args[SORT_ARG]) {
keys = _string_args[SORT_ARG];
buffered = 1;
if (!strcmp(c->name, "status") || !strcmp(c->name, "table")) {
if (c && (!strcmp(c->name, "status") || !strcmp(c->name, "table"))) {
err("--sort is not yet supported with status and table");
goto out;
}
@@ -1673,10 +1673,13 @@ static int _ls(int argc, char **argv, void *data)
return _process_all(argc, argv, 0, _display_name);
}
static int _help(int argc, char **argv, void *data);
/*
* Dispatch table
*/
static struct command _commands[] = {
{"help", "[-c|-C|--columns]", 0, 0, _help},
{"create", "<dev_name> [-j|--major <major> -m|--minor <minor>]\n"
"\t [-U|--uid <uid>] [-G|--gid <gid>] [-M|--mode <octal_mode>]\n"
"\t [-u|uuid <uuid>]\n"
@@ -1710,14 +1713,18 @@ static void _usage(FILE *out)
fprintf(out, "Usage:\n\n");
fprintf(out, "dmsetup [--version] [-v|--verbose [-v|--verbose ...]]\n"
" [-r|--readonly] [--noopencount] [--nolockfs]\n\n");
" [-r|--readonly] [--noopencount] [--nolockfs]\n"
" [-c|-C|--columns] [-o <fields>] [-O|--sort <sort_fields>]\n"
" [--noheadings] [--separator <separator>]\n\n");
for (i = 0; _commands[i].name; i++)
fprintf(out, "\t%s %s\n", _commands[i].name, _commands[i].help);
fprintf(out, "\n<device> may be device name or -u <uuid> or "
"-j <major> -m <minor>\n");
fprintf(out, "<fields> are comma-separated. Use 'help -c' for list.\n");
fprintf(out, "Table_file contents may be supplied on stdin.\n");
fprintf(out, "Tree options are: ascii, utf, vt100; compact, inverted, notrunc;\n"
" [no]device, active, open, rw and uuid.\n\n");
" [no]device, active, open, rw and uuid.\n");
fprintf(out, "\n");
return;
}
@@ -1728,6 +1735,23 @@ static void _losetup_usage(FILE *out)
"[-o offset] [-f|loop_device] [file]\n\n");
}
static int _help(int argc __attribute((unused)),
char **argv __attribute((unused)),
void *data __attribute((unused)))
{
_usage(stderr);
if (_switches[COLS_ARG]) {
_switches[OPTIONS_ARG] = 1;
_string_args[OPTIONS_ARG] = (char *) "help";
_switches[SORT_ARG] = 0;
(void) _report_init(NULL);
}
return 1;
}
static struct command *_find_command(const char *name)
{
int i;
@@ -2096,7 +2120,7 @@ static int _process_switches(int *argc, char ***argv)
return 1;
}
if(!strcmp(base, "losetup") || !strcmp(base, "dmlosetup")){
if (!strcmp(base, "losetup") || !strcmp(base, "dmlosetup")){
r = _process_losetup_switches(base, argc, argv);
free(namebase);
return r;

View File

@@ -138,6 +138,30 @@ out:
return ret;
}
static int _pvs_in_vg(struct cmd_context *cmd, const char *vg_name,
struct volume_group *vg, int consistent,
void *handle)
{
if (!vg) {
log_error("Volume group %s not found", vg_name);
return ECMD_FAILED;
}
return process_each_pv_in_vg(cmd, vg, NULL, handle, &_pvs_single);
}
static int _pvsegs_in_vg(struct cmd_context *cmd, const char *vg_name,
struct volume_group *vg, int consistent,
void *handle)
{
if (!vg) {
log_error("Volume group %s not found", vg_name);
return ECMD_FAILED;
}
return process_each_pv_in_vg(cmd, vg, NULL, handle, &_pvsegs_single);
}
static int _report(struct cmd_context *cmd, int argc, char **argv,
report_type_t report_type)
{
@@ -146,8 +170,8 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
char *str;
const char *keys = NULL, *options = NULL, *separator;
int r = ECMD_PROCESSED;
int aligned, buffered, headings;
unsigned args_are_pvs;
aligned = find_config_tree_int(cmd, "report/aligned",
DEFAULT_REP_ALIGNED);
@@ -158,6 +182,8 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
separator = find_config_tree_str(cmd, "report/separator",
DEFAULT_REP_SEPARATOR);
args_are_pvs = (report_type == PVS || report_type == PVSEGS) ? 1 : 0;
switch (report_type) {
case LVS:
keys = find_config_tree_str(cmd, "report/lvs_sort",
@@ -292,16 +318,24 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
report_handle, &_vgs_single);
break;
case PVS:
r = process_each_pv(cmd, argc, argv, NULL, report_handle,
&_pvs_single);
if (args_are_pvs)
r = process_each_pv(cmd, argc, argv, NULL,
report_handle, &_pvs_single);
else
r = process_each_vg(cmd, argc, argv, LCK_VG_READ, 0,
report_handle, &_pvs_in_vg);
break;
case SEGS:
r = process_each_lv(cmd, argc, argv, LCK_VG_READ, report_handle,
&_lvsegs_single);
break;
case PVSEGS:
r = process_each_pv(cmd, argc, argv, NULL, report_handle,
&_pvsegs_single);
if (args_are_pvs)
r = process_each_pv(cmd, argc, argv, NULL,
report_handle, &_pvsegs_single);
else
r = process_each_vg(cmd, argc, argv, LCK_VG_READ, 0,
report_handle, &_pvsegs_in_vg);
break;
}

View File

@@ -427,13 +427,13 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv)
int ret = 1;
int consistent = 1;
if (!argc & !arg_count(cmd, removemissing_ARG)) {
if (!argc && !arg_count(cmd, removemissing_ARG)) {
log_error("Please give volume group name and "
"physical volume paths");
return EINVALID_CMD_LINE;
}
if (!argc & arg_count(cmd, removemissing_ARG)) {
if (!argc && arg_count(cmd, removemissing_ARG)) {
log_error("Please give volume group name");
return EINVALID_CMD_LINE;
}

View File

@@ -72,6 +72,9 @@ static int _move_lvs(struct volume_group *vg_from, struct volume_group *vg_to)
if ((lv->status & SNAPSHOT))
continue;
if ((lv->status & MIRRORED))
continue;
/* Ensure all the PVs used by this LV remain in the same */
/* VG as each other */
vg_with = NULL;
@@ -161,6 +164,48 @@ static int _move_snapshots(struct volume_group *vg_from,
return 1;
}
static int _move_mirrors(struct volume_group *vg_from,
struct volume_group *vg_to)
{
struct list *lvh, *lvht;
struct logical_volume *lv;
struct lv_segment *seg;
int i, seg_in, log_in;
list_iterate_safe(lvh, lvht, &vg_from->lvs) {
lv = list_item(lvh, struct lv_list)->lv;
if (!(lv->status & MIRRORED))
continue;
seg = first_seg(lv);
seg_in = 0;
for (i = 0; i < seg->area_count; i++)
if (_lv_is_in_vg(vg_to, seg_lv(seg, i)))
seg_in++;
log_in = (!seg->log_lv || _lv_is_in_vg(vg_to, seg->log_lv));
if ((seg_in && seg_in < seg->area_count) ||
(seg_in && seg->log_lv && !log_in) ||
(!seg_in && seg->log_lv && log_in)) {
log_error("Mirror %s split", lv->name);
return 0;
}
if (seg_in == seg->area_count && log_in) {
list_del(lvh);
list_add(&vg_to->lvs, lvh);
vg_from->lv_count--;
vg_to->lv_count++;
}
}
return 1;
}
int vgsplit(struct cmd_context *cmd, int argc, char **argv)
{
char *vg_name_from, *vg_name_to;
@@ -275,6 +320,10 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv)
if (!(_move_snapshots(vg_from, vg_to)))
goto error;
/* Move required mirrors across */
if (!(_move_mirrors(vg_from, vg_to)))
goto error;
/* FIXME Split mdas properly somehow too! */
/* Currently we cheat by sharing the format instance and relying on
* vg_write to ignore mdas outside the VG! Done this way, with text