1
0
mirror of git://sourceware.org/git/lvm2.git synced 2026-01-02 20:32:47 +03:00

Compare commits

..

24 Commits

Author SHA1 Message Date
Alasdair Kergon
e5bdb0e0b5 pre-release 2007-01-17 17:51:51 +00:00
Alasdair Kergon
1106b7775a Fix a segfault if an empty config file section encountered. 2007-01-17 16:22:59 +00:00
Alasdair Kergon
ae2852156d merge _target_*register_events
introduce _create_dm_event_handler()
2007-01-17 15:00:57 +00:00
Alasdair Kergon
44c6c36c43 stat oom_adj and stay silent if it doesn't exist
dm_event_handler now keeps private copies of strings
2007-01-17 14:45:10 +00:00
Alasdair Kergon
a81926503d use updated dm_event_get_registered_device interface 2007-01-16 23:05:13 +00:00
Alasdair Kergon
af13ccddda more fixes 2007-01-16 23:03:13 +00:00
Alasdair Kergon
392e1bc2e8 more little fixes 2007-01-16 21:13:07 +00:00
Alasdair Kergon
9268d92c70 clean up global mutex usage and fix a race in thread finalisation code
properly clean up thread status when thread terminates from within
2007-01-16 20:27:07 +00:00
Alasdair Kergon
bb3366c07d dmeventd oom_adj + reduce thread stack size 2007-01-16 20:13:04 +00:00
Alasdair Kergon
d24d563ebc Move basic reporting functions into libdevmapper. 2007-01-16 18:06:12 +00:00
Alasdair Kergon
954bd9257b Add basic reporting functions to libdevmapper. 2007-01-16 18:04:15 +00:00
Alasdair Kergon
5d51a56c02 reduce some if/else complexity 2007-01-15 22:37:40 +00:00
Alasdair Kergon
f48648552e Fix a malloc error path in dmsetup message. 2007-01-15 22:05:50 +00:00
Alasdair Kergon
edb9c3cc9f Fix partition table processing after sparc changes (introduced in 2.02.16).
Fix cmdline PE range processing segfault (introduced in 2.02.13).
2007-01-15 21:55:11 +00:00
Alasdair Kergon
01dc83b936 fix recent checkins 2007-01-15 19:47:49 +00:00
Alasdair Kergon
3a8dff3a62 fail registration if timeout thread cannot be started 2007-01-15 19:19:31 +00:00
Alasdair Kergon
13b234ccba use DMEVENTD_PATH 2007-01-15 19:11:58 +00:00
Alasdair Kergon
e451e93664 static naming 2007-01-15 18:58:40 +00:00
Alasdair Kergon
b4f9531475 Some libdevmapper-event interface changes. 2007-01-15 18:22:02 +00:00
Alasdair Kergon
3184ff75c4 More libdevmapper-event interface changes and fixes.
Rename dm_saprintf() to dm_asprintf().
2007-01-15 18:21:01 +00:00
Alasdair Kergon
43243f4d30 Report error if NULL pointer supplied to dm_strdup_aux(). 2007-01-15 14:39:12 +00:00
Alasdair Kergon
c975a100b1 Report dmeventd mirror monitoring status. 2007-01-12 20:38:30 +00:00
Alasdair Kergon
02bf389425 Reinstate dm_event_get_registered_device 2007-01-12 20:22:11 +00:00
Alasdair Kergon
bcb9a3dd04 post-release 2007-01-11 23:19:08 +00:00
28 changed files with 2039 additions and 1466 deletions

View File

@@ -1 +1 @@
2.02.18-cvs (2007-01-11)
2.02.19-cvs (2007-01-17)

View File

@@ -1,3 +1,13 @@
Version 2.02.19 - 17th January 2007
===================================
Fix a segfault if an empty config file section encountered.
Move basic reporting functions into libdevmapper.
Fix partition table processing after sparc changes (2.02.16).
Fix cmdline PE range processing segfault (2.02.13).
Some libdevmapper-event interface changes.
Report dmeventd mirror monitoring status.
Fix dmeventd mirror status line processing.
Version 2.02.18 - 11th January 2007
===================================
Revised libdevmapper-event interface for dmeventd.

View File

@@ -1,3 +1,12 @@
Version 1.02.15 - 17th January 2007
===================================
Add basic reporting functions to libdevmapper.
Fix a malloc error path in dmsetup message.
More libdevmapper-event interface changes and fixes.
Rename dm_saprintf() to dm_asprintf().
Report error if NULL pointer is supplied to dm_strdup_aux().
Reinstate dm_event_get_registered_device.
Version 1.02.14 - 11th January 2007
===================================
Add dm_saprintf().

View File

@@ -1,16 +1,17 @@
dm_event_handler_create
dm_event_handler_destroy
dm_event_handler_set_dso
dm_event_handler_set_name
dm_event_handler_set_dev_name
dm_event_handler_set_uuid
dm_event_handler_set_major
dm_event_handler_set_minor
dm_event_handler_set_events
dm_event_handler_set_event_mask
dm_event_handler_get_dso
dm_event_handler_get_name
dm_event_handler_get_devname
dm_event_handler_get_uuid
dm_event_handler_get_major
dm_event_handler_get_minor
dm_event_handler_get_events
dm_event_register
dm_event_unregister
dm_event_handler_get_event_mask
dm_event_register_handler
dm_event_unregister_handler
dm_event_get_registered_device

File diff suppressed because it is too large Load Diff

View File

@@ -31,109 +31,143 @@
#include <arpa/inet.h> /* for htonl, ntohl */
struct dm_event_handler {
const char *dso;
const char *device;
const char *uuid;
char *dso;
char *dev_name;
char *uuid;
int major;
int minor;
enum dm_event_type events;
enum dm_event_mask mask;
};
static void dm_event_handler_clear_device(struct dm_event_handler *h)
static void _dm_event_handler_clear_dev_info(struct dm_event_handler *dmevh)
{
h->device = h->uuid = NULL;
h->major = h->minor = 0;
if (dmevh->dev_name)
dm_free(dmevh->dev_name);
if (dmevh->uuid)
dm_free(dmevh->uuid);
dmevh->dev_name = dmevh->uuid = NULL;
dmevh->major = dmevh->minor = 0;
}
struct dm_event_handler *dm_event_handler_create(void)
{
struct dm_event_handler *ret = 0;
struct dm_event_handler *dmevh = NULL;
if (!(ret = dm_malloc(sizeof(*ret))))
if (!(dmevh = dm_malloc(sizeof(*dmevh))))
return NULL;
ret->dso = ret->device = ret->uuid = NULL;
ret->major = ret->minor = 0;
ret->events = 0;
dmevh->dso = dmevh->dev_name = dmevh->uuid = NULL;
dmevh->major = dmevh->minor = 0;
dmevh->mask = 0;
return ret;
return dmevh;
}
void dm_event_handler_destroy(struct dm_event_handler *h)
void dm_event_handler_destroy(struct dm_event_handler *dmevh)
{
dm_free(h);
_dm_event_handler_clear_dev_info(dmevh);
if (dmevh->dso)
dm_free(dmevh->dso);
dm_free(dmevh);
}
void dm_event_handler_set_dso(struct dm_event_handler *h, const char *path)
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path)
{
h->dso = path;
if (!path) /* noop */
return 0;
if (dmevh->dso)
dm_free(dmevh->dso);
dmevh->dso = dm_strdup(path);
if (!dmevh->dso)
return -ENOMEM;
return 0;
}
void dm_event_handler_set_name(struct dm_event_handler *h, const char *name)
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *dev_name)
{
dm_event_handler_clear_device(h);
h->device = name;
if (!dev_name)
return 0;
_dm_event_handler_clear_dev_info(dmevh);
dmevh->dev_name = dm_strdup(dev_name);
if (!dmevh->dev_name)
return -ENOMEM;
return 0;
}
void dm_event_handler_set_uuid(struct dm_event_handler *h, const char *uuid)
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid)
{
dm_event_handler_clear_device(h);
h->uuid = uuid;
if (!uuid)
return 0;
_dm_event_handler_clear_dev_info(dmevh);
dmevh->uuid = dm_strdup(uuid);
if (!dmevh->dev_name)
return -ENOMEM;
return 0;
}
void dm_event_handler_set_major(struct dm_event_handler *h, int major)
void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major)
{
int minor = h->minor;
int minor = dmevh->minor;
dm_event_handler_clear_device(h);
h->major = major;
h->minor = minor;
_dm_event_handler_clear_dev_info(dmevh);
dmevh->major = major;
dmevh->minor = minor;
}
void dm_event_handler_set_minor(struct dm_event_handler *h, int minor)
void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor)
{
int major = h->major;
int major = dmevh->major;
dm_event_handler_clear_device(h);
_dm_event_handler_clear_dev_info(dmevh);
h->major = major;
h->minor = minor;
dmevh->major = major;
dmevh->minor = minor;
}
void dm_event_handler_set_events(struct dm_event_handler *h,
enum dm_event_type event)
void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
enum dm_event_mask evmask)
{
h->events = event;
dmevh->mask = evmask;
}
const char *dm_event_handler_get_dso(const struct dm_event_handler *h)
const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh)
{
return h->dso;
return dmevh->dso;
}
const char *dm_event_handler_get_name(const struct dm_event_handler *h)
const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh)
{
return h->device;
return dmevh->dev_name;
}
const char *dm_event_handler_get_uuid(const struct dm_event_handler *h)
const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh)
{
return h->uuid;
return dmevh->uuid;
}
int dm_event_handler_get_major(const struct dm_event_handler *h)
int dm_event_handler_get_major(const struct dm_event_handler *dmevh)
{
return h->major;
return dmevh->major;
}
int dm_event_handler_get_minor(const struct dm_event_handler *h)
int dm_event_handler_get_minor(const struct dm_event_handler *dmevh)
{
return h->minor;
return dmevh->minor;
}
enum dm_event_type dm_event_handler_get_events(const struct dm_event_handler *h)
enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh)
{
return h->events;
return dmevh->mask;
}
/*
@@ -145,8 +179,8 @@ enum dm_event_type dm_event_handler_get_events(const struct dm_event_handler *h)
*
* Returns: 0 on failure, 1 on success
*/
static int daemon_read(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg)
static int _daemon_read(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg)
{
unsigned bytes = 0;
int ret, i;
@@ -205,8 +239,8 @@ static int daemon_read(struct dm_event_fifos *fifos,
}
/* Write message to daemon. */
static int daemon_write(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg)
static int _daemon_write(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg)
{
unsigned bytes = 0;
int ret = 0;
@@ -248,14 +282,15 @@ static int daemon_write(struct dm_event_fifos *fifos,
return bytes == size;
}
static int daemon_talk(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg, int cmd,
const char *dso_name, const char *device,
enum dm_event_type events, uint32_t timeout)
static int _daemon_talk(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg, int cmd,
const char *dso_name, const char *dev_name,
enum dm_event_mask evmask, uint32_t timeout)
{
const char *dso = dso_name ? dso_name : "";
const char *dev = device ? device : "";
const char *dev = dev_name ? dev_name : "";
const char *fmt = "%s %s %u %" PRIu32;
int msg_size;
memset(msg, 0, sizeof(*msg));
/*
@@ -263,18 +298,23 @@ static int daemon_talk(struct dm_event_fifos *fifos,
* into ASCII message string.
*/
msg->cmd = cmd;
msg->size = dm_saprintf(&(msg->data), fmt, dso, dev, events, timeout);
if ((msg_size = dm_asprintf(&(msg->data), fmt, dso, dev, evmask,
timeout)) < 0) {
log_error("_daemon_talk: message allocation failed");
return -ENOMEM;
}
msg->size = msg_size;
/*
* Write command and message to and
* read status return code from daemon.
*/
if (!daemon_write(fifos, msg)) {
if (!_daemon_write(fifos, msg)) {
stack;
return -EIO;
}
if (!daemon_read(fifos, msg)) {
if (!_daemon_read(fifos, msg)) {
stack;
return -EIO;
}
@@ -294,7 +334,7 @@ static int daemon_talk(struct dm_event_fifos *fifos,
*
* Returns: 1 on success, 0 otherwise
*/
static int start_daemon(struct dm_event_fifos *fifos)
static int _start_daemon(struct dm_event_fifos *fifos)
{
int pid, ret = 0;
int status;
@@ -332,8 +372,7 @@ static int start_daemon(struct dm_event_fifos *fifos)
log_error("Unable to fork.");
else if (!pid) {
/* FIXME configure path (cf. lvm2 modprobe) */
execvp("dmeventd", NULL);
execvp(DMEVENTD_PATH, NULL);
exit(EXIT_FAILURE);
} else {
if (waitpid(pid, &status, 0) < 0)
@@ -349,7 +388,7 @@ static int start_daemon(struct dm_event_fifos *fifos)
}
/* Initialize client. */
static int init_client(struct dm_event_fifos *fifos)
static int _init_client(struct dm_event_fifos *fifos)
{
/* FIXME? Is fifo the most suitable method? Why not share
comms/daemon code with something else e.g. multipath? */
@@ -359,7 +398,7 @@ static int init_client(struct dm_event_fifos *fifos)
fifos->client_path = DM_EVENT_FIFO_CLIENT;
fifos->server_path = DM_EVENT_FIFO_SERVER;
if (!start_daemon(fifos)) {
if (!_start_daemon(fifos)) {
stack;
return 0;
}
@@ -391,7 +430,7 @@ static int init_client(struct dm_event_fifos *fifos)
return 1;
}
static void dtr_client(struct dm_event_fifos *fifos)
static void _dtr_client(struct dm_event_fifos *fifos)
{
if (flock(fifos->server, LOCK_UN))
log_error("flock unlock %s", fifos->server_path);
@@ -400,76 +439,92 @@ static void dtr_client(struct dm_event_fifos *fifos)
close(fifos->server);
}
/* Get uuid of a device, if it exists (otherwise NULL). */
static struct dm_task *get_device_info(const struct dm_event_handler *h)
/* Get uuid of a device */
static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh)
{
struct dm_task *dmt = dm_task_create(DM_DEVICE_INFO);
struct dm_task *ret;
struct dm_task *dmt;
struct dm_info info;
if (!dmt)
if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
log_error("_get_device_info: dm_task creation for info failed");
return NULL;
if (h->uuid)
dm_task_set_uuid(dmt, h->uuid);
else if (h->device)
dm_task_set_name(dmt, h->device);
else if (h->major && h->minor) {
dm_task_set_major(dmt, h->major);
dm_task_set_minor(dmt, h->minor);
}
if (!dm_task_run(dmt))
ret = NULL;
else
ret = dmt;
if (dmevh->uuid)
dm_task_set_uuid(dmt, dmevh->uuid);
else if (dmevh->dev_name)
dm_task_set_name(dmt, dmevh->dev_name);
else if (dmevh->major && dmevh->minor) {
dm_task_set_major(dmt, dmevh->major);
dm_task_set_minor(dmt, dmevh->minor);
}
return ret;
/* FIXME Add name or uuid or devno to messages */
if (!dm_task_run(dmt)) {
log_error("_get_device_info: dm_task_run() failed");
goto failed;
}
if (!dm_task_get_info(dmt, &info)) {
log_error("_get_device_info: failed to get info for device");
goto failed;
}
if (!info.exists) {
log_error("_get_device_info: device not found");
goto failed;
}
return dmt;
failed:
dm_task_destroy(dmt);
return NULL;
}
/* Handle the event (de)registration call and return negative error codes. */
static int do_event(int cmd, struct dm_event_daemon_message *msg,
const char *dso_name, const char *device,
enum dm_event_type events, uint32_t timeout)
static int _do_event(int cmd, struct dm_event_daemon_message *msg,
const char *dso_name, const char *dev_name,
enum dm_event_mask evmask, uint32_t timeout)
{
int ret;
struct dm_event_fifos fifos;
if (!init_client(&fifos)) {
if (!_init_client(&fifos)) {
stack;
return -ESRCH;
}
ret = daemon_talk(&fifos, msg, cmd, dso_name, device, events, timeout);
ret = _daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
/* what is the opposite of init? */
dtr_client(&fifos);
_dtr_client(&fifos);
return ret;
}
/* External library interface. */
int dm_event_register(const struct dm_event_handler *h)
int dm_event_register_handler(const struct dm_event_handler *dmevh)
{
int ret, err;
int ret = 1, err;
const char *uuid;
struct dm_task *dmt;
struct dm_event_daemon_message msg;
if (!(dmt = get_device_info(h))) {
log_error("%s: device not found", h->device);
if (!(dmt = _get_device_info(dmevh))) {
stack;
return 0;
}
uuid = dm_task_get_uuid(dmt);
if ((err = do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, &msg,
h->dso, uuid, h->events, 0)) < 0) {
if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, &msg,
dmevh->dso, uuid, dmevh->mask, 0)) < 0) {
log_error("%s: event registration failed: %s",
dm_task_get_name(dmt),
msg.data ? msg.data : strerror(-err));
ret = 0;
} else
ret = 1;
}
if (msg.data)
dm_free(msg.data);
@@ -479,28 +534,27 @@ int dm_event_register(const struct dm_event_handler *h)
return ret;
}
int dm_event_unregister(const struct dm_event_handler *h)
int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
{
int ret, err;
int ret = 1, err;
const char *uuid;
struct dm_task *dmt;
struct dm_event_daemon_message msg;
if (!(dmt = get_device_info(h))) {
log_error("%s: device not found", dm_task_get_name(dmt));
if (!(dmt = _get_device_info(dmevh))) {
stack;
return 0;
}
uuid = dm_task_get_uuid(dmt);
if ((err = do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, &msg,
h->dso, uuid, h->events, 0)) < 0) {
if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, &msg,
dmevh->dso, uuid, dmevh->mask, 0)) < 0) {
log_error("%s: event deregistration failed: %s",
dm_task_get_name(dmt),
msg.data ? msg.data : strerror(-err));
ret = 0;
} else
ret = 1;
}
if (msg.data)
dm_free(msg.data);
@@ -510,12 +564,9 @@ int dm_event_unregister(const struct dm_event_handler *h)
return ret;
}
#if 0 /* left out for now */
/* Fetch a string off src and duplicate it into *dest. */
/* FIXME: move to seperate module to share with the daemon. */
static const char delimiter = ' ';
static char *fetch_string(char **src)
/* FIXME: move to separate module to share with the daemon. */
static char *_fetch_string(char **src, const int delimiter)
{
char *p, *ret;
@@ -532,13 +583,14 @@ static char *fetch_string(char **src)
}
/* Parse a device message from the daemon. */
static int parse_message(struct dm_event_daemon_message *msg, char **dso_name,
char **device, enum dm_event_type *events)
static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
char **uuid, enum dm_event_mask *evmask)
{
char *p = msg->data;
if ((*dso_name = fetch_string(&p)) && (*device = fetch_string(&p))) {
*events = atoi(p);
if ((*dso_name = _fetch_string(&p, ' ')) &&
(*uuid = _fetch_string(&p, ' '))) {
*evmask = atoi(p);
return 0;
}
@@ -550,55 +602,95 @@ static int parse_message(struct dm_event_daemon_message *msg, char **dso_name,
* dm_event_get_registered_device
* @dso_name
* @device_path
* @events
* @mask
* @next
*
* FIXME: This function sucks.
*
* Returns: 1 if device found, 0 otherwise (even on error)
* Returns: 0 if handler found, error (-ENOMEM, -ENOENT) otherwise
*/
int dm_event_get_registered_device(char **dso_name, char **device_path,
enum dm_event_type *events, int next)
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
{
int ret;
char *dso_name_arg = NULL, *device_path_arg = NULL;
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;
if (!(ret = do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
DM_EVENT_CMD_GET_REGISTERED_DEVICE,
&msg, *dso_name, *device_path, *events, 0))) {
ret = !parse_message(&msg, &dso_name_arg, &device_path_arg,
events);
} else /* FIXME: Make sure this is ENOENT */
ret = 0;
if (msg.data)
dm_free(msg.data);
if (next) {
if (*dso_name)
dm_free(*dso_name);
if (*device_path)
dm_free(*device_path);
*dso_name = dso_name_arg;
*device_path = device_path_arg;
} else {
if (!(*dso_name))
*dso_name = dso_name_arg;
if (!(*device_path))
*device_path = device_path_arg;
if (!(dmt = _get_device_info(dmevh))) {
stack;
return 0;
}
uuid = dm_task_get_uuid(dmt);
if (!(ret = _do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
DM_EVENT_CMD_GET_REGISTERED_DEVICE,
&msg, dmevh->dso, uuid, dmevh->mask, 0))) {
/* FIXME this will probably horribly break if we get
ill-formatted reply */
ret = _parse_message(&msg, &reply_dso, &reply_uuid, &reply_mask);
} else {
ret = -ENOENT;
goto fail;
}
dm_task_destroy(dmt);
if (msg.data) {
dm_free(msg.data);
msg.data = NULL;
}
_dm_event_handler_clear_dev_info(dmevh);
dmevh->uuid = dm_strdup(reply_uuid);
if (!dmevh->uuid) {
ret = -ENOMEM;
goto fail;
}
if (!(dmt = _get_device_info(dmevh))) {
ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */
goto fail;
}
dm_event_handler_set_dso(dmevh, reply_dso);
dm_event_handler_set_event_mask(dmevh, reply_mask);
dmevh->dev_name = dm_strdup(dm_task_get_name(dmt));
if (!dmevh->dev_name) {
ret = -ENOMEM;
goto fail;
}
struct dm_info info;
if (!dm_task_get_info(dmt, &info)) {
ret = -1;
goto fail;
}
dmevh->major = info.major;
dmevh->minor = info.minor;
dm_task_destroy(dmt);
return ret;
fail:
if (msg.data)
dm_free(msg.data);
_dm_event_handler_clear_dev_info(dmevh);
dm_task_destroy(dmt);
return ret;
}
#if 0 /* left out for now */
int dm_event_set_timeout(const char *device_path, uint32_t timeout)
{
struct dm_event_daemon_message msg;
if (!device_exists(device_path))
return -ENODEV;
return do_event(DM_EVENT_CMD_SET_TIMEOUT, &msg,
return _do_event(DM_EVENT_CMD_SET_TIMEOUT, &msg,
NULL, device_path, 0, timeout);
}
@@ -609,7 +701,7 @@ int dm_event_get_timeout(const char *device_path, uint32_t *timeout)
if (!device_exists(device_path))
return -ENODEV;
if (!(ret = do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path,
if (!(ret = _do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path,
0, 0)))
*timeout = atoi(msg.data);
if (msg.data)

View File

@@ -23,8 +23,11 @@
#include <stdint.h>
/* Event type definitions. */
enum dm_event_type {
/*
* Event library interface.
*/
enum dm_event_mask {
DM_EVENT_SETTINGS_MASK = 0x0000FF,
DM_EVENT_SINGLE = 0x000001, /* Report multiple errors just once. */
DM_EVENT_MULTI = 0x000002, /* Report all of them. */
@@ -33,7 +36,7 @@ enum dm_event_type {
DM_EVENT_SECTOR_ERROR = 0x000100, /* Failure on a particular sector. */
DM_EVENT_DEVICE_ERROR = 0x000200, /* Device failure. */
DM_EVENT_PATH_ERROR = 0x000400, /* Failure on an io path. */
DM_EVENT_ADAPTOR_ERROR = 0x000800, /* Failure off a host adaptor. */
DM_EVENT_ADAPTOR_ERROR = 0x000800, /* Failure of a host adaptor. */
DM_EVENT_STATUS_MASK = 0xFF0000,
DM_EVENT_SYNC_STATUS = 0x010000, /* Mirror synchronization completed/failed. */
@@ -44,50 +47,58 @@ enum dm_event_type {
#define DM_EVENT_ALL_ERRORS DM_EVENT_ERROR_MASK
/* Prototypes for event lib interface. */
struct dm_event_handler;
/* Create and destroy dm_event_handler struct, which is passed to
register/unregister functions below */
struct dm_event_handler *dm_event_handler_create(void);
void dm_event_handler_destroy(struct dm_event_handler *h);
void dm_event_handler_destroy(struct dm_event_handler *dmevh);
/* Set parameters of a handler:
- dso - shared library path to handle the events
(only one of the following three needs to be set)
- name - device name or path
- uuid - device uuid
- major and minor - device major/minor numbers
- events - a bitfield defining which events to handle (see
enum dm_event_type above)
*/
void dm_event_handler_set_dso(struct dm_event_handler *h, const char *path);
void dm_event_handler_set_name(struct dm_event_handler *h, const char *name);
void dm_event_handler_set_uuid(struct dm_event_handler *h, const char *uuid);
void dm_event_handler_set_major(struct dm_event_handler *h, int major);
void dm_event_handler_set_minor(struct dm_event_handler *h, int minor);
void dm_event_handler_set_events(struct dm_event_handler *h,
enum dm_event_type event);
/*
* Path of shared library to handle events.
*
* All of dso, dev_name and uuid strings are duplicated, you do not
* need to keep the pointers valid after the call succeeds. Thes may
* return -ENOMEM though.
*/
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path);
/* Get parameters of a handler, same as above */
const char *dm_event_handler_get_dso(const struct dm_event_handler *h);
const char *dm_event_handler_get_name(const struct dm_event_handler *h);
const char *dm_event_handler_get_uuid(const struct dm_event_handler *h);
int dm_event_handler_get_major(const struct dm_event_handler *h);
int dm_event_handler_get_minor(const struct dm_event_handler *h);
enum dm_event_type dm_event_handler_get_events(const struct dm_event_handler *h);
/*
* Identify the device to monitor by exactly one of dev_name, uuid or
* device number. String arguments are duplicated, see above.
*/
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *dev_name);
/* Call out to dmeventd to register or unregister a handler. If
dmeventd is not running, it is spawned first. */
int dm_event_register(const struct dm_event_handler *h);
int dm_event_unregister(const struct dm_event_handler *h);
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid);
void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major);
void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor);
/*
* Specify mask for events to monitor.
*/
void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
enum dm_event_mask evmask);
const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh);
const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh);
const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh);
int dm_event_handler_get_major(const struct dm_event_handler *dmevh);
int dm_event_handler_get_minor(const struct dm_event_handler *dmevh);
enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh);
/* FIXME Review interface (what about this next thing?) */
int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next);
/*
* Initiate monitoring using dmeventd.
*/
int dm_event_register_handler(const struct dm_event_handler *dmevh);
int dm_event_unregister_handler(const struct dm_event_handler *dmevh);
/* Prototypes for DSO interface, see dmeventd.c, struct dso_data for
detailed descriptions. */
void process_event(struct dm_task *dmt, enum dm_event_type event);
int register_device(const char *device, const char *uuid, int major, int minor);
int unregister_device(const char *device, const char *uuid, int major,
void process_event(struct dm_task *dmt, enum dm_event_mask evmask);
int register_device(const char *dev_name, const char *uuid, int major, int minor);
int unregister_device(const char *dev_name, const char *uuid, int major,
int minor);
#endif

View File

@@ -15,7 +15,6 @@
#include "libdevmapper.h"
#include "libdevmapper-event.h"
#include "lvm2cmd.h"
#include "lvm-string.h"
#include <errno.h>
#include <signal.h>
@@ -62,8 +61,12 @@ static int _get_mirror_event(char *params)
int log_argc, num_devs;
/*
* Unused: 0 409600 mirror
* Used : 2 253:4 253:5 400/400 1 AA 3 cluster 253:3 A
* dm core parms: 0 409600 mirror
* Mirror core parms: 2 253:4 253:5 400/400
* New-style failure params: 1 AA
* New-style log params: 3 cluster 253:3 A
* or 3 disk 253:3 A
* or 1 core
*/
/* number of devices */
@@ -74,9 +77,9 @@ static int _get_mirror_event(char *params)
goto out_parse;
p += strlen(p) + 1;
/* devices names + max log parameters */
args = dm_malloc((num_devs + 8) * sizeof(char *));
if (!args || dm_split_words(p, num_devs + 8, 0, args) < num_devs + 8)
/* devices names + "400/400" + "1 AA" + 1 or 3 log parms + NULL */
args = dm_malloc((num_devs + 7) * sizeof(char *));
if (!args || dm_split_words(p, num_devs + 7, 0, args) < num_devs + 5)
goto out_parse;
dev_status_str = args[2 + num_devs];
@@ -161,7 +164,7 @@ static int _remove_failed_devices(const char *device)
return (r == 1) ? 0 : -1;
}
void process_event(struct dm_task *dmt, enum dm_event_type event)
void process_event(struct dm_task *dmt, enum dm_event_mask event)
{
void *next = NULL;
uint64_t start, length;

View File

@@ -15,7 +15,6 @@
#include "libdevmapper.h"
#include "libdevmapper-event.h"
#include "lvm2cmd.h"
#include "lvm-string.h"
#include <errno.h>
#include <signal.h>
@@ -62,8 +61,12 @@ static int _get_mirror_event(char *params)
int log_argc, num_devs;
/*
* Unused: 0 409600 mirror
* Used : 2 253:4 253:5 400/400 1 AA 3 cluster 253:3 A
* dm core parms: 0 409600 mirror
* Mirror core parms: 2 253:4 253:5 400/400
* New-style failure params: 1 AA
* New-style log params: 3 cluster 253:3 A
* or 3 disk 253:3 A
* or 1 core
*/
/* number of devices */
@@ -74,9 +77,9 @@ static int _get_mirror_event(char *params)
goto out_parse;
p += strlen(p) + 1;
/* devices names + max log parameters */
args = dm_malloc((num_devs + 8) * sizeof(char *));
if (!args || dm_split_words(p, num_devs + 8, 0, args) < num_devs + 8)
/* devices names + "400/400" + "1 AA" + 1 or 3 log parms + NULL */
args = dm_malloc((num_devs + 7) * sizeof(char *));
if (!args || dm_split_words(p, num_devs + 7, 0, args) < num_devs + 5)
goto out_parse;
dev_status_str = args[2 + num_devs];
@@ -161,7 +164,7 @@ static int _remove_failed_devices(const char *device)
return (r == 1) ? 0 : -1;
}
void process_event(struct dm_task *dmt, enum dm_event_type event)
void process_event(struct dm_task *dmt, enum dm_event_mask event)
{
void *next = NULL;
uint64_t start, length;

View File

@@ -655,10 +655,11 @@ int register_dev_for_events(struct cmd_context *cmd,
struct logical_volume *lv, int do_reg)
{
#ifdef DMEVENTD
int i, pending = 0, registered;
int r = 0;
struct list *tmp;
struct lv_segment *seg;
int (*reg) (struct lv_segment *, int events);
int (*reg) (struct cmd_context *c, struct lv_segment *s, int e);
if (do_reg && !dmeventd_register_mode())
return 1;
@@ -666,24 +667,59 @@ int register_dev_for_events(struct cmd_context *cmd,
list_iterate(tmp, &lv->segments) {
seg = list_item(tmp, struct lv_segment);
if (!seg_monitored(seg) || (seg->status & PVMOVE))
continue;
reg = NULL;
if (do_reg) {
if (seg->segtype->ops->target_register_events)
reg = seg->segtype->ops->target_register_events;
} else if (seg->segtype->ops->target_unregister_events)
reg = seg->segtype->ops->target_unregister_events;
/* Check monitoring status */
if (seg->segtype->ops->target_registered)
registered = seg->segtype->ops->target_registered(seg, &pending);
else
continue; /* segtype doesn't support registration */
/*
* FIXME: We should really try again if pending
*/
registered = (pending) ? 0 : registered;
if (do_reg) {
if (registered)
log_verbose("%s/%s already monitored.", lv->vg->name, lv->name);
else if (seg->segtype->ops->target_register_events)
reg = seg->segtype->ops->target_register_events;
} else {
if (!registered)
log_verbose("%s/%s already not monitored.", lv->vg->name, lv->name);
else if (seg->segtype->ops->target_unregister_events)
reg = seg->segtype->ops->target_unregister_events;
}
/* Do [un]monitor */
if (!reg)
continue;
/* FIXME specify events */
if (!reg(seg, 0)) {
if (!reg(cmd, seg, 0)) {
stack;
return -1;
}
r = 1;
/* Check [un]monitor results */
/* Try a couple times if pending, but not forever... */
for (i = 0; i < 10; i++) {
pending = 0;
registered = seg->segtype->ops->target_registered(seg, &pending);
if (pending ||
(!registered && do_reg) ||
(registered && !do_reg))
log_very_verbose("%s/%s %smonitoring still pending.",
lv->vg->name, lv->name, do_reg ? "" : "un");
else
break;
sleep(1);
}
r = (registered && do_reg) || (!registered && !do_reg);
}
return r;
@@ -728,7 +764,7 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
}
}
if (register_dev_for_events(cmd, lv, 0) != 1)
if (register_dev_for_events(cmd, lv, 0) < 0)
/* FIXME Consider aborting here */
stack;
@@ -786,7 +822,7 @@ static int _lv_resume(struct cmd_context *cmd, const char *lvid_s,
memlock_dec();
fs_unlock();
if (register_dev_for_events(cmd, lv, 1) != 1)
if (register_dev_for_events(cmd, lv, 1) < 0)
stack;
return 1;
@@ -832,7 +868,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
return 0;
}
if (register_dev_for_events(cmd, lv, 0) != 1)
if (register_dev_for_events(cmd, lv, 0) < 0)
stack;
memlock_inc();
@@ -905,7 +941,7 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
memlock_dec();
fs_unlock();
if (!register_dev_for_events(cmd, lv, 1) != 1)
if (!register_dev_for_events(cmd, lv, 1) < 0)
stack;
return r;

View File

@@ -853,7 +853,7 @@ static const char *_find_config_str(const struct config_node *cn1,
const struct config_node *n = _find_first_config_node(cn1, cn2, path);
/* Empty strings are ignored */
if ((n && n->v->type == CFG_STRING) && (*n->v->v.str)) {
if ((n && n->v && n->v->type == CFG_STRING) && (*n->v->v.str)) {
log_very_verbose("Setting %s to %s", path, n->v->v.str);
return n->v->v.str;
}

View File

@@ -72,7 +72,7 @@ static int _has_partition_table(struct device *dev)
/* Check for msdos partition table */
part_magic = buf + PART_MAGIC_OFFSET/sizeof(buf[0]);
if ((*part_magic == xlate16(PART_MAGIC))) {
part = (struct partition *) (buf + PART_OFFSET);
part = (struct partition *) (buf + PART_OFFSET/sizeof(buf[0]));
for (p = 0; p < 4; p++, part++) {
/* Table is invalid if boot indicator not 0 or 0x80 */
if ((part->boot_ind & 0x7f)) {

View File

@@ -32,6 +32,7 @@ struct dev_manager;
#define SEG_FORMAT1_SUPPORT 0x00000010U
#define SEG_VIRTUAL 0x00000020U
#define SEG_CANNOT_BE_ZEROED 0x00000040U
#define SEG_MONITORED 0x00000080U
#define seg_is_mirrored(seg) ((seg)->segtype->flags & SEG_AREAS_MIRRORED ? 1 : 0)
#define seg_is_striped(seg) ((seg)->segtype->flags & SEG_AREAS_STRIPED ? 1 : 0)
@@ -39,6 +40,7 @@ struct dev_manager;
#define seg_is_virtual(seg) ((seg)->segtype->flags & SEG_VIRTUAL ? 1 : 0)
#define seg_can_split(seg) ((seg)->segtype->flags & SEG_CAN_SPLIT ? 1 : 0)
#define seg_cannot_be_zeroed(seg) ((seg)->segtype->flags & SEG_CANNOT_BE_ZEROED ? 1 : 0)
#define seg_monitored(seg) ((seg)->segtype->flags & SEG_MONITORED ? 1 : 0)
#define segtype_is_striped(segtype) ((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0)
#define segtype_is_mirrored(segtype) ((segtype)->flags & SEG_AREAS_MIRRORED ? 1 : 0)
@@ -81,8 +83,11 @@ struct segtype_handler {
const struct lv_segment *seg,
struct list *modules);
void (*destroy) (const struct segment_type * segtype);
int (*target_register_events) (struct lv_segment *seg, int events);
int (*target_unregister_events) (struct lv_segment *seg, int events);
int (*target_registered) (struct lv_segment *seg, int *pending);
int (*target_register_events) (struct cmd_context *cmd,
struct lv_segment *seg, int events);
int (*target_unregister_events) (struct cmd_context *cmd,
struct lv_segment *seg, int events);
};
struct segment_type *get_segtype_from_string(struct cmd_context *cmd,

View File

@@ -368,13 +368,12 @@ static int _mirrored_target_present(const struct lv_segment *seg __attribute((un
}
#ifdef DMEVENTD
static int _setup_registration(struct dm_pool *mem, struct cmd_context *cmd,
char **dso)
static int _get_mirror_dso_path(struct cmd_context *cmd, char **dso)
{
char *path;
const char *libpath;
if (!(path = dm_pool_alloc(mem, PATH_MAX))) {
if (!(path = dm_pool_alloc(cmd->mem, PATH_MAX))) {
log_error("Failed to allocate dmeventd library path.");
return 0;
}
@@ -389,78 +388,111 @@ static int _setup_registration(struct dm_pool *mem, struct cmd_context *cmd,
return 1;
}
/* FIXME This gets run while suspended and performs banned operations. */
/* FIXME Merge these two functions */
static int _target_register_events(struct lv_segment *seg,
int events)
static struct dm_event_handler *_create_dm_event_handler(const char *dmname,
const char *dso,
enum dm_event_mask mask)
{
struct dm_event_handler *dmevh;
if (!(dmevh = dm_event_handler_create()))
return_0;
if (dm_event_handler_set_dso(dmevh, dso))
goto fail;
if (dm_event_handler_set_dev_name(dmevh, dmname))
goto fail;
dm_event_handler_set_event_mask(dmevh, mask);
return dmevh;
fail:
dm_event_handler_destroy(dmevh);
return NULL;
}
static int _target_registered(struct lv_segment *seg, int *pending)
{
char *dso, *name;
struct logical_volume *lv;
struct volume_group *vg;
struct dm_event_handler *handler;
enum dm_event_mask evmask = 0;
struct dm_event_handler *dmevh;
lv = seg->lv;
vg = lv->vg;
if (!_setup_registration(vg->cmd->mem, vg->cmd, &dso)) {
stack;
return 0;
}
*pending = 0;
if (!_get_mirror_dso_path(vg->cmd, &dso))
return_0;
if (!(name = build_dm_name(vg->cmd->mem, vg->name, lv->name, NULL)))
return_0;
if (!(handler = dm_event_handler_create()))
if (!(dmevh = _create_dm_event_handler(name, dso, DM_EVENT_ALL_ERRORS)))
return_0;
dm_event_handler_set_dso(handler, dso);
dm_event_handler_set_name(handler, name);
dm_event_handler_set_events(handler, DM_EVENT_ALL_ERRORS);
if (!dm_event_register(handler)) {
dm_event_handler_destroy(handler);
return_0;
if (dm_event_get_registered_device(dmevh, 0)) {
dm_event_handler_destroy(dmevh);
return 0;
}
dm_event_handler_destroy(handler);
log_info("Registered %s for events", name);
evmask = dm_event_handler_get_event_mask(dmevh);
if (evmask & DM_EVENT_REGISTRATION_PENDING) {
*pending = 1;
evmask &= ~DM_EVENT_REGISTRATION_PENDING;
}
dm_event_handler_destroy(dmevh);
return evmask;
}
/* FIXME This gets run while suspended and performs banned operations. */
static int _target_set_events(struct cmd_context *cmd,
struct lv_segment *seg,
int evmask, int set)
{
char *dso, *name;
struct logical_volume *lv;
struct volume_group *vg;
struct dm_event_handler *dmevh;
int r;
lv = seg->lv;
vg = lv->vg;
if (!_get_mirror_dso_path(cmd, &dso))
return_0;
if (!(name = build_dm_name(cmd->mem, vg->name, lv->name, NULL)))
return_0;
if (!(dmevh = _create_dm_event_handler(name, dso, DM_EVENT_ALL_ERRORS)))
return_0;
r = set ? dm_event_register_handler(dmevh) : dm_event_unregister_handler(dmevh);
dm_event_handler_destroy(dmevh);
if (!r)
return_0;
log_info("%s %s for events", set ? "Registered" : "Unregistered", name);
return 1;
}
static int _target_unregister_events(struct lv_segment *seg,
static int _target_register_events(struct cmd_context *cmd,
struct lv_segment *seg,
int events)
{
char *dso;
char *name;
struct logical_volume *lv;
struct volume_group *vg;
struct dm_event_handler *handler;
return _target_set_events(cmd, seg, events, 1);
}
lv = seg->lv;
vg = lv->vg;
/* FIXME Remove this and use handle to avoid config file race */
if (!_setup_registration(vg->cmd->mem, vg->cmd, &dso))
return_0;
if (!(name = build_dm_name(vg->cmd->mem, vg->name, lv->name, NULL)))
return_0;
if (!(handler = dm_event_handler_create()))
return_0;
dm_event_handler_set_dso(handler, dso);
dm_event_handler_set_name(handler, name);
dm_event_handler_set_events(handler, DM_EVENT_ALL_ERRORS);
if (!dm_event_unregister(handler)) {
dm_event_handler_destroy(handler);
return_0;
}
dm_event_handler_destroy(handler);
log_info("Unregistered %s for events", name);
return 1;
static int _target_unregister_events(struct cmd_context *cmd,
struct lv_segment *seg,
int events)
{
return _target_set_events(cmd, seg, events, 0);
}
#endif /* DMEVENTD */
@@ -504,6 +536,7 @@ static struct segtype_handler _mirrored_ops = {
.target_percent = _mirrored_target_percent,
.target_present = _mirrored_target_present,
#ifdef DMEVENTD
.target_registered = _target_registered,
.target_register_events = _target_register_events,
.target_unregister_events = _target_unregister_events,
#endif
@@ -530,7 +563,7 @@ struct segment_type *init_segtype(struct cmd_context *cmd)
segtype->ops = &_mirrored_ops;
segtype->name = "mirror";
segtype->private = NULL;
segtype->flags = SEG_AREAS_MIRRORED;
segtype->flags = SEG_AREAS_MIRRORED | SEG_MONITORED;
log_very_verbose("Initialised segtype: %s", segtype->name);

File diff suppressed because it is too large Load Diff

View File

@@ -115,4 +115,15 @@ dm_split_lvm_name
dm_split_words
dm_snprintf
dm_basename
dm_saprintf
dm_asprintf
dm_report_init
dm_report_object
dm_report_output
dm_report_free
dm_report_get_private
dm_report_field_string
dm_report_field_int
dm_report_field_int32
dm_report_field_uint32
dm_report_field_uint64
dm_report_field_set_value

View File

@@ -24,6 +24,7 @@ SOURCES =\
libdm-file.c \
libdm-deptree.c \
libdm-string.c \
libdm-report.c \
mm/dbg_malloc.c \
mm/pool.c \
$(interface)/libdm-iface.c

View File

@@ -124,10 +124,10 @@ struct dm_names {
};
struct dm_versions {
uint32_t next; /* Offset to next struct from start of this struct */
uint32_t version[3];
uint32_t next; /* Offset to next struct from start of this struct */
uint32_t version[3];
char name[0];
char name[0];
};
int dm_get_library_version(char *version, size_t size);
@@ -236,12 +236,12 @@ int dm_tree_add_dev(struct dm_tree *tree, uint32_t major, uint32_t minor);
* Add a new node to the tree if it doesn't already exist.
*/
struct dm_tree_node *dm_tree_add_new_dev(struct dm_tree *tree,
const char *name,
const char *uuid,
uint32_t major, uint32_t minor,
int read_only,
int clear_inactive,
void *context);
const char *name,
const char *uuid,
uint32_t major, uint32_t minor,
int read_only,
int clear_inactive,
void *context);
/*
* Search for a node in the tree.
@@ -289,16 +289,16 @@ int dm_tree_deactivate_children(struct dm_tree_node *dnode,
* Ignores devices that don't have a uuid starting with uuid_prefix.
*/
int dm_tree_preload_children(struct dm_tree_node *dnode,
const char *uuid_prefix,
size_t uuid_prefix_len);
const char *uuid_prefix,
size_t uuid_prefix_len);
/*
* Resume a device plus all dependencies.
* Ignores devices that don't have a uuid starting with uuid_prefix.
*/
int dm_tree_activate_children(struct dm_tree_node *dnode,
const char *uuid_prefix,
size_t uuid_prefix_len);
const char *uuid_prefix,
size_t uuid_prefix_len);
/*
* Suspend a device plus all dependencies.
@@ -626,7 +626,85 @@ char *dm_basename(const char *path);
/*
* Returns size of a buffer which is allocated with dm_malloc.
* Pointer to the buffer is stored in *buf.
* Returns -1 on failure leaving buf undefined.
*/
int dm_saprintf(char **buf, const char *format, ...);
int dm_asprintf(char **buf, const char *format, ...);
/*********************
* reporting functions
*********************/
struct dm_report_object_type {
uint32_t id; /* Powers of 2 */
const char *desc;
const char *prefix; /* field id string prefix (optional) */
void *(*data_fn)(void *object); /* callback from report_object() */
};
struct dm_report_field;
/*
* dm_report_field_type flags
*/
#define DM_REPORT_FIELD_MASK 0x0000000F
#define DM_REPORT_FIELD_ALIGN_LEFT 0x00000001
#define DM_REPORT_FIELD_ALIGN_RIGHT 0x00000002
#define DM_REPORT_FIELD_STRING 0x00000004
#define DM_REPORT_FIELD_NUMBER 0x00000008
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_* */
int (*report_fn)(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data,
void *private);
};
/*
* dm_report_init output_flags
*/
#define DM_REPORT_OUTPUT_MASK 0x00000007
#define DM_REPORT_OUTPUT_ALIGNED 0x00000001
#define DM_REPORT_OUTPUT_BUFFERED 0x00000002
#define DM_REPORT_OUTPUT_HEADINGS 0x00000004
struct dm_report *dm_report_init(uint32_t *report_types,
const struct dm_report_object_type *types,
const struct dm_report_field_type *fields,
const char *output_fields,
const char *output_separator,
uint32_t output_flags,
const char *sort_keys,
void *private);
int dm_report_object(struct dm_report *rh, void *object);
int dm_report_output(struct dm_report *rh);
void dm_report_free(struct dm_report *rh);
/* report functions for common types */
int dm_report_field_string(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data);
int dm_report_field_int32(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data);
int dm_report_field_uint32(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data);
int dm_report_field_int(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data);
int dm_report_field_uint64(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data);
/*
* Helper function for custom reporting functions
*/
/*
* sortvalue may be NULL if it's the same as value
*/
void dm_report_field_set_value(struct dm_report_field *field,
const void *value, const void *sortvalue);
#endif /* LIB_DEVICE_MAPPER_H */

811
libdm/libdm-report.c Normal file
View File

@@ -0,0 +1,811 @@
/*
* Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004 Red Hat, Inc. All rights reserved.
*
* This file is part of device-mapper userspace tools.
* The code is based on LVM2 report function.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "libdevmapper.h"
#include "list.h"
#include "log.h"
/*
* Internal flags
*/
#define RH_SORT_REQUIRED 0x00000100
#define RH_HEADINGS_PRINTED 0x00000200
struct dm_report {
struct dm_pool *mem;
uint32_t report_types;
const char *field_prefix;
uint32_t flags;
const char *separator;
uint32_t keys_count;
/* Ordered list of fields needed for this report */
struct list field_props;
/* Rows of report data */
struct list rows;
/* Array of field definitions */
const struct dm_report_field_type *fields;
const struct dm_report_object_type *types;
/* To store caller private data */
void *private;
};
/*
* Internal per-field flags
*/
#define FLD_HIDDEN 0x00000100
#define FLD_SORT_KEY 0x00000200
#define FLD_ASCENDING 0x00000400
#define FLD_DESCENDING 0x00000800
struct field_properties {
struct list list;
uint32_t field_num;
uint32_t sort_posn;
unsigned width;
const struct dm_report_object_type *type;
uint32_t flags;
};
/*
* Report data field
*/
struct dm_report_field {
struct list list;
struct field_properties *props;
const char *report_string; /* Formatted ready for display */
const void *sort_value; /* Raw value for sorting */
};
struct row {
struct list list;
struct dm_report *rh;
struct list fields; /* Fields in display order */
struct dm_report_field *(*sort_fields)[]; /* Fields in sort order */
};
static const struct dm_report_object_type *_find_type(struct dm_report *rh,
uint32_t report_type)
{
const struct dm_report_object_type *t;
for (t = rh->types; t->data_fn; t++)
if (t->id == report_type)
return t;
return NULL;
}
/*
* Data-munging functions to prepare each data type for display and sorting
*/
int dm_report_field_string(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data)
{
char *repstr;
if (!(repstr = dm_pool_strdup(rh->mem, *(const char **) data))) {
log_error("dm_report_field_string: dm_pool_strdup failed");
return 0;
}
field->report_string = repstr;
field->sort_value = (const void *) field->report_string;
return 1;
}
int dm_report_field_int(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data)
{
const int value = *(const int *) data;
uint64_t *sortval;
char *repstr;
if (!(repstr = dm_pool_zalloc(rh->mem, 13))) {
log_error("dm_report_field_int: dm_pool_alloc failed");
return 0;
}
if (!(sortval = dm_pool_alloc(rh->mem, sizeof(int64_t)))) {
log_error("dm_report_field_int: dm_pool_alloc failed");
return 0;
}
if (dm_snprintf(repstr, 12, "%d", value) < 0) {
log_error("dm_report_field_int: int too big: %d", value);
return 0;
}
*sortval = (const uint64_t) value;
field->sort_value = sortval;
field->report_string = repstr;
return 1;
}
int dm_report_field_uint32(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data)
{
const uint32_t value = *(const uint32_t *) data;
uint64_t *sortval;
char *repstr;
if (!(repstr = dm_pool_zalloc(rh->mem, 12))) {
log_error("dm_report_field_uint32: dm_pool_alloc failed");
return 0;
}
if (!(sortval = dm_pool_alloc(rh->mem, sizeof(uint64_t)))) {
log_error("dm_report_field_uint32: dm_pool_alloc failed");
return 0;
}
if (dm_snprintf(repstr, 11, "%u", value) < 0) {
log_error("dm_report_field_uint32: uint32 too big: %u", value);
return 0;
}
*sortval = (const uint64_t) value;
field->sort_value = sortval;
field->report_string = repstr;
return 1;
}
int dm_report_field_int32(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data)
{
const int32_t value = *(const int32_t *) data;
uint64_t *sortval;
char *repstr;
if (!(repstr = dm_pool_zalloc(rh->mem, 13))) {
log_error("dm_report_field_int32: dm_pool_alloc failed");
return 0;
}
if (!(sortval = dm_pool_alloc(rh->mem, sizeof(int64_t)))) {
log_error("dm_report_field_int32: dm_pool_alloc failed");
return 0;
}
if (dm_snprintf(repstr, 12, "%d", value) < 0) {
log_error("dm_report_field_int32: int32 too big: %d", value);
return 0;
}
*sortval = (const uint64_t) value;
field->sort_value = sortval;
field->report_string = repstr;
return 1;
}
int dm_report_field_uint64(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data)
{
const int value = *(const uint64_t *) data;
uint64_t *sortval;
char *repstr;
if (!(repstr = dm_pool_zalloc(rh->mem, 22))) {
log_error("dm_report_field_uint64: dm_pool_alloc failed");
return 0;
}
if (!(sortval = dm_pool_alloc(rh->mem, sizeof(uint64_t)))) {
log_error("dm_report_field_uint64: dm_pool_alloc failed");
return 0;
}
if (dm_snprintf(repstr, 21, "%d", value) < 0) {
log_error("dm_report_field_uint64: uint64 too big: %d", value);
return 0;
}
*sortval = (const uint64_t) value;
field->sort_value = sortval;
field->report_string = repstr;
return 1;
}
/*
* Helper functions for custom report functions
*/
void dm_report_field_set_value(struct dm_report_field *field, const void *value, const void *sortvalue)
{
field->report_string = (const char *) value;
field->sort_value = sortvalue ? : value;
}
/*
* show help message
*/
static void _display_fields(struct dm_report *rh)
{
uint32_t f;
const struct dm_report_object_type *type;
const char *desc, *last_desc = "";
for (f = 0; rh->fields[f].report_fn; f++) {
if ((type = _find_type(rh, rh->fields[f].type)) && type->desc)
desc = type->desc;
else
desc = " ";
if (desc != last_desc) {
if (*last_desc)
log_print(" ");
log_print("%s Fields", desc);
}
log_print("- %s", rh->fields[f].id);
last_desc = desc;
}
}
/*
* Initialise report handle
*/
static int _copy_field(struct dm_report *rh, struct field_properties *dest,
uint32_t field_num)
{
dest->field_num = field_num;
dest->width = rh->fields[field_num].width;
dest->flags = rh->fields[field_num].flags & DM_REPORT_FIELD_MASK;
/* set object type method */
dest->type = _find_type(rh, rh->fields[field_num].type);
if (!dest->type) {
log_error("dm_report: field not match: %s",
rh->fields[field_num].id);
return 0;
}
return 1;
}
static int _field_match(struct dm_report *rh, const char *field, size_t flen)
{
uint32_t f, l;
struct field_properties *fp;
if (!flen)
return 0;
for (f = 0; rh->fields[f].report_fn; f++) {
if ((!strncasecmp(rh->fields[f].id, field, flen) &&
strlen(rh->fields[f].id) == flen) ||
(l = strlen(rh->field_prefix),
!strncasecmp(rh->field_prefix, rh->fields[f].id, l) &&
!strncasecmp(rh->fields[f].id + l, field, flen) &&
strlen(rh->fields[f].id) == l + flen)) {
rh->report_types |= rh->fields[f].type;
if (!(fp = dm_pool_zalloc(rh->mem, sizeof(*fp)))) {
log_error("dm_report: "
"struct field_properties allocation "
"failed");
return 0;
}
if (!_copy_field(rh, fp, f))
return 0;
list_add(&rh->field_props, &fp->list);
return 1;
}
}
return 0;
}
static int _add_sort_key(struct dm_report *rh, uint32_t field_num,
uint32_t flags)
{
struct field_properties *fp, *found = NULL;
list_iterate_items(fp, &rh->field_props) {
if (fp->field_num == field_num) {
found = fp;
break;
}
}
if (!found) {
rh->report_types |= rh->fields[field_num].type;
if (!(found = dm_pool_zalloc(rh->mem, sizeof(*found)))) {
log_error("dm_report: "
"struct field_properties allocation failed");
return 0;
}
if (!_copy_field(rh, found, field_num))
return 0;
/* Add as a non-display field */
found->flags |= FLD_HIDDEN;
list_add(&rh->field_props, &found->list);
}
if (found->flags & FLD_SORT_KEY) {
log_error("dm_report: Ignoring duplicate sort field: %s",
rh->fields[field_num].id);
return 1;
}
found->flags |= FLD_SORT_KEY;
found->sort_posn = rh->keys_count++;
found->flags |= flags;
return 1;
}
static int _key_match(struct dm_report *rh, const char *key, size_t len)
{
uint32_t f, l;
uint32_t flags;
if (!len)
return 0;
if (*key == '+') {
key++;
len--;
flags = FLD_ASCENDING;
} else if (*key == '-') {
key++;
len--;
flags = FLD_DESCENDING;
} else
flags = FLD_ASCENDING;
if (!len) {
log_error("dm_report: Missing sort field name");
return 0;
}
for (f = 0; rh->fields[f].report_fn; f++) {
if ((!strncasecmp(rh->fields[f].id, key, len) &&
strlen(rh->fields[f].id) == len) ||
(l = strlen(rh->field_prefix),
!strncasecmp(rh->field_prefix, rh->fields[f].id, l) &&
!strncasecmp(rh->fields[f].id + l, key, len) &&
strlen(rh->fields[f].id) == l + len)) {
return _add_sort_key(rh, f, flags);
}
}
return 0;
}
static int _parse_options(struct dm_report *rh, const char *format)
{
const char *ws; /* Word start */
const char *we = format; /* Word end */
while (*we) {
/* Allow consecutive commas */
while (*we && *we == ',')
we++;
/* start of the field name */
ws = we;
while (*we && *we != ',')
we++;
if (!_field_match(rh, ws, (size_t) (we - ws))) {
_display_fields(rh);
log_print(" ");
log_error("dm_report: Unrecognised field: %.*s",
(int) (we - ws), ws);
return 0;
}
}
return 1;
}
static int _parse_keys(struct dm_report *rh, const char *keys)
{
const char *ws; /* Word start */
const char *we = keys; /* Word end */
while (*we) {
/* Allow consecutive commas */
while (*we && *we == ',')
we++;
ws = we;
while (*we && *we != ',')
we++;
if (!_key_match(rh, ws, (size_t) (we - ws))) {
log_error("dm_report: Unrecognised field: %.*s",
(int) (we - ws), ws);
return 0;
}
}
return 1;
}
struct dm_report *dm_report_init(uint32_t *report_types,
const struct dm_report_object_type *types,
const struct dm_report_field_type *fields,
const char *output_fields,
const char *output_separator,
uint32_t output_flags,
const char *sort_keys,
void *private)
{
struct dm_report *rh;
const struct dm_report_object_type *type;
if (!(rh = dm_malloc(sizeof(*rh)))) {
log_error("dm_report_init: dm_malloc failed");
return 0;
}
memset(rh, 0, sizeof(*rh));
/*
* rh->report_types is updated in _parse_options() and _parse_keys()
* to contain all types corresponding to the fields specified by
* options or keys.
*/
if (report_types)
rh->report_types = *report_types;
rh->separator = output_separator;
rh->fields = fields;
rh->types = types;
rh->private = private;
rh->flags |= output_flags & DM_REPORT_OUTPUT_MASK;
if (output_flags & DM_REPORT_OUTPUT_BUFFERED)
rh->flags |= RH_SORT_REQUIRED;
list_init(&rh->field_props);
list_init(&rh->rows);
if ((type = _find_type(rh, rh->report_types)) && type->prefix)
rh->field_prefix = type->prefix;
else
rh->field_prefix = "";
if (!(rh->mem = dm_pool_create("report", 10 * 1024))) {
log_error("dm_report_init: allocation of memory pool failed");
return NULL;
}
/* Generate list of fields for output based on format string & flags */
if (!_parse_options(rh, output_fields))
return NULL;
if (!_parse_keys(rh, sort_keys))
return NULL;
/* Return updated types value for further compatility check by caller */
if (report_types)
*report_types = rh->report_types;
return rh;
}
void dm_report_free(struct dm_report *rh)
{
dm_pool_destroy(rh->mem);
dm_free(rh);
}
/*
* Create a row of data for an object
*/
static void * _report_get_field_data(struct dm_report *rh,
struct field_properties *fp, void *object)
{
void *ret = fp->type->data_fn(object);
if (!ret)
return NULL;
return ret + rh->fields[fp->field_num].offset;
}
int dm_report_object(struct dm_report *rh, void *object)
{
struct field_properties *fp;
struct row *row;
struct dm_report_field *field;
void *data = NULL;
if (!(row = dm_pool_zalloc(rh->mem, sizeof(*row)))) {
log_error("dm_report_object: struct row allocation failed");
return 0;
}
row->rh = rh;
if ((rh->flags & RH_SORT_REQUIRED) &&
!(row->sort_fields =
dm_pool_zalloc(rh->mem, sizeof(struct dm_report_field *) *
rh->keys_count))) {
log_error("dm_report_object: "
"row sort value structure allocation failed");
return 0;
}
list_init(&row->fields);
list_add(&rh->rows, &row->list);
/* For each field to be displayed, call its report_fn */
list_iterate_items(fp, &rh->field_props) {
if (!(field = dm_pool_zalloc(rh->mem, sizeof(*field)))) {
log_error("dm_report_object: "
"struct dm_report_field allocation failed");
return 0;
}
field->props = fp;
data = _report_get_field_data(rh, fp, object);
if (!data)
return 0;
if (!rh->fields[fp->field_num].report_fn(rh, rh->mem,
field, data,
rh->private)) {
log_error("dm_report_object: "
"report function failed for field %s",
rh->fields[fp->field_num].id);
return 0;
}
if ((strlen(field->report_string) > field->props->width))
field->props->width = strlen(field->report_string);
if ((rh->flags & RH_SORT_REQUIRED) &&
(field->props->flags & FLD_SORT_KEY)) {
(*row->sort_fields)[field->props->sort_posn] = field;
}
list_add(&row->fields, &field->list);
}
if (!(rh->flags & DM_REPORT_OUTPUT_BUFFERED))
return dm_report_output(rh);
return 1;
}
/*
* Print row of headings
*/
static int _report_headings(struct dm_report *rh)
{
struct field_properties *fp;
const char *heading;
char buf[1024];
if (rh->flags & RH_HEADINGS_PRINTED)
return 1;
rh->flags |= RH_HEADINGS_PRINTED;
if (!(rh->flags & DM_REPORT_OUTPUT_HEADINGS))
return 1;
if (!dm_pool_begin_object(rh->mem, 128)) {
log_error("dm_report: "
"dm_pool_begin_object failed for headings");
return 0;
}
/* First heading line */
list_iterate_items(fp, &rh->field_props) {
if (fp->flags & FLD_HIDDEN)
continue;
heading = rh->fields[fp->field_num].heading;
if (rh->flags & DM_REPORT_OUTPUT_ALIGNED) {
if (dm_snprintf(buf, sizeof(buf), "%-*.*s",
fp->width, fp->width, heading) < 0) {
log_error("dm_report: snprintf heading failed");
goto bad;
}
if (!dm_pool_grow_object(rh->mem, buf, fp->width)) {
log_error("dm_report: Failed to generate report headings for printing");
goto bad;
}
} else if (!dm_pool_grow_object(rh->mem, heading,
strlen(heading))) {
log_error("dm_report: Failed to generate report headings for printing");
goto bad;
}
if (!list_end(&rh->field_props, &fp->list))
if (!dm_pool_grow_object(rh->mem, rh->separator,
strlen(rh->separator))) {
log_error("dm_report: Failed to generate report headings for printing");
goto bad;
}
}
if (!dm_pool_grow_object(rh->mem, "\0", 1)) {
log_error("dm_report: Failed to generate report headings for printing");
goto bad;
}
log_print("%s", (char *) dm_pool_end_object(rh->mem));
return 1;
bad:
dm_pool_abandon_object(rh->mem);
return 0;
}
/*
* Sort rows of data
*/
static int _row_compare(const void *a, const void *b)
{
const struct row *rowa = *(const struct row **) a;
const struct row *rowb = *(const struct row **) b;
const struct dm_report_field *sfa, *sfb;
uint32_t cnt;
for (cnt = 0; cnt < rowa->rh->keys_count; cnt++) {
sfa = (*rowa->sort_fields)[cnt];
sfb = (*rowb->sort_fields)[cnt];
if (sfa->props->flags & DM_REPORT_FIELD_NUMBER) {
const uint64_t numa =
*(const uint64_t *) sfa->sort_value;
const uint64_t numb =
*(const uint64_t *) sfb->sort_value;
if (numa == numb)
continue;
if (sfa->props->flags & FLD_ASCENDING) {
return (numa > numb) ? 1 : -1;
} else { /* FLD_DESCENDING */
return (numa < numb) ? 1 : -1;
}
} else { /* DM_REPORT_FIELD_STRING */
const char *stra = (const char *) sfa->sort_value;
const char *strb = (const char *) sfb->sort_value;
int cmp = strcmp(stra, strb);
if (!cmp)
continue;
if (sfa->props->flags & FLD_ASCENDING) {
return (cmp > 0) ? 1 : -1;
} else { /* FLD_DESCENDING */
return (cmp < 0) ? 1 : -1;
}
}
}
return 0; /* Identical */
}
static int _sort_rows(struct dm_report *rh)
{
struct row *(*rows)[];
uint32_t count = 0;
struct row *row;
if (!(rows = dm_pool_alloc(rh->mem, sizeof(**rows) *
list_size(&rh->rows)))) {
log_error("dm_report: sort array allocation failed");
return 0;
}
list_iterate_items(row, &rh->rows)
(*rows)[count++] = row;
qsort(rows, count, sizeof(**rows), _row_compare);
list_init(&rh->rows);
while (count--)
list_add_h(&rh->rows, &(*rows)[count]->list);
return 1;
}
/*
* Produce report output
*/
int dm_report_output(struct dm_report *rh)
{
struct list *fh, *rowh, *ftmp, *rtmp;
struct row *row = NULL;
struct dm_report_field *field;
const char *repstr;
char buf[4096];
unsigned width;
if (list_empty(&rh->rows))
return 1;
/* Sort rows */
if ((rh->flags & RH_SORT_REQUIRED))
_sort_rows(rh);
/* If headings not printed yet, calculate field widths and print them */
if (!(rh->flags & RH_HEADINGS_PRINTED))
_report_headings(rh);
/* Print and clear buffer */
list_iterate_safe(rowh, rtmp, &rh->rows) {
if (!dm_pool_begin_object(rh->mem, 512)) {
log_error("dm_report: "
"dm_pool_begin_object failed for row");
return 0;
}
row = list_item(rowh, struct row);
list_iterate_safe(fh, ftmp, &row->fields) {
field = list_item(fh, struct dm_report_field);
if (field->props->flags & FLD_HIDDEN)
continue;
repstr = field->report_string;
width = field->props->width;
if (!(rh->flags & DM_REPORT_OUTPUT_ALIGNED)) {
if (!dm_pool_grow_object(rh->mem, repstr,
strlen(repstr)))
goto bad_grow;
} else if (field->props->flags & DM_REPORT_FIELD_ALIGN_LEFT) {
if (dm_snprintf(buf, sizeof(buf), "%-*.*s",
width, width, repstr) < 0)
goto bad_snprintf;
if (!dm_pool_grow_object(rh->mem, buf, width))
goto bad_grow;
} else if (field->props->flags & DM_REPORT_FIELD_ALIGN_RIGHT) {
if (dm_snprintf(buf, sizeof(buf), "%*.*s",
width, width, repstr) < 0)
goto bad_snprintf;
if (!dm_pool_grow_object(rh->mem, buf, width))
goto bad_grow;
}
if (!list_end(&row->fields, fh))
if (!dm_pool_grow_object(rh->mem, rh->separator,
strlen(rh->separator)))
goto bad_grow;
list_del(&field->list);
}
if (!dm_pool_grow_object(rh->mem, "\0", 1))
goto bad_grow;
log_print("%s", (char *) dm_pool_end_object(rh->mem));
list_del(&row->list);
}
if (row)
dm_pool_free(rh->mem, row);
return 1;
bad_snprintf:
log_error("dm_report: snprintf row failed");
bad_grow:
log_error("dm_report: Failed to generate row for printing");
dm_pool_abandon_object(rh->mem);
return 0;
}

View File

@@ -129,7 +129,7 @@ char *dm_basename(const char *path)
return p ? p + 1 : (char *) path;
}
int dm_saprintf(char **result, const char *format, ...)
int dm_asprintf(char **result, const char *format, ...)
{
int n, ok = 0, size = 32;
va_list ap;

View File

@@ -20,9 +20,14 @@
char *dm_strdup_aux(const char *str, const char *file, int line)
{
char *ret = dm_malloc_aux_debug(strlen(str) + 1, file, line);
char *ret;
if (ret)
if (!str) {
log_error("Internal error: dm_strdup called with NULL pointer");
return NULL;
}
if ((ret = dm_malloc_aux_debug(strlen(str) + 1, file, line)))
strcpy(ret, str);
return ret;

View File

@@ -533,7 +533,11 @@ static int _message(int argc, char **argv, void *data __attribute((unused)))
for (i = 0; i < argc; i++)
sz += strlen(argv[i]) + 1;
str = dm_malloc(sz);
if (!(str = dm_malloc(sz))) {
err("message string allocation failed");
goto out;
}
memset(str, 0, sz);
for (i = 0; i < argc; i++) {
@@ -1669,7 +1673,7 @@ static char *parse_loop_device_name(char *dev)
char *buf;
char *device;
if (!(buf = dm_malloc(PATH_MAX)));
if (!(buf = dm_malloc(PATH_MAX)))
return NULL;
if (dev[0] == '/') {

View File

@@ -104,8 +104,10 @@ static int lvchange_registration(struct cmd_context *cmd,
(dmeventd_register_mode()) ? "" : "un", lv->name);
r = 0;
} else if (!r) {
log_verbose("Logical volume %s needs no monitoring.",
lv->name);
log_verbose("Logical volume %s needs no %smonitoring, or is already %smonitored",
(dmeventd_register_mode()) ? "" : "un",
lv->name,
(dmeventd_register_mode()) ? "" : "un");
r = 1;
}

View File

@@ -16,6 +16,7 @@
#include "tools.h"
#include "lvm2cmdline.h"
#include "label.h"
#include "memlock.h"
#include "version.h"
#include "lvm2cmd.h"

View File

@@ -152,6 +152,14 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
goto error;
}
if ((lv->status & MIRRORED) ||
(lv->status & MIRROR_LOG) ||
(lv->status & MIRROR_IMAGE)) {
log_error("Mirrored LV, \"%s\" cannot be renamed: %s",
lv->name, strerror(ENOSYS));
goto error;
}
if (!archive(lv->vg)) {
stack;
goto error;

View File

@@ -25,7 +25,7 @@ static int _vgs_single(struct cmd_context *cmd __attribute((unused)),
return ECMD_FAILED;
}
if (!report_object(handle, vg, NULL, NULL, NULL, NULL))
if (!report_object(handle, vg, NULL, NULL, NULL, NULL));
return ECMD_FAILED;
check_current_backup(vg);
@@ -39,7 +39,7 @@ static int _lvs_single(struct cmd_context *cmd, struct logical_volume *lv,
if (!arg_count(cmd, all_ARG) && !lv_is_visible(lv))
return ECMD_PROCESSED;
if (!report_object(handle, lv->vg, lv, NULL, NULL, NULL))
if (!report_object(handle, lv->vg, lv, NULL, NULL, NULL));
return ECMD_FAILED;
return ECMD_PROCESSED;
@@ -48,7 +48,7 @@ static int _lvs_single(struct cmd_context *cmd, struct logical_volume *lv,
static int _segs_single(struct cmd_context *cmd __attribute((unused)),
struct lv_segment *seg, void *handle)
{
if (!report_object(handle, seg->lv->vg, seg->lv, NULL, seg, NULL))
if (!report_object(handle, seg->lv->vg, seg->lv, NULL, seg, NULL));
return ECMD_FAILED;
return ECMD_PROCESSED;
@@ -78,7 +78,7 @@ static int _pvsegs_sub_single(struct cmd_context *cmd, struct volume_group *vg,
goto out;
}
if (!report_object(handle, vg, NULL, pv, NULL, pvseg))
if (!report_object(handle, vg, NULL, pv, NULL, pvseg));
ret = ECMD_FAILED;
out:
@@ -128,7 +128,7 @@ static int _pvs_single(struct cmd_context *cmd, struct volume_group *vg,
}
}
if (!report_object(handle, vg, NULL, pv, NULL, NULL))
if (!report_object(handle, vg, NULL, pv, NULL, NULL));
ret = ECMD_FAILED;
out:
@@ -262,6 +262,26 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
headings)))
return 0;
/* Ensure options selected are compatible */
if (report_type & SEGS)
report_type |= LVS;
if (report_type & PVSEGS)
report_type |= PVS;
if ((report_type & LVS) && (report_type & PVS)) {
log_error("Can't report LV and PV fields at the same time");
return 0;
}
/* Change report type if fields specified makes this necessary */
if (report_type & SEGS)
report_type = SEGS;
else if (report_type & LVS)
report_type = LVS;
else if (report_type & PVSEGS)
report_type = PVSEGS;
else if (report_type & PVS)
report_type = PVS;
switch (report_type) {
case LVS:
r = process_each_lv(cmd, argc, argv, LCK_VG_READ, report_handle,
@@ -285,9 +305,9 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
break;
}
report_output(report_handle);
dm_report_output(report_handle);
report_free(report_handle);
dm_report_free(report_handle);
return r;
}

View File

@@ -993,7 +993,7 @@ static int _create_pv_entry(struct dm_pool *mem, struct pv_list *pvl,
}
/* Determine selected physical extents */
if (!_parse_pes(mem, colon, pe_ranges, dev_name(pvl->pv->dev),
if (!_parse_pes(mem, colon, new_pvl->pe_ranges, dev_name(pvl->pv->dev),
pvl->pv->pe_count)) {
stack;
return 0;

View File

@@ -53,8 +53,7 @@ static int _register_lvs_in_vg(struct cmd_context *cmd,
}
/*
* returns the number of monitored devices, not the number
* of _new_ monitored devices
* returns the number of _new_ monitored devices
*/
return count;
@@ -117,7 +116,7 @@ static int _vgchange_monitoring(struct cmd_context *cmd, struct volume_group *vg
if ((active = lvs_in_vg_activated(vg))) {
monitored = _register_lvs_in_vg(cmd, vg, dmeventd_register_mode());
log_print("%d logical volume(s) in volume group "
"\"%s\" now %smonitored",
"\"%s\" %smonitored",
monitored, vg->name, (dmeventd_register_mode()) ? "" : "un");
}
@@ -157,7 +156,7 @@ static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg)
"already active", active, vg->name);
monitored = _register_lvs_in_vg(cmd, vg, dmeventd_register_mode());
log_verbose("%d existing logical volume(s) in volume "
"group \"%s\" now %smonitored",
"group \"%s\" %smonitored",
monitored, vg->name,
dmeventd_register_mode() ? "" : "un");
}