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

Compare commits

..

43 Commits

Author SHA1 Message Date
Alasdair Kergon
34a74e81e3 pre-release 2007-01-25 23:36:59 +00:00
Alasdair Kergon
cb120ddb15 dmeventd mirror sets ignore_suspended_devices and avoids scanning mirrors. 2007-01-25 23:32:29 +00:00
Alasdair Kergon
f9ee4395b0 also ignore mirrors 2007-01-25 23:03:48 +00:00
Alasdair Kergon
71f06d51ed Add devices/ignore_suspended_devices to ignore suspended dm devices. 2007-01-25 21:22:30 +00:00
Alasdair Kergon
217f70952f don't remove libdm-common.h any more 2007-01-25 15:45:10 +00:00
Alasdair Kergon
f813d41a76 Add some missing close() and fclose() return code checks.
Fix exit statuses of reporting tools (2.02.19).
2007-01-25 14:37:48 +00:00
Alasdair Kergon
d851289d8a Add some missing close() and fclose() return value checks. 2007-01-25 14:16:20 +00:00
Alasdair Kergon
b115b8a2ea Add init script for dmeventd monitoring. 2007-01-24 23:44:43 +00:00
Alasdair Kergon
d0f7067471 lvm.static no longer interacts with dmeventd unless explicitly asked to. 2007-01-24 23:43:27 +00:00
Alasdair Kergon
be5b4c38a7 fix earlier checkin 2007-01-24 22:06:11 +00:00
Alasdair Kergon
d6d597e3dd Migrate dmsetup column-based output over to new libdevmapper report framework. 2007-01-24 18:09:07 +00:00
Alasdair Kergon
84e348fade Add field definitions to report help text.
Remove unnecessary cmd arg from target_*monitor_events().
2007-01-24 16:51:24 +00:00
Alasdair Kergon
910054657e Adjust report field help description layout. 2007-01-24 16:41:33 +00:00
Alasdair Kergon
8357a11249 fix earlier checkin 2007-01-23 23:58:55 +00:00
Alasdair Kergon
9b021ba057 Add descriptions to reporting field definitions. 2007-01-23 19:18:52 +00:00
Alasdair Kergon
317e588efd Add private variable to dmeventd shared library interface. 2007-01-23 17:40:40 +00:00
Alasdair Kergon
b1d32a03c7 add a dso-private variable to dmeventd interface
more inline docn
2007-01-23 17:38:39 +00:00
Alasdair Kergon
ee6e6529ee Long-lived processes write out persistent dev cache in refresh_toolcontext(). 2007-01-23 16:03:54 +00:00
Alasdair Kergon
9d944d6cf9 Fix refresh_toolcontext() always to wipe persistent device filter cache.
Add is_long_lived to toolcontext.
2007-01-23 15:58:06 +00:00
Alasdair Kergon
13635d281a Add --clustered to man pages. 2007-01-23 13:08:34 +00:00
Alasdair Kergon
2493c46970 Streamline dm_report_field_* interface. 2007-01-22 15:07:21 +00:00
Alasdair Kergon
63e4217271 Add dm_event_handler_[gs]et_timeout functions.
Streamline dm_report_field_* interface.
2007-01-22 15:03:57 +00:00
Alasdair Kergon
f4bd12e8e9 register->monitor etc. 2007-01-19 22:21:45 +00:00
Alasdair Kergon
df15f46900 var dev_name->device_name (lvm2 has dev_name()) 2007-01-19 20:42:09 +00:00
Alasdair Kergon
fb3a732361 fix exit status; always print message on child failure 2007-01-19 18:08:36 +00:00
Alasdair Kergon
2d74110feb Add cmdline debug & version options to dmeventd.
Fix oom_adj handling.
2007-01-19 17:22:17 +00:00
Alasdair Kergon
19d102082d Add DM_LIB_VERSION definition to configure.h. 2007-01-19 15:53:01 +00:00
Alasdair Kergon
d2af2c9487 Update reporting man pages. 2007-01-18 22:33:24 +00:00
Alasdair Kergon
82980149fa Suppress 'Unrecognised field' error if report field is 'help'. 2007-01-18 22:15:04 +00:00
Alasdair Kergon
a19bb7b909 fix last checkin 2007-01-18 21:59:02 +00:00
Alasdair Kergon
9d98c3278d No longer necessary to specify alignment for report fields. 2007-01-18 17:48:29 +00:00
Alasdair Kergon
26376ac1c9 Some internal renaming.
Add --separator and --sort to dmsetup (unused as yet).
Make alignment flag optional when specifying report fields.
2007-01-18 17:47:58 +00:00
Alasdair Kergon
8459f99341 post-release 2007-01-17 17:56:15 +00:00
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
57 changed files with 1700 additions and 1546 deletions

View File

@@ -1 +1 @@
2.02.19-cvs (2007-01-12)
2.02.20-cvs (2007-01-25)

View File

@@ -1,5 +1,27 @@
Version 2.02.19 -
Version 2.02.20 - 25th January 2007
===================================
dmeventd mirror sets ignore_suspended_devices and avoids scanning mirrors.
Add devices/ignore_suspended_devices to ignore suspended dm devices.
Add some missing close() and fclose() return code checks.
Fix exit statuses of reporting tools (2.02.19).
Add init script for dmeventd monitoring.
lvm.static no longer interacts with dmeventd unless explicitly asked to.
Add field definitions to report help text.
Remove unnecessary cmd arg from target_*monitor_events().
Add private variable to dmeventd shared library interface.
Long-lived processes write out persistent dev cache in refresh_toolcontext().
Fix refresh_toolcontext() always to wipe persistent device filter cache.
Add is_long_lived to toolcontext.
Add --clustered to man pages.
Streamline dm_report_field_* interface.
Change remaining dmeventd terminology 'register' to 'monitor'.
Update reporting man pages.
No longer necessary to specify alignment type for report fields.
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.

View File

@@ -1,4 +1,18 @@
Version 1.02.15 -
Version 1.02.16 - 25th January 2007
===================================
Add some missing close() and fclose() return value checks.
Migrate dmsetup column-based output over to new libdevmapper report framework.
Add descriptions to reporting field definitions.
Add a dso-private variable to dmeventd dso interface.
Add dm_event_handler_[gs]et_timeout functions.
Streamline dm_report_field_* interface.
Add cmdline debug & version options to dmeventd.
Add DM_LIB_VERSION definition to configure.h.
Suppress 'Unrecognised field' error if report field is 'help'.
Add --separator and --sort to dmsetup (unused).
Make alignment flag optional when specifying report fields.
Version 1.02.15 - 17th January 2007
===================================
Add basic reporting functions to libdevmapper.
Fix a malloc error path in dmsetup message.

View File

@@ -325,8 +325,8 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
init_mirror_in_sync(1);
if (!(lock_flags & LCK_DMEVENTD_REGISTER_MODE))
init_dmeventd_register(0);
if (!(lock_flags & LCK_DMEVENTD_MONITOR_MODE))
init_dmeventd_monitor(0);
switch (command) {
case LCK_LV_EXCLUSIVE:
@@ -362,8 +362,8 @@ int do_lock_lv(unsigned char command, unsigned char lock_flags, char *resource)
if (lock_flags & LCK_MIRROR_NOSYNC_MODE)
init_mirror_in_sync(0);
if (!(lock_flags & LCK_DMEVENTD_REGISTER_MODE))
init_dmeventd_register(DEFAULT_DMEVENTD_MONITOR);
if (!(lock_flags & LCK_DMEVENTD_MONITOR_MODE))
init_dmeventd_monitor(DEFAULT_DMEVENTD_MONITOR);
/* clean the pool for another command */
dm_pool_empty(cmd->mem);
@@ -473,7 +473,8 @@ static void drop_vg_locks()
sync_unlock(vg, LCK_EXCL);
}
fclose(vgs);
if (fclose(vgs))
DEBUGLOG("vgs fclose failed: %s\n", strerror(errno));
}
/*
@@ -523,7 +524,8 @@ static void *get_initial_state()
}
}
}
fclose(lvs);
if (fclose(lvs))
DEBUGLOG("lvs fclose failed: %s\n", strerror(errno));
return NULL;
}
@@ -575,7 +577,7 @@ void init_lvhash()
/* Called to initialise the LVM context of the daemon */
int init_lvm(int using_gulm)
{
if (!(cmd = create_toolcontext(NULL, 0))) {
if (!(cmd = create_toolcontext(NULL, 0, 1))) {
log_error("Failed to allocate command context");
return 0;
}

View File

@@ -15,3 +15,5 @@ dm_event_handler_get_event_mask
dm_event_register_handler
dm_event_unregister_handler
dm_event_get_registered_device
dm_event_handler_set_timeout
dm_event_handler_get_timeout

View File

@@ -39,7 +39,14 @@
#include <arpa/inet.h> /* for htonl, ntohl */
#ifdef linux
#include <malloc.h>
# include <malloc.h>
# define OOM_ADJ_FILE "/proc/self/oom_adj"
/* From linux/oom.h */
# define OOM_DISABLE (-17)
# define OOM_ADJUST_MIN (-16)
#endif
/* FIXME We use syslog for now, because multilog is not yet implemented */
@@ -47,6 +54,7 @@
static volatile sig_atomic_t _exit_now = 0; /* set to '1' when signal is given to exit */
static volatile sig_atomic_t _thread_registries_empty = 1; /* registries are empty initially */
static int _debug = 0;
/* List (un)link macros. */
#define LINK(x, head) list_add(head, &(x)->list)
@@ -59,13 +67,37 @@ static volatile sig_atomic_t _thread_registries_empty = 1; /* registries are emp
#define DAEMON_NAME "dmeventd"
/* Global mutex for list accesses. */
/*
Global mutex for thread list access. Has to be held when:
- iterating thread list
- adding or removing elements from thread list
- changing or reading thread_status's fields:
processing, status, events
Use _lock_mutex() and _unlock_mutex() to hold/release it
*/
static pthread_mutex_t _global_mutex;
/*
There are three states a thread can attain (see struct
thread_status, field int status):
- DM_THREAD_RUNNING: thread has started up and is either working or
waiting for events... transitions to either SHUTDOWN or DONE
- DM_THREAD_SHUTDOWN: thread is still doing something, but it is
supposed to terminate (and transition to DONE) as soon as it
finishes whatever it was doing at the point of flipping state to
SHUTDOWN... the thread is still on the thread list
- DM_THREAD_DONE: thread has terminated and has been moved over to
unused thread list, cleanup pending
*/
#define DM_THREAD_RUNNING 0
#define DM_THREAD_SHUTDOWN 1
#define DM_THREAD_DONE 2
#define THREAD_STACK_SIZE (300*1024)
#define DEBUGLOG(fmt, args...) _debuglog(fmt, ## args)
/* Data kept about a DSO. */
struct dso_data {
struct list list;
@@ -87,7 +119,7 @@ struct dso_data {
* DM_DEVICE_STATUS). It should not destroy it.
* The caller must dispose of the task.
*/
void (*process_event)(struct dm_task *dmt, enum dm_event_mask event);
void (*process_event)(struct dm_task *dmt, enum dm_event_mask event, void **user);
/*
* Device registration.
@@ -98,7 +130,7 @@ struct dso_data {
* and activate a mapping).
*/
int (*register_device)(const char *device, const char *uuid, int major,
int minor);
int minor, void **user);
/*
* Device unregistration.
@@ -108,7 +140,7 @@ struct dso_data {
* steps (eg, deactivate mapping, metadata update).
*/
int (*unregister_device)(const char *device, const char *uuid,
int major, int minor);
int major, int minor, void **user);
};
static LIST_INIT(_dso_registry);
@@ -147,13 +179,16 @@ struct thread_status {
} device;
uint32_t event_nr; /* event number */
int processing; /* Set when event is being processed */
int status; /* running/shutdown/done */
int status; /* see DM_THREAD_{RUNNING,SHUTDOWN,DONE}
constants above */
enum dm_event_mask events; /* bitfield for event filter. */
enum dm_event_mask current_events; /* bitfield for occured events. */
struct dm_task *current_task;
time_t next_time;
uint32_t timeout;
struct list timeout_list;
void *dso_private; /* dso per-thread status variable */
};
static LIST_INIT(_thread_registry);
static LIST_INIT(_thread_registry_unused);
@@ -163,6 +198,24 @@ static LIST_INIT(_timeout_registry);
static pthread_mutex_t _timeout_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t _timeout_cond = PTHREAD_COND_INITIALIZER;
static void _debuglog(const char *fmt, ...)
{
time_t P;
va_list ap;
if (!_debug)
return;
va_start(ap,fmt);
time(&P);
fprintf(stderr, "dmeventd[%p]: %.15s ", (void *) pthread_self(), ctime(&P)+4 );
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
}
/* Allocate/free the status structure for a monitoring thread. */
static struct thread_status *_alloc_thread_status(struct message_data *data,
struct dso_data *dso_data)
@@ -213,6 +266,18 @@ static struct dso_data *_alloc_dso_data(struct message_data *data)
return ret;
}
/* Create a device monitoring thread. */
static int _pthread_create_smallstack(pthread_t *t, void *(*fun)(void *), void *arg)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
/*
* We use a smaller stack since it gets preallocated in its entirety
*/
pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE);
return pthread_create(t, &attr, fun, arg);
}
static void _free_dso_data(struct dso_data *data)
{
dm_free(data->dso_name);
@@ -225,7 +290,7 @@ static void _free_dso_data(struct dso_data *data)
*/
/* FIXME? move to libdevmapper to share with the client lib (need to
make delimiter a parameter then) */
static int _fetch_string(char **ptr, char **src, const char delimiter)
static int _fetch_string(char **ptr, char **src, const int delimiter)
{
int ret = 0;
char *p;
@@ -307,7 +372,8 @@ static int _parse_message(struct message_data *message_data)
return ret;
};
/* Global mutex to lock access to lists et al. */
/* Global mutex to lock access to lists et al. See _global_mutex
above. */
static int _lock_mutex(void)
{
return pthread_mutex_lock(&_global_mutex);
@@ -400,14 +466,14 @@ static void _exit_dm_lib(void)
dm_lib_exit();
}
static void _exit_timeout(void *unused)
static void _exit_timeout(void *unused __attribute((unused)))
{
_timeout_running = 0;
pthread_mutex_unlock(&_timeout_mutex);
}
/* Wake up monitor threads every so often. */
static void *_timeout_thread(void *unused)
static void *_timeout_thread(void *unused __attribute((unused)))
{
struct timespec timeout;
time_t curr_time;
@@ -419,16 +485,16 @@ static void *_timeout_thread(void *unused)
while (!list_empty(&_timeout_registry)) {
struct thread_status *thread;
timeout.tv_sec = (time_t) -1;
timeout.tv_sec = 0;
curr_time = time(NULL);
list_iterate_items_gen(thread, &_timeout_registry, timeout_list) {
if (thread->next_time < curr_time) {
if (thread->next_time <= curr_time) {
thread->next_time = curr_time + thread->timeout;
pthread_kill(thread->thread, SIGALRM);
}
if (thread->next_time < timeout.tv_sec)
if (thread->next_time < timeout.tv_sec || !timeout.tv_sec)
timeout.tv_sec = thread->next_time;
}
@@ -458,8 +524,7 @@ static int _register_for_timeout(struct thread_status *thread)
if (!_timeout_running) {
pthread_t timeout_id;
if (!(ret = -pthread_create(&timeout_id, NULL,
_timeout_thread, NULL)))
if (!(ret = -_pthread_create_smallstack(&timeout_id, _timeout_thread, NULL)))
_timeout_running = 1;
}
@@ -581,7 +646,8 @@ static int _do_register_device(struct thread_status *thread)
return thread->dso_data->register_device(thread->device.name,
thread->device.uuid,
thread->device.major,
thread->device.minor);
thread->device.minor,
&(thread->dso_private));
}
/* Unregister a device with the DSO. */
@@ -590,19 +656,20 @@ static int _do_unregister_device(struct thread_status *thread)
return thread->dso_data->unregister_device(thread->device.name,
thread->device.uuid,
thread->device.major,
thread->device.minor);
thread->device.minor,
&(thread->dso_private));
}
/* Process an event in the DSO. */
static void _do_process_event(struct thread_status *thread, struct dm_task *task)
{
thread->dso_data->process_event(task, thread->current_events);
thread->dso_data->process_event(task, thread->current_events, &(thread->dso_private));
}
/* Thread cleanup handler to unregister device. */
static void _monitor_unregister(void *arg)
{
struct thread_status *thread = arg;
struct thread_status *thread = arg, *thread_iter;
if (!_do_unregister_device(thread))
syslog(LOG_ERR, "%s: %s unregister failed\n", __func__,
@@ -610,6 +677,45 @@ static void _monitor_unregister(void *arg)
if (thread->current_task)
dm_task_destroy(thread->current_task);
thread->current_task = NULL;
_lock_mutex();
if (thread->events & DM_EVENT_TIMEOUT) {
/* _unregister_for_timeout locks another mutex, we
don't want to deadlock so we release our mutex for
a bit */
_unlock_mutex();
_unregister_for_timeout(thread);
_lock_mutex();
}
/* we may have been relinked to unused registry since we were
called, so check that */
list_iterate_items(thread_iter, &_thread_registry_unused)
if (thread_iter == thread) {
thread->status = DM_THREAD_DONE;
_unlock_mutex();
return;
}
thread->status = DM_THREAD_DONE;
UNLINK_THREAD(thread);
LINK(thread, &_thread_registry_unused);
_unlock_mutex();
}
static struct dm_task *_get_device_status(struct thread_status *ts)
{
struct dm_task *dmt = dm_task_create(DM_DEVICE_STATUS);
if (!dmt)
return NULL;
dm_task_set_uuid(dmt, ts->device.uuid);
if (!dm_task_run(dmt)) {
dm_task_destroy(dmt);
return NULL;
}
return dmt;
}
/* Device monitoring thread. */
@@ -638,6 +744,18 @@ static void *_monitor_thread(void *arg)
if (wait_error == DM_WAIT_FATAL)
break;
/* Timeout occurred, task is not filled properly.
* We get device status here for processing it in DSO.
*/
if (wait_error == DM_WAIT_INTR &&
thread->current_events & DM_EVENT_TIMEOUT) {
dm_task_destroy(task);
task = _get_device_status(thread);
/* FIXME: syslog fail here ? */
if (!(thread->current_task = task))
continue;
}
/*
* We know that wait succeeded and stored a
* pointer to dm_task with device status into task.
@@ -676,10 +794,6 @@ static void *_monitor_thread(void *arg)
}
}
_lock_mutex();
thread->status = DM_THREAD_DONE;
_unlock_mutex();
pthread_cleanup_pop(1);
return NULL;
@@ -688,7 +802,7 @@ static void *_monitor_thread(void *arg)
/* Create a device monitoring thread. */
static int _create_thread(struct thread_status *thread)
{
return pthread_create(&thread->thread, NULL, _monitor_thread, thread);
return _pthread_create_smallstack(&thread->thread, _monitor_thread, thread);
}
static int _terminate_thread(struct thread_status *thread)
@@ -701,7 +815,7 @@ static int _terminate_thread(struct thread_status *thread)
return pthread_kill(thread->thread, SIGALRM);
}
/* DSO reference counting. */
/* DSO reference counting. Call with _global_mutex locked! */
static void _lib_get(struct dso_data *data)
{
data->ref_count++;
@@ -721,8 +835,6 @@ static struct dso_data *_lookup_dso(struct message_data *data)
{
struct dso_data *dso_data, *ret = NULL;
_lock_mutex();
list_iterate_items(dso_data, &_dso_registry)
if (!strcmp(data->dso_name, dso_data->dso_name)) {
_lib_get(dso_data);
@@ -730,14 +842,11 @@ static struct dso_data *_lookup_dso(struct message_data *data)
break;
}
_unlock_mutex();
return ret;
}
/* Lookup DSO symbols we need. */
static int _lookup_symbol(void *dl, struct dso_data *data,
void **symbol, const char *name)
static int _lookup_symbol(void *dl, void **symbol, const char *name)
{
if ((*symbol = dlsym(dl, name)))
return 1;
@@ -747,11 +856,11 @@ static int _lookup_symbol(void *dl, struct dso_data *data,
static int lookup_symbols(void *dl, struct dso_data *data)
{
return _lookup_symbol(dl, data, (void *) &data->process_event,
return _lookup_symbol(dl, (void *) &data->process_event,
"process_event") &&
_lookup_symbol(dl, data, (void *) &data->register_device,
_lookup_symbol(dl, (void *) &data->register_device,
"register_device") &&
_lookup_symbol(dl, data, (void *) &data->unregister_device,
_lookup_symbol(dl, (void *) &data->unregister_device,
"unregister_device");
}
@@ -847,12 +956,12 @@ static int _register_for_event(struct message_data *message_data)
usually means we are so starved on resources that we are
almost as good as dead already... */
if (thread_new->events & DM_EVENT_TIMEOUT) {
ret = -_register_for_timeout(thread);
if (ret) {
_unlock_mutex();
goto out;
}
}
ret = -_register_for_timeout(thread_new);
if (ret) {
_unlock_mutex();
goto out;
}
}
if (!(thread = _lookup_thread_status(message_data))) {
_unlock_mutex();
@@ -912,6 +1021,13 @@ static int _unregister_for_event(struct message_data *message_data)
goto out;
}
if (thread->status == DM_THREAD_DONE) {
/* the thread has terminated while we were not
watching */
_unlock_mutex();
return 0;
}
thread->events &= ~message_data->events.field;
if (!(thread->events & DM_EVENT_TIMEOUT))
@@ -963,52 +1079,71 @@ static int _want_registered_device(char *dso_name, char *device_uuid,
/* If DSO names and device paths are equal. */
if (dso_name && device_uuid)
return !strcmp(dso_name, thread->dso_data->dso_name) &&
!strcmp(device_uuid, thread->device.uuid);
!strcmp(device_uuid, thread->device.uuid) &&
(thread->status == DM_THREAD_RUNNING ||
(thread->events & DM_EVENT_REGISTRATION_PENDING));
/* If DSO names are equal. */
if (dso_name)
return !strcmp(dso_name, thread->dso_data->dso_name);
return !strcmp(dso_name, thread->dso_data->dso_name) &&
(thread->status == DM_THREAD_RUNNING ||
(thread->events & DM_EVENT_REGISTRATION_PENDING));
/* If device paths are equal. */
if (device_uuid)
return !strcmp(device_uuid, thread->device.uuid);
return !strcmp(device_uuid, thread->device.uuid) &&
(thread->status == DM_THREAD_RUNNING ||
(thread->events & DM_EVENT_REGISTRATION_PENDING));
return 1;
}
static int _get_registered_dev(struct message_data *message_data, int next)
{
int hit = 0;
struct thread_status *thread;
struct thread_status *thread, *hit = NULL;
_lock_mutex();
/* Iterate list of threads checking if we want a particular one. */
list_iterate_items(thread, &_thread_registry)
if ((hit = _want_registered_device(message_data->dso_name,
message_data->device_uuid,
thread)))
break;
if (_want_registered_device(message_data->dso_name,
message_data->device_uuid,
thread)) {
hit = thread;
break;
}
/*
* If we got a registered device and want the next one ->
* fetch next conforming element off the list.
*/
if (!hit || !next)
if (hit && !next) {
_unlock_mutex();
return _registered_device(message_data, hit);
}
if (!hit)
goto out;
do {
thread = hit;
while (1) {
if (list_end(&_thread_registry, &thread->list))
goto out;
thread = list_item(thread->list.n, struct thread_status);
} while (!_want_registered_device(message_data->dso_name, NULL, thread));
if (_want_registered_device(message_data->dso_name, NULL, thread)) {
hit = thread;
break;
}
}
return _registered_device(message_data, thread);
_unlock_mutex();
return _registered_device(message_data, hit);
out:
_unlock_mutex();
return -ENOENT;
}
@@ -1303,7 +1438,7 @@ static void _cleanup_unused_threads(void)
if (thread->status == DM_THREAD_RUNNING) {
thread->status = DM_THREAD_SHUTDOWN;
break;
}
}
if (thread->status == DM_THREAD_SHUTDOWN) {
if (!thread->events) {
@@ -1319,7 +1454,7 @@ static void _cleanup_unused_threads(void)
stack;
}
break;
}
}
list_del(l);
syslog(LOG_ERR,
@@ -1341,7 +1476,7 @@ static void _cleanup_unused_threads(void)
_unlock_mutex();
}
static void _sig_alarm(int signum)
static void _sig_alarm(int signum __attribute((unused)))
{
pthread_testcancel();
}
@@ -1373,7 +1508,7 @@ static void _init_thread_signals(void)
* Set the global variable which the process should
* be watching to determine when to exit.
*/
static void _exit_handler(int sig)
static void _exit_handler(int sig __attribute((unused)))
{
/*
* We exit when '_exit_now' is set.
@@ -1407,30 +1542,64 @@ static int _lock_pidfile(void)
return 0;
}
#ifdef linux
/*
* Protection against OOM killer if kernel supports it
*/
static int _set_oom_adj(int val)
{
FILE *fp;
struct stat st;
if (stat(OOM_ADJ_FILE, &st) == -1) {
if (errno == ENOENT)
DEBUGLOG(OOM_ADJ_FILE " not found");
else
perror(OOM_ADJ_FILE ": stat failed");
return 1;
}
if (!(fp = fopen(OOM_ADJ_FILE, "w"))) {
perror(OOM_ADJ_FILE ": fopen failed");
return 0;
}
fprintf(fp, "%i", val);
if (fclose(fp))
perror(OOM_ADJ_FILE ": fclose failed");
return 1;
}
#endif
static void _daemonize(void)
{
int status;
int pid;
int child_status;
int fd;
pid_t pid;
struct rlimit rlim;
struct timeval tval;
sigset_t my_sigset;
sigemptyset(&my_sigset);
if (sigprocmask(SIG_SETMASK, &my_sigset, NULL) < 0) {
fprintf(stderr, "Unable to restore signals.");
fprintf(stderr, "Unable to restore signals.\n");
exit(EXIT_FAILURE);
}
signal(SIGTERM, &_exit_handler);
pid = fork();
if (pid < 0)
switch (pid = fork()) {
case -1:
perror("fork failed:");
exit(EXIT_FAILURE);
if (pid) {
case 0: /* Child */
break;
default:
/* Wait for response from child */
while (!waitpid(pid, &status, WNOHANG) && !_exit_now) {
while (!waitpid(pid, &child_status, WNOHANG) && !_exit_now) {
tval.tv_sec = 0;
tval.tv_usec = 250000; /* .25 sec */
select(0, NULL, NULL, NULL, &tval);
@@ -1440,27 +1609,23 @@ static void _daemonize(void)
exit(EXIT_SUCCESS);
/* Problem with child. Determine what it is by exit code */
switch (WEXITSTATUS(status)) {
switch (WEXITSTATUS(child_status)) {
case EXIT_LOCKFILE_INUSE:
fprintf(stderr, "Another dmeventd daemon is already running\n");
break;
case EXIT_DESC_CLOSE_FAILURE:
break;
case EXIT_DESC_OPEN_FAILURE:
break;
case EXIT_OPEN_PID_FAILURE:
break;
case EXIT_FIFO_FAILURE:
break;
case EXIT_CHDIR_FAILURE:
break;
default:
fprintf(stderr, "Child exited with code %d\n", WEXITSTATUS(child_status));
break;
}
exit(EXIT_FAILURE); /* Redundant */
exit(WEXITSTATUS(child_status));
}
setsid();
if (chdir("/"))
exit(EXIT_CHDIR_FAILURE);
@@ -1477,6 +1642,51 @@ static void _daemonize(void)
(open("/dev/null", O_WRONLY) < 0))
exit(EXIT_DESC_OPEN_FAILURE);
setsid();
}
static void usage(char *prog, FILE *file)
{
fprintf(file, "Usage:\n");
fprintf(file, "%s [Vhd]\n", prog);
fprintf(file, "\n");
fprintf(file, " -V Show version of dmeventd\n");
fprintf(file, " -h Show this help information\n");
fprintf(file, " -d Don't fork, run in the foreground\n");
fprintf(file, "\n");
}
int main(int argc, char *argv[])
{
int ret;
signed char opt;
struct dm_event_fifos fifos;
//struct sys_log logdata = {DAEMON_NAME, LOG_DAEMON};
opterr = 0;
optind = 0;
while ((opt = getopt(argc, argv, "?hVd")) != EOF) {
switch (opt) {
case 'h':
usage(argv[0], stdout);
exit(0);
case '?':
usage(argv[0], stderr);
exit(0);
case 'd':
_debug++;
break;
case 'V':
printf("dmeventd version: %s\n", DM_LIB_VERSION);
exit(1);
break;
}
}
if (!_debug)
_daemonize();
openlog("dmeventd", LOG_PID, LOG_DAEMON);
_lock_pidfile(); /* exits if failure */
@@ -1485,15 +1695,11 @@ static void _daemonize(void)
signal(SIGINT, &_exit_handler);
signal(SIGHUP, &_exit_handler);
signal(SIGQUIT, &_exit_handler);
}
int main(int argc, char *argv[])
{
int ret;
struct dm_event_fifos fifos;
//struct sys_log logdata = {DAEMON_NAME, LOG_DAEMON};
_daemonize();
#ifdef linux
if (!_set_oom_adj(OOM_DISABLE) && !_set_oom_adj(OOM_ADJUST_MIN))
syslog(LOG_ERR, "Failed to set oom_adj to protect against OOM killer");
#endif
_init_thread_signals();
@@ -1516,7 +1722,7 @@ int main(int argc, char *argv[])
/* Signal parent, letting them know we are ready to go. */
kill(getppid(), SIGTERM);
syslog(LOG_INFO, "dmeventd ready for processing.");
syslog(LOG_NOTICE, "dmeventd ready for processing.");
while (!_exit_now) {
_process_request(&fifos);
@@ -1535,7 +1741,8 @@ int main(int argc, char *argv[])
#endif
pthread_mutex_destroy(&_global_mutex);
syslog(LOG_INFO, "dmeventd shutting down.");
syslog(LOG_NOTICE, "dmeventd shutting down.");
closelog();
exit(EXIT_SUCCESS);
}

View File

@@ -31,19 +31,24 @@
#include <arpa/inet.h> /* for htonl, ntohl */
struct dm_event_handler {
const char *dso;
char *dso;
const char *dev_name;
char *dev_name;
const char *uuid;
char *uuid;
int major;
int minor;
uint32_t timeout;
enum dm_event_mask mask;
};
static void dm_event_handler_clear_dev_name(struct dm_event_handler *dmevh)
static void _dm_event_handler_clear_dev_info(struct dm_event_handler *dmevh)
{
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;
}
@@ -58,39 +63,64 @@ struct dm_event_handler *dm_event_handler_create(void)
dmevh->dso = dmevh->dev_name = dmevh->uuid = NULL;
dmevh->major = dmevh->minor = 0;
dmevh->mask = 0;
dmevh->timeout = 0;
return dmevh;
}
void dm_event_handler_destroy(struct dm_event_handler *dmevh)
{
_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 *dmevh, const char *path)
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path)
{
dmevh->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_dev_name(struct dm_event_handler *dmevh, const char *dev_name)
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *dev_name)
{
dm_event_handler_clear_dev_name(dmevh);
if (!dev_name)
return 0;
dmevh->dev_name = dev_name;
_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 *dmevh, const char *uuid)
int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid)
{
dm_event_handler_clear_dev_name(dmevh);
if (!uuid)
return 0;
dmevh->uuid = uuid;
_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 *dmevh, int major)
{
int minor = dmevh->minor;
dm_event_handler_clear_dev_name(dmevh);
_dm_event_handler_clear_dev_info(dmevh);
dmevh->major = major;
dmevh->minor = minor;
@@ -100,7 +130,7 @@ void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor)
{
int major = dmevh->major;
dm_event_handler_clear_dev_name(dmevh);
_dm_event_handler_clear_dev_info(dmevh);
dmevh->major = major;
dmevh->minor = minor;
@@ -112,6 +142,11 @@ void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,
dmevh->mask = evmask;
}
void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout)
{
dmevh->timeout = timeout;
}
const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh)
{
return dmevh->dso;
@@ -137,6 +172,11 @@ int dm_event_handler_get_minor(const struct dm_event_handler *dmevh)
return dmevh->minor;
}
int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh)
{
return dmevh->timeout;
}
enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh)
{
return dmevh->mask;
@@ -262,6 +302,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;
int msg_size;
memset(msg, 0, sizeof(*msg));
/*
@@ -269,10 +310,12 @@ 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,
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
@@ -453,8 +496,8 @@ failed:
/* 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 *dev_name,
enum dm_event_mask evmask, uint32_t timeout)
const char *dso_name, const char *dev_name,
enum dm_event_mask evmask, uint32_t timeout)
{
int ret;
struct dm_event_fifos fifos;
@@ -488,7 +531,7 @@ int dm_event_register_handler(const struct dm_event_handler *dmevh)
uuid = dm_task_get_uuid(dmt);
if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, &msg,
dmevh->dso, uuid, dmevh->mask, 0)) < 0) {
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
log_error("%s: event registration failed: %s",
dm_task_get_name(dmt),
msg.data ? msg.data : strerror(-err));
@@ -518,7 +561,7 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
uuid = dm_task_get_uuid(dmt);
if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, &msg,
dmevh->dso, uuid, dmevh->mask, 0)) < 0) {
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
log_error("%s: event deregistration failed: %s",
dm_task_get_name(dmt),
msg.data ? msg.data : strerror(-err));
@@ -535,7 +578,7 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
/* Fetch a string off src and duplicate it into *dest. */
/* FIXME: move to separate module to share with the daemon. */
static char *_fetch_string(char **src, const char delimiter)
static char *_fetch_string(char **src, const int delimiter)
{
char *p, *ret;
@@ -553,12 +596,12 @@ static char *_fetch_string(char **src, const char delimiter)
/* Parse a device message from the daemon. */
static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
char **dev_name, enum dm_event_mask *evmask)
char **uuid, enum dm_event_mask *evmask)
{
char *p = msg->data;
if ((*dso_name = _fetch_string(&p, ' ')) &&
(*dev_name = _fetch_string(&p, ' '))) {
(*uuid = _fetch_string(&p, ' '))) {
*evmask = atoi(p);
return 0;
@@ -574,42 +617,80 @@ static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
* @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_mask *mask, 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 (!(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, *dso_name, *device_path, *mask, 0))) {
ret = !_parse_message(&msg, &dso_name_arg, &device_path_arg,
mask);
} 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;
&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 {
if (!(*dso_name))
*dso_name = dso_name_arg;
if (!(*device_path))
*device_path = device_path_arg;
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;
}
@@ -621,8 +702,9 @@ int dm_event_set_timeout(const char *device_path, uint32_t timeout)
if (!device_exists(device_path))
return -ENODEV;
return _do_event(DM_EVENT_CMD_SET_TIMEOUT, &msg,
NULL, device_path, 0, timeout);
NULL, device_path, 0, timeout);
}
int dm_event_get_timeout(const char *device_path, uint32_t *timeout)

View File

@@ -54,19 +54,24 @@ void dm_event_handler_destroy(struct dm_event_handler *dmevh);
/*
* Path of shared library to handle events.
*
* All of dso, device_name and uuid strings are duplicated, you do not
* need to keep the pointers valid after the call succeeds. Thes may
* return -ENOMEM though.
*/
void dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path);
int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path);
/*
* Identify the device to monitor by exactly one of
* dev_name, uuid or device number.
* Identify the device to monitor by exactly one of device_name, uuid or
* device number. String arguments are duplicated, see above.
*/
void dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *dev_name);
int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *device_name);
void dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid);
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);
void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout);
/*
* Specify mask for events to monitor.
@@ -79,11 +84,11 @@ 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);
int dm_event_handler_get_timeout(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 */
int dm_event_get_registered_device(char **dso_name, char **device_path,
enum dm_event_mask *evmask, int next);
/* 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.
@@ -93,9 +98,9 @@ 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_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);
void process_event(struct dm_task *dmt, enum dm_event_mask evmask, void **user);
int register_device(const char *device_name, const char *uuid, int major, int minor, void **user);
int unregister_device(const char *device_name, const char *uuid, int major,
int minor, void **user);
#endif

View File

@@ -151,7 +151,7 @@ static int _remove_failed_devices(const char *device)
}
/* FIXME Is any sanity-checking required on %s? */
if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --removemissing %s", vg)) {
if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --removemissing %s", vg)) {
/* this error should be caught above, but doesn't hurt to check again */
syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
@@ -164,7 +164,8 @@ static int _remove_failed_devices(const char *device)
return (r == 1) ? 0 : -1;
}
void process_event(struct dm_task *dmt, enum dm_event_mask event)
void process_event(struct dm_task *dmt, enum dm_event_mask event,
void **unused __attribute((unused)))
{
void *next = NULL;
uint64_t start, length;
@@ -221,7 +222,8 @@ void process_event(struct dm_task *dmt, enum dm_event_mask event)
pthread_mutex_unlock(&_event_mutex);
}
int register_device(const char *device, const char *uuid, int major, int minor)
int register_device(const char *device, const char *uuid, int major, int minor,
void **unused __attribute((unused)))
{
int r = 0;
@@ -257,7 +259,8 @@ out:
return r;
}
int unregister_device(const char *device, const char *uuid, int major, int minor)
int unregister_device(const char *device, const char *uuid, int major, int minor,
void **unused __attribute((unused)))
{
pthread_mutex_lock(&_register_mutex);

View File

@@ -151,7 +151,7 @@ static int _remove_failed_devices(const char *device)
}
/* FIXME Is any sanity-checking required on %s? */
if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --removemissing %s", vg)) {
if (CMD_SIZE <= snprintf(cmd_str, CMD_SIZE, "vgreduce --config devices{ignore_suspended_devices=1} --removemissing %s", vg)) {
/* this error should be caught above, but doesn't hurt to check again */
syslog(LOG_ERR, "Unable to form LVM command: Device name too long");
dm_pool_empty(_mem_pool); /* FIXME: not safe with multiple threads */
@@ -164,7 +164,8 @@ static int _remove_failed_devices(const char *device)
return (r == 1) ? 0 : -1;
}
void process_event(struct dm_task *dmt, enum dm_event_mask event)
void process_event(struct dm_task *dmt, enum dm_event_mask event,
void **unused __attribute((unused)))
{
void *next = NULL;
uint64_t start, length;
@@ -221,7 +222,8 @@ void process_event(struct dm_task *dmt, enum dm_event_mask event)
pthread_mutex_unlock(&_event_mutex);
}
int register_device(const char *device, const char *uuid, int major, int minor)
int register_device(const char *device, const char *uuid, int major, int minor,
void **unused __attribute((unused)))
{
int r = 0;
@@ -257,7 +259,8 @@ out:
return r;
}
int unregister_device(const char *device, const char *uuid, int major, int minor)
int unregister_device(const char *device, const char *uuid, int major, int minor,
void **unused __attribute((unused)))
{
pthread_mutex_lock(&_register_mutex);

View File

@@ -79,6 +79,12 @@ devices {
# software RAID (md) devices by looking for md superblocks.
# 1 enables; 0 disables.
md_component_detection = 1
# If, while scanning the system for PVs, LVM2 encounters a device-mapper
# device that has its I/O suspended, it waits for it to become accessible.
# Set this to 1 to skip such devices. This should only be needed
# in recovery situations.
ignore_suspended_devices = 0
}
# This section that allows you to configure the nature of the

View File

@@ -640,28 +640,27 @@ int lvs_in_vg_opened(struct volume_group *vg)
}
/*
* register_dev_for_events
*
* This function uses proper error codes (but breaks convention)
* to return:
* -1 on error
* 0 if the lv's targets don't do event [un]registration
* 0 if the lv is already [un]registered -- FIXME: not implemented
* 1 if the lv had a segment which was [un]registered
*
* Returns: -1 on error
* Returns 0 if an attempt to (un)monitor the device failed.
* Returns 1 otherwise.
*/
int register_dev_for_events(struct cmd_context *cmd,
struct logical_volume *lv, int do_reg)
int monitor_dev_for_events(struct cmd_context *cmd,
struct logical_volume *lv, int monitor)
{
#ifdef DMEVENTD
int i, pending = 0, registered;
int r = 0;
int i, pending = 0, monitored;
int r = 1;
struct list *tmp;
struct lv_segment *seg;
int (*reg) (struct cmd_context *c, struct lv_segment *s, int e);
int (*monitor_fn) (struct lv_segment *s, int e);
if (do_reg && !dmeventd_register_mode())
/* skip dmeventd code altogether */
if (dmeventd_monitor_mode() == DMEVENTD_MONITOR_IGNORE)
return 1;
/*
* Nothing to do if dmeventd configured not to be used.
*/
if (monitor && !dmeventd_monitor_mode())
return 1;
list_iterate(tmp, &lv->segments) {
@@ -669,57 +668,61 @@ int register_dev_for_events(struct cmd_context *cmd,
if (!seg_monitored(seg) || (seg->status & PVMOVE))
continue;
reg = NULL;
monitor_fn = NULL;
/* Check monitoring status */
if (seg->segtype->ops->target_registered)
registered = seg->segtype->ops->target_registered(seg, &pending);
if (seg->segtype->ops->target_monitored)
monitored = seg->segtype->ops->target_monitored(seg, &pending);
else
continue; /* segtype doesn't support registration */
/*
* FIXME: We should really try again if pending
*/
registered = (pending) ? 0 : registered;
monitored = (pending) ? 0 : monitored;
if (do_reg) {
if (registered)
if (monitor) {
if (monitored)
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 (seg->segtype->ops->target_monitor_events)
monitor_fn = seg->segtype->ops->target_monitor_events;
} else {
if (!registered)
if (!monitored)
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;
else if (seg->segtype->ops->target_unmonitor_events)
monitor_fn = seg->segtype->ops->target_unmonitor_events;
}
/* Do [un]monitor */
if (!reg)
if (!monitor_fn)
continue;
log_verbose("%sonitoring %s/%s", monitor ? "M" : "Not m", lv->vg->name, lv->name);
/* FIXME specify events */
if (!reg(cmd, seg, 0)) {
stack;
return -1;
if (!monitor_fn(seg, 0)) {
log_error("%s/%s: %s segment monitoring function failed.",
lv->vg->name, lv->name, seg->segtype->name);
return 0;
}
/* 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);
monitored = seg->segtype->ops->target_monitored(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");
(!monitored && monitor) ||
(monitored && !monitor))
log_very_verbose("%s/%s %smonitoring still pending: waiting...",
lv->vg->name, lv->name, monitor ? "" : "un");
else
break;
sleep(1);
}
r = (registered && do_reg) || (!registered && !do_reg);
r = (monitored && monitor) || (!monitored && !monitor);
}
return r;
@@ -764,7 +767,7 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s,
}
}
if (register_dev_for_events(cmd, lv, 0) < 0)
if (!monitor_dev_for_events(cmd, lv, 0))
/* FIXME Consider aborting here */
stack;
@@ -822,7 +825,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) < 0)
if (!monitor_dev_for_events(cmd, lv, 1))
stack;
return 1;
@@ -868,7 +871,7 @@ int lv_deactivate(struct cmd_context *cmd, const char *lvid_s)
return 0;
}
if (register_dev_for_events(cmd, lv, 0) < 0)
if (!monitor_dev_for_events(cmd, lv, 0))
stack;
memlock_inc();
@@ -941,7 +944,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) < 0)
if (!monitor_dev_for_events(cmd, lv, 1))
stack;
return r;

View File

@@ -86,7 +86,7 @@ int lvs_in_vg_activated(struct volume_group *vg);
int lvs_in_vg_opened(struct volume_group *vg);
int register_dev_for_events(struct cmd_context *cmd,
int monitor_dev_for_events(struct cmd_context *cmd,
struct logical_volume *lv, int do_reg);
/*
@@ -95,4 +95,9 @@ int register_dev_for_events(struct cmd_context *cmd,
int pv_uses_vg(struct physical_volume *pv,
struct volume_group *vg);
/*
* Returns 1 if mapped device is not suspended.
*/
int device_is_usable(dev_t dev);
#endif

View File

@@ -25,6 +25,7 @@
#include "targets.h"
#include "config.h"
#include "filter.h"
#include "activate.h"
#include <limits.h>
#include <dirent.h>
@@ -154,6 +155,58 @@ static int _info_run(const char *name, const char *dlid, struct dm_info *info,
return r;
}
int device_is_usable(dev_t dev)
{
struct dm_task *dmt;
struct dm_info info;
const char *name;
uint64_t start, length;
char *target_type = NULL;
char *params;
void *next = NULL;
int r = 0;
if (!(dmt = dm_task_create(DM_DEVICE_STATUS))) {
log_error("Failed to allocate dm_task struct to check dev status");
return 0;
}
if (!dm_task_set_major(dmt, MAJOR(dev)) || !dm_task_set_minor(dmt, MINOR(dev)))
goto_out;
if (!dm_task_run(dmt)) {
log_error("Failed to get state of mapped device");
goto out;
}
if (!dm_task_get_info(dmt, &info))
goto_out;
if (!info.exists || info.suspended)
goto out;
name = dm_task_get_name(dmt);
/* FIXME Also check for mirror block_on_error and mpath no paths */
/* For now, we exclude all mirrors */
do {
next = dm_get_next_target(dmt, next, &start, &length,
&target_type, &params);
/* Skip if target type doesn't match */
if (!strcmp(target_type, "mirror"))
goto out;
} while (next);
/* FIXME Also check dependencies? */
r = 1;
out:
dm_task_destroy(dmt);
return r;
}
static int _info(const char *name, const char *dlid, int mknodes,
int with_open_count, struct dm_info *info,
struct dm_pool *mem, char **uuid_out)

View File

@@ -59,8 +59,6 @@
# include <malloc.h>
#endif
static FILE *_log;
static int _get_env_vars(struct cmd_context *cmd)
{
const char *e;
@@ -575,7 +573,7 @@ static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
filters[0] : composite_filter_create(nr_filt, filters);
}
static int _init_filters(struct cmd_context *cmd)
static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
{
const char *dev_cache;
struct dev_filter *f3, *f4;
@@ -594,6 +592,9 @@ static int _init_filters(struct cmd_context *cmd)
return 0;
}
init_ignore_suspended_devices(find_config_tree_int(cmd,
"devices/ignore_suspended_devices", DEFAULT_IGNORE_SUSPENDED_DEVICES));
dev_cache = find_config_tree_str(cmd, "devices/cache",
cache_file);
if (!(f4 = persistent_filter_create(f3, dev_cache))) {
@@ -608,8 +609,13 @@ static int _init_filters(struct cmd_context *cmd)
if (!*cmd->sys_dir)
cmd->dump_filter = 0;
if (!stat(dev_cache, &st) &&
(st.st_ctime != config_file_timestamp(cmd->cft)) &&
/*
* Only load persistent filter device cache on startup if it is newer
* than the config file and this is not a long-lived process.
*/
if (load_persistent_cache && !cmd->is_long_lived &&
!stat(dev_cache, &st) &&
(st.st_ctime > config_file_timestamp(cmd->cft)) &&
!persistent_filter_load(f4, NULL))
log_verbose("Failed to load existing device cache from %s",
dev_cache);
@@ -881,7 +887,8 @@ static int _init_backup(struct cmd_context *cmd)
}
/* Entry point */
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static)
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static,
unsigned is_long_lived)
{
struct cmd_context *cmd;
@@ -905,6 +912,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static)
memset(cmd, 0, sizeof(*cmd));
cmd->args = the_args;
cmd->is_static = is_static;
cmd->is_long_lived = is_long_lived;
cmd->hosttags = 0;
list_init(&cmd->formats);
list_init(&cmd->segtypes);
@@ -953,7 +961,7 @@ struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static)
if (!_init_dev_cache(cmd))
goto error;
if (!_init_filters(cmd))
if (!_init_filters(cmd, 1))
goto error;
if (!(cmd->mem = dm_pool_create("command", 4 * 1024))) {
@@ -1022,10 +1030,10 @@ int refresh_toolcontext(struct cmd_context *cmd)
{
log_verbose("Reloading config files");
if (cmd->config_valid) {
if (cmd->dump_filter)
persistent_filter_dump(cmd->filter);
}
/*
* Don't update the persistent filter cache as we will
* perform a full rescan.
*/
activation_release();
lvmcache_destroy();
@@ -1064,7 +1072,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
if (!_init_dev_cache(cmd))
return 0;
if (!_init_filters(cmd))
if (!_init_filters(cmd, 0))
return 0;
if (!_init_formats(cmd))
@@ -1073,6 +1081,13 @@ int refresh_toolcontext(struct cmd_context *cmd)
if (!_init_segtypes(cmd))
return 0;
/*
* If we are a long-lived process, write out the updated persistent
* device cache for the benefit of short-lived processes.
*/
if (cmd->is_long_lived && cmd->dump_filter)
persistent_filter_dump(cmd->filter);
cmd->config_valid = 1;
return 1;
}
@@ -1100,8 +1115,4 @@ void destroy_toolcontext(struct cmd_context *cmd)
activation_exit();
fin_log();
fin_syslog();
if (_log)
fclose(_log);
}

View File

@@ -65,6 +65,7 @@ struct cmd_context {
struct arg *args;
char **argv;
unsigned is_static; /* Static binary? */
unsigned is_long_lived; /* Optimises persistent_filter handling */
struct dev_filter *filter;
int dump_filter; /* Dump filter when exiting? */
@@ -88,7 +89,7 @@ struct cmd_context {
char proc_dir[PATH_MAX];
};
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static);
struct cmd_context *create_toolcontext(struct arg *the_args, unsigned is_static, unsigned is_long_lived);
void destroy_toolcontext(struct cmd_context *cmd);
int refresh_toolcontext(struct cmd_context *cmd);
int config_files_changed(struct cmd_context *cmd);

View File

@@ -435,13 +435,13 @@ int write_config_file(struct config_tree *cft, const char *file,
log_verbose("Dumping configuration to %s", file);
if (!argc) {
if (!_write_config(cft->root, 0, fp, 0)) {
log_error("Failure while writing configuration");
log_error("Failure while writing to %s", file);
r = 0;
}
} else while (argc--) {
if ((cn = find_config_node(cft->root, *argv))) {
if (!_write_config(cn, 1, fp, 0)) {
log_error("Failure while writing configuration");
log_error("Failure while writing to %s", file);
r = 0;
}
} else {
@@ -451,8 +451,10 @@ int write_config_file(struct config_tree *cft, const char *file,
argv++;
}
if (fp != stdout)
fclose(fp);
if ((fp != stdout) && fclose(fp)) {
log_sys_error("fclose", file);
r = 0;
}
return r;
}
@@ -853,7 +855,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

@@ -30,6 +30,7 @@
#define DEFAULT_PROC_DIR "/proc"
#define DEFAULT_SYSFS_SCAN 1
#define DEFAULT_MD_COMPONENT_DETECTION 1
#define DEFAULT_IGNORE_SUSPENDED_DEVICES 1
#define DEFAULT_LOCK_DIR "/var/lock/lvm"
#define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so"

View File

@@ -292,11 +292,14 @@ int dev_get_sectsize(struct device *dev, uint32_t *size)
if (ioctl(fd, BLKSSZGET, &s) < 0) {
log_sys_error("ioctl BLKSSZGET", name);
close(fd);
if (close(fd))
log_sys_error("close", name);
return 0;
}
close(fd);
if (close(fd))
log_sys_error("close", name);
*size = (uint32_t) s;
log_very_verbose("%s: sector size is %" PRIu32 " bytes", name, *size);

View File

@@ -239,7 +239,10 @@ int persistent_filter_dump(struct dev_filter *f)
/* _write_array(pf, fp, "invalid_devices", PF_BAD_DEVICE); */
fprintf(fp, "}\n");
fclose(fp);
if (fclose(fp)) {
log_sys_error("fclose", tmp_file);
goto out;
}
if (rename(tmp_file, pf->file))
log_error("%s: rename to %s failed: %s", tmp_file, pf->file,

View File

@@ -54,7 +54,9 @@ static int _locate_sysfs_blocks(const char *proc, char *path, size_t len)
}
}
fclose(fp);
if (fclose(fp))
log_sys_error("fclose", proc_mounts);
return r;
}
@@ -156,7 +158,9 @@ static int _read_dev(const char *file, dev_t *result)
}
r = _parse_dev(file, fp, result);
fclose(fp);
if (fclose(fp))
log_sys_error("fclose", file);
return r;
}

View File

@@ -19,6 +19,7 @@
#include "lvm-string.h"
#include "config.h"
#include "metadata.h"
#include "activate.h"
#include <dirent.h>
#include <unistd.h>
@@ -37,6 +38,7 @@ typedef struct {
} device_info_t;
static int _md_major = -1;
static int _device_mapper_major = -1;
int md_major(void)
{
@@ -90,6 +92,13 @@ static int _passes_lvm_type_device_filter(struct dev_filter *f,
return 0;
}
/* Skip suspended devices */
if (MAJOR(dev->dev) == _device_mapper_major &&
ignore_suspended_devices() && !device_is_usable(dev->dev)) {
log_debug("%s: Skipping: Suspended dm device", name);
return 0;
}
/* Check it's accessible */
if (!dev_open_flags(dev, O_RDONLY, 0, 1)) {
log_debug("%s: Skipping: open failed", name);
@@ -182,10 +191,14 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
if (!strncmp("md", line + i, 2) && isspace(*(line + i + 2)))
_md_major = line_maj;
/* Look for device-mapper device */
/* FIXME Cope with multiple majors */
if (!strncmp("device-mapper", line + i, 13) && isspace(*(line + i + 13)))
_device_mapper_major = line_maj;
/* Go through the valid device names and if there is a
match store max number of partitions */
for (j = 0; device_info[j].name != NULL; j++) {
dev_len = strlen(device_info[j].name);
if (dev_len <= strlen(line + i) &&
!strncmp(device_info[j].name, line + i, dev_len) &&
@@ -204,7 +217,8 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
if (cv->type != CFG_STRING) {
log_error("Expecting string in devices/types "
"in config file");
fclose(pd);
if (fclose(pd))
log_sys_error("fclose", proc_devices);
return 0;
}
dev_len = strlen(cv->v.str);
@@ -214,14 +228,16 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
log_error("Max partition count missing for %s "
"in devices/types in config file",
name);
fclose(pd);
if (fclose(pd))
log_sys_error("fclose", proc_devices);
return 0;
}
if (!cv->v.i) {
log_error("Zero partition count invalid for "
"%s in devices/types in config file",
name);
fclose(pd);
if (fclose(pd))
log_sys_error("fclose", proc_devices);
return 0;
}
if (dev_len <= strlen(line + i) &&
@@ -232,7 +248,10 @@ static int _scan_proc_dev(const char *proc, const struct config_node *cn)
}
}
}
fclose(pd);
if (fclose(pd))
log_sys_error("fclose", proc_devices);
return 1;
}

View File

@@ -249,17 +249,23 @@ int archive_vg(struct volume_group *vg,
if (!(fp = fdopen(fd, "w"))) {
log_err("Couldn't create FILE object for archive.");
close(fd);
if (close(fd))
log_sys_error("close", temp_file);
return 0;
}
if (!text_vg_export_file(vg, desc, fp)) {
stack;
fclose(fp);
if (fclose(fp))
log_sys_error("fclose", temp_file);
return 0;
}
fclose(fp);
if (fclose(fp)) {
log_sys_error("fclose", temp_file);
/* Leave file behind as evidence of failure */
return 0;
}
/*
* Now we want to rename this file to <vg>_index.vg.

View File

@@ -710,7 +710,8 @@ static int _vg_write_file(struct format_instance *fid, struct volume_group *vg,
if (!(fp = fdopen(fd, "w"))) {
log_sys_error("fdopen", temp_file);
close(fd);
if (close(fd))
log_sys_error("fclose", temp_file);
return 0;
}
@@ -718,13 +719,15 @@ static int _vg_write_file(struct format_instance *fid, struct volume_group *vg,
if (!text_vg_export_file(vg, tc->desc, fp)) {
log_error("Failed to write metadata to %s.", temp_file);
fclose(fp);
if (fclose(fp))
log_sys_error("fclose", temp_file);
return 0;
}
if (fsync(fd) && (errno != EROFS) && (errno != EINVAL)) {
log_sys_error("fsync", tc->path_edit);
fclose(fp);
if (fclose(fp))
log_sys_error("fclose", tc->path_edit);
return 0;
}

View File

@@ -321,8 +321,8 @@ static int _lock_for_cluster(unsigned char cmd, unsigned int flags, char *name)
if (mirror_in_sync())
args[1] |= LCK_MIRROR_NOSYNC_MODE;
if (dmeventd_register_mode())
args[1] |= LCK_DMEVENTD_REGISTER_MODE;
if (dmeventd_monitor_mode())
args[1] |= LCK_DMEVENTD_MONITOR_MODE;
/*
* VG locks are just that: locks, and have no side effects

View File

@@ -163,8 +163,8 @@ static int _lock_file(const char *file, int flags)
log_very_verbose("Locking %s %c%c", ll->res, state,
flags & LCK_NONBLOCK ? ' ' : 'B');
do {
if (ll->lf > -1)
close(ll->lf);
if ((ll->lf > -1) && close(ll->lf))
log_sys_error("close", file);
if ((ll->lf = open(file, O_CREAT | O_APPEND | O_RDWR, 0777))
< 0) {

View File

@@ -75,7 +75,7 @@ int check_lvm1_vg_inactive(struct cmd_context *cmd, const char *vgname);
*/
#define LCK_PARTIAL_MODE 0x00000001 /* Running in partial mode */
#define LCK_MIRROR_NOSYNC_MODE 0x00000002 /* Mirrors don't require sync */
#define LCK_DMEVENTD_REGISTER_MODE 0x00000004 /* Register with dmeventd */
#define LCK_DMEVENTD_MONITOR_MODE 0x00000004 /* Register with dmeventd */
/*

View File

@@ -48,7 +48,8 @@ static char _cmd_name[30] = "";
static char _msg_prefix[30] = " ";
static int _already_logging = 0;
static int _mirror_in_sync = 0;
static int _dmeventd_register = DEFAULT_DMEVENTD_MONITOR;
static int _dmeventd_monitor = DEFAULT_DMEVENTD_MONITOR;
static int _ignore_suspended_devices = 0;
static lvm2_log_fn_t _lvm2_log_fn = NULL;
@@ -120,7 +121,8 @@ void fin_log(void)
}
if (_log_to_file) {
fclose(_log_file);
if (fclose(_log_file))
fprintf(stderr, "fclose() on log file failed: %s", strerror(errno));
_log_to_file = 0;
}
}
@@ -189,9 +191,14 @@ void init_mirror_in_sync(int in_sync)
_mirror_in_sync = in_sync;
}
void init_dmeventd_register(int reg)
void init_dmeventd_monitor(int reg)
{
_dmeventd_register = reg;
_dmeventd_monitor = reg;
}
void init_ignore_suspended_devices(int ignore)
{
_ignore_suspended_devices = ignore;
}
void init_cmd_name(int status)
@@ -268,9 +275,14 @@ int mirror_in_sync(void)
return _mirror_in_sync;
}
int dmeventd_register_mode(void)
int dmeventd_monitor_mode(void)
{
return _dmeventd_register;
return _dmeventd_monitor;
}
int ignore_suspended_devices(void)
{
return _ignore_suspended_devices;
}
void init_debug(int level)

View File

@@ -75,7 +75,8 @@ void init_ignorelockingfailure(int level);
void init_lockingfailed(int level);
void init_security_level(int level);
void init_mirror_in_sync(int in_sync);
void init_dmeventd_register(int reg);
void init_dmeventd_monitor(int reg);
void init_ignore_suspended_devices(int ignore);
void set_cmd_name(const char *cmd_name);
@@ -90,7 +91,10 @@ int ignorelockingfailure(void);
int lockingfailed(void);
int security_level(void);
int mirror_in_sync(void);
int dmeventd_register_mode(void);
int ignore_suspended_devices(void);
#define DMEVENTD_MONITOR_IGNORE -1
int dmeventd_monitor_mode(void);
/* Suppress messages to stdout/stderr (1) or everywhere (2) */
/* Returns previous setting */

View File

@@ -83,11 +83,9 @@ struct segtype_handler {
const struct lv_segment *seg,
struct list *modules);
void (*destroy) (const struct segment_type * segtype);
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);
int (*target_monitored) (struct lv_segment *seg, int *pending);
int (*target_monitor_events) (struct lv_segment *seg, int events);
int (*target_unmonitor_events) (struct lv_segment *seg, int events);
};
struct segment_type *get_segtype_from_string(struct cmd_context *cmd,

View File

@@ -368,7 +368,7 @@ static int _mirrored_target_present(const struct lv_segment *seg __attribute((un
}
#ifdef DMEVENTD
static int _setup_registration(struct cmd_context *cmd, char **dso)
static int _get_mirror_dso_path(struct cmd_context *cmd, char **dso)
{
char *path;
const char *libpath;
@@ -388,110 +388,105 @@ static int _setup_registration(struct cmd_context *cmd, char **dso)
return 1;
}
static int _target_registered(struct lv_segment *seg, int *pending)
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_monitored(struct lv_segment *seg, int *pending)
{
char *dso, *name;
struct logical_volume *lv;
struct volume_group *vg;
enum dm_event_mask evmask = 0;
struct dm_event_handler *dmevh;
lv = seg->lv;
vg = lv->vg;
*pending = 0;
if (!_setup_registration(vg->cmd, &dso)) {
stack;
return 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 (!dm_event_get_registered_device(&dso, &name, &evmask, 0))
return 0;
if (!(dmevh = _create_dm_event_handler(name, dso, DM_EVENT_ALL_ERRORS)))
return_0;
if (dm_event_get_registered_device(dmevh, 0)) {
dm_event_handler_destroy(dmevh);
return 0;
}
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. */
/* FIXME Merge these two functions */
static int _target_register_events(struct cmd_context *cmd,
struct lv_segment *seg,
int evmask)
static int _target_set_events(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 (!_setup_registration(cmd, &dso)) {
stack;
return 0;
}
if (!(name = build_dm_name(cmd->mem, vg->name, lv->name, NULL)))
if (!_get_mirror_dso_path(vg->cmd, &dso))
return_0;
if (!(dmevh = dm_event_handler_create()))
if (!(name = build_dm_name(vg->cmd->mem, vg->name, lv->name, NULL)))
return_0;
dm_event_handler_set_dso(dmevh, dso);
dm_event_handler_set_devname(dmevh, name);
dm_event_handler_set_event_mask(dmevh, DM_EVENT_ALL_ERRORS);
if (!dm_event_register_handler(dmevh)) {
dm_event_handler_destroy(dmevh);
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("Registered %s for events", name);
log_info("%s %s for events", set ? "Monitored" : "Unmonitored", name);
return 1;
}
static int _target_unregister_events(struct cmd_context *cmd,
struct lv_segment *seg,
int evmask)
static int _target_monitor_events(struct lv_segment *seg, int events)
{
char *dso;
char *name;
struct logical_volume *lv;
struct volume_group *vg;
struct dm_event_handler *dmevh;
return _target_set_events(seg, events, 1);
}
lv = seg->lv;
vg = lv->vg;
/* FIXME Remove this and use handle to avoid config file race */
if (!_setup_registration(cmd, &dso))
return_0;
if (!(name = build_dm_name(cmd->mem, vg->name, lv->name, NULL)))
return_0;
if (!(dmevh = dm_event_handler_create()))
return_0;
dm_event_handler_set_dso(dmevh, dso);
dm_event_handler_set_devname(dmevh, name);
dm_event_handler_set_event_mask(dmevh, DM_EVENT_ALL_ERRORS);
if (!dm_event_unregister_handler(dmevh)) {
dm_event_handler_destroy(dmevh);
return_0;
}
dm_event_handler_destroy(dmevh);
log_info("Unregistered %s for events", name);
return 1;
static int _target_unmonitor_events(struct lv_segment *seg, int events)
{
return _target_set_events(seg, events, 0);
}
#endif /* DMEVENTD */
@@ -535,9 +530,9 @@ 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,
.target_monitored = _target_monitored,
.target_monitor_events = _target_monitor_events,
.target_unmonitor_events = _target_unmonitor_events,
#endif
#endif
.modules_needed = _mirrored_modules_needed,

View File

@@ -66,7 +66,8 @@ int create_temp_name(const char *dir, char *buffer, size_t len, int *fd)
if (!fcntl(*fd, F_SETLK, &lock))
return 1;
close(*fd);
if (close(*fd))
log_sys_error("close", buffer);
}
return 0;
@@ -239,7 +240,8 @@ void sync_dir(const char *file)
if (fsync(fd) && (errno != EROFS) && (errno != EINVAL))
log_sys_error("fsync", dir);
close(fd);
if (close(fd))
log_sys_error("close", dir);
out:
dm_free(dir);

View File

@@ -18,67 +18,67 @@
* Display Fn, Unique format identifier */
/* *INDENT-OFF* */
FIELD(LVS, lv, STR, "LV UUID", lvid.id[1], 38, uuid, "lv_uuid")
FIELD(LVS, lv, STR, "LV", lvid, 4, lvname, "lv_name")
FIELD(LVS, lv, STR, "Attr", lvid, 4, lvstatus, "lv_attr")
FIELD(LVS, lv, NUM, "Maj", major, 3, int32, "lv_major")
FIELD(LVS, lv, NUM, "Min", minor, 3, int32, "lv_minor")
FIELD(LVS, lv, STR, "KMaj", lvid, 4, lvkmaj, "lv_kernel_major")
FIELD(LVS, lv, STR, "KMin", lvid, 4, lvkmin, "lv_kernel_minor")
FIELD(LVS, lv, NUM, "LSize", size, 5, size64, "lv_size")
FIELD(LVS, lv, NUM, "#Seg", lvid, 4, lvsegcount, "seg_count")
FIELD(LVS, lv, STR, "Origin", lvid, 6, origin, "origin")
FIELD(LVS, lv, NUM, "Snap%", lvid, 6, snpercent, "snap_percent")
FIELD(LVS, lv, NUM, "Copy%", lvid, 6, copypercent, "copy_percent")
FIELD(LVS, lv, STR, "Move", lvid, 4, movepv, "move_pv")
FIELD(LVS, lv, STR, "LV Tags", tags, 7, tags, "lv_tags")
FIELD(LVS, lv, STR, "Log", lvid, 3, loglv, "mirror_log")
FIELD(LVS, lv, STR, "Modules", lvid, 7, modules, "modules")
FIELD(LVS, lv, STR, "LV UUID", lvid.id[1], 38, uuid, "lv_uuid", "Unique identifier")
FIELD(LVS, lv, STR, "LV", lvid, 4, lvname, "lv_name", "Name. LVs created for internal use are enclosed in brackets.")
FIELD(LVS, lv, STR, "Attr", lvid, 4, lvstatus, "lv_attr", "Various attributes - see man page.")
FIELD(LVS, lv, NUM, "Maj", major, 3, int32, "lv_major", "Persistent major number or -1 if not persistent.")
FIELD(LVS, lv, NUM, "Min", minor, 3, int32, "lv_minor", "Persistent minor number or -1 if not persistent.")
FIELD(LVS, lv, STR, "KMaj", lvid, 4, lvkmaj, "lv_kernel_major", "Currently assigned major number or -1 if LV is not active.")
FIELD(LVS, lv, STR, "KMin", lvid, 4, lvkmin, "lv_kernel_minor", "Currently assigned minor number or -1 if LV is not active.")
FIELD(LVS, lv, NUM, "LSize", size, 5, size64, "lv_size", "Size of LV in current units.")
FIELD(LVS, lv, NUM, "#Seg", lvid, 4, lvsegcount, "seg_count", "Number of segments in LV.")
FIELD(LVS, lv, STR, "Origin", lvid, 6, origin, "origin", "For snapshots, the origin device of this LV")
FIELD(LVS, lv, NUM, "Snap%", lvid, 6, snpercent, "snap_percent", "For snapshots, the percentage full if LV is active.")
FIELD(LVS, lv, NUM, "Copy%", lvid, 6, copypercent, "copy_percent", "For mirrors and pvmove, current percentage in-sync.")
FIELD(LVS, lv, STR, "Move", lvid, 4, movepv, "move_pv", "For pvmove, Source PV of temporary LV created by pvmove")
FIELD(LVS, lv, STR, "LV Tags", tags, 7, tags, "lv_tags", "Tags, if any.")
FIELD(LVS, lv, STR, "Log", lvid, 3, loglv, "mirror_log", "For mirrors, the LV holding the synchronisation log.")
FIELD(LVS, lv, STR, "Modules", lvid, 7, modules, "modules", "Kernel device-mapper modules required for this LV.")
FIELD(PVS, pv, STR, "Fmt", id, 3, pvfmt, "pv_fmt")
FIELD(PVS, pv, STR, "PV UUID", id, 38, uuid, "pv_uuid")
FIELD(PVS, pv, NUM, "PSize", id, 5, pvsize, "pv_size")
FIELD(PVS, pv, NUM, "DevSize", dev, 7, devsize, "dev_size")
FIELD(PVS, pv, NUM, "1st PE", pe_start, 7, size64, "pe_start")
FIELD(PVS, pv, NUM, "PFree", id, 5, pvfree, "pv_free")
FIELD(PVS, pv, NUM, "Used", id, 4, pvused, "pv_used")
FIELD(PVS, pv, STR, "PV", dev, 10, dev_name, "pv_name")
FIELD(PVS, pv, STR, "Attr", status, 4, pvstatus, "pv_attr")
FIELD(PVS, pv, NUM, "PE", pe_count, 3, uint32, "pv_pe_count")
FIELD(PVS, pv, NUM, "Alloc", pe_alloc_count, 5, uint32, "pv_pe_alloc_count")
FIELD(PVS, pv, STR, "PV Tags", tags, 7, tags, "pv_tags")
FIELD(PVS, pv, STR, "Fmt", id, 3, pvfmt, "pv_fmt", "Type of metadata.")
FIELD(PVS, pv, STR, "PV UUID", id, 38, uuid, "pv_uuid", "Unique identifier.")
FIELD(PVS, pv, NUM, "PSize", id, 5, pvsize, "pv_size", "Size of PV in current units.")
FIELD(PVS, pv, NUM, "DevSize", dev, 7, devsize, "dev_size", "Size of underlying device in current units.")
FIELD(PVS, pv, NUM, "1st PE", pe_start, 7, size64, "pe_start", "Offset to the start of data on the underlying device.")
FIELD(PVS, pv, NUM, "PFree", id, 5, pvfree, "pv_free", "Total amount of unallocated space in current units.")
FIELD(PVS, pv, NUM, "Used", id, 4, pvused, "pv_used", "Total amount of allocated space in current units.")
FIELD(PVS, pv, STR, "PV", dev, 10, dev_name, "pv_name", "Name.")
FIELD(PVS, pv, STR, "Attr", status, 4, pvstatus, "pv_attr", "Various attributes - see man page.")
FIELD(PVS, pv, NUM, "PE", pe_count, 3, uint32, "pv_pe_count", "Total number of Physical Extents.")
FIELD(PVS, pv, NUM, "Alloc", pe_alloc_count, 5, uint32, "pv_pe_alloc_count", "Total number of allocated Physical Extents.")
FIELD(PVS, pv, STR, "PV Tags", tags, 7, tags, "pv_tags", "Tags, if any.")
FIELD(VGS, vg, STR, "Fmt", cmd, 3, vgfmt, "vg_fmt")
FIELD(VGS, vg, STR, "VG UUID", id, 38, uuid, "vg_uuid")
FIELD(VGS, vg, STR, "VG", name, 4, string, "vg_name")
FIELD(VGS, vg, STR, "Attr", cmd, 5, vgstatus, "vg_attr")
FIELD(VGS, vg, NUM, "VSize", cmd, 5, vgsize, "vg_size")
FIELD(VGS, vg, NUM, "VFree", cmd, 5, vgfree, "vg_free")
FIELD(VGS, vg, STR, "SYS ID", system_id, 6, string, "vg_sysid")
FIELD(VGS, vg, NUM, "Ext", extent_size, 3, size32, "vg_extent_size")
FIELD(VGS, vg, NUM, "#Ext", extent_count, 4, uint32, "vg_extent_count")
FIELD(VGS, vg, NUM, "Free", free_count, 4, uint32, "vg_free_count")
FIELD(VGS, vg, NUM, "MaxLV", max_lv, 5, uint32, "max_lv")
FIELD(VGS, vg, NUM, "MaxPV", max_pv, 5, uint32, "max_pv")
FIELD(VGS, vg, NUM, "#PV", pv_count, 3, uint32, "pv_count")
FIELD(VGS, vg, NUM, "#LV", lv_count, 3, uint32, "lv_count")
FIELD(VGS, vg, NUM, "#SN", snapshot_count, 3, uint32, "snap_count")
FIELD(VGS, vg, NUM, "Seq", seqno, 3, uint32, "vg_seqno")
FIELD(VGS, vg, STR, "VG Tags", tags, 7, tags, "vg_tags")
FIELD(VGS, vg, STR, "Fmt", cmd, 3, vgfmt, "vg_fmt", "Type of metadata.")
FIELD(VGS, vg, STR, "VG UUID", id, 38, uuid, "vg_uuid", "Unique identifier.")
FIELD(VGS, vg, STR, "VG", name, 4, string, "vg_name", "Name.")
FIELD(VGS, vg, STR, "Attr", cmd, 5, vgstatus, "vg_attr", "Various attributes - see man page.")
FIELD(VGS, vg, NUM, "VSize", cmd, 5, vgsize, "vg_size", "Total size of VG in current units.")
FIELD(VGS, vg, NUM, "VFree", cmd, 5, vgfree, "vg_free", "Total amount of free space in current units.")
FIELD(VGS, vg, STR, "SYS ID", system_id, 6, string, "vg_sysid", "System ID indicating when and where it was created.")
FIELD(VGS, vg, NUM, "Ext", extent_size, 3, size32, "vg_extent_size", "Size of Physical Extents in current units.")
FIELD(VGS, vg, NUM, "#Ext", extent_count, 4, uint32, "vg_extent_count", "Total number of Physical Extents.")
FIELD(VGS, vg, NUM, "Free", free_count, 4, uint32, "vg_free_count", "Total number of unallocated Physical Extents.")
FIELD(VGS, vg, NUM, "MaxLV", max_lv, 5, uint32, "max_lv", "Maximum number of LVs allowed in VG or 0 if unlimited.")
FIELD(VGS, vg, NUM, "MaxPV", max_pv, 5, uint32, "max_pv", "Maximum number of PVs allowed in VG or 0 if unlimited.")
FIELD(VGS, vg, NUM, "#PV", pv_count, 3, uint32, "pv_count", "Number of PVs.")
FIELD(VGS, vg, NUM, "#LV", lv_count, 3, uint32, "lv_count", "Number of LVs.")
FIELD(VGS, vg, NUM, "#SN", snapshot_count, 3, uint32, "snap_count", "Number of snapshots.")
FIELD(VGS, vg, NUM, "Seq", seqno, 3, uint32, "vg_seqno", "Revision number of internal metadata. Incremented whenever it changes.")
FIELD(VGS, vg, STR, "VG Tags", tags, 7, tags, "vg_tags", "Tags, if any.")
FIELD(SEGS, seg, STR, "Type", list, 4, segtype, "segtype")
FIELD(SEGS, seg, NUM, "#Str", area_count, 4, uint32, "stripes")
FIELD(SEGS, seg, NUM, "Stripe", stripe_size, 6, size32, "stripesize")
FIELD(SEGS, seg, NUM, "Stripe", stripe_size, 6, size32, "stripe_size")
FIELD(SEGS, seg, NUM, "Chunk", list, 5, chunksize, "chunksize")
FIELD(SEGS, seg, NUM, "Chunk", list, 5, chunksize, "chunk_size")
FIELD(SEGS, seg, NUM, "Region", region_size, 6, size32, "regionsize")
FIELD(SEGS, seg, NUM, "Region", region_size, 6, size32, "region_size")
FIELD(SEGS, seg, NUM, "Start", list, 5, segstart, "seg_start")
FIELD(SEGS, seg, NUM, "SSize", list, 5, segsize, "seg_size")
FIELD(SEGS, seg, STR, "Seg Tags", tags, 8, tags, "seg_tags")
FIELD(SEGS, seg, STR, "Devices", list, 5, devices, "devices")
FIELD(SEGS, seg, STR, "Type", list, 4, segtype, "segtype", "Type of LV segment")
FIELD(SEGS, seg, NUM, "#Str", area_count, 4, uint32, "stripes", "Number of stripes or mirror legs.")
FIELD(SEGS, seg, NUM, "Stripe", stripe_size, 6, size32, "stripesize", "For stripes, amount of data placed on one device before switching to the next.")
FIELD(SEGS, seg, NUM, "Stripe", stripe_size, 6, size32, "stripe_size", "For stripes, amount of data placed on one device before switching to the next.")
FIELD(SEGS, seg, NUM, "Region", region_size, 6, size32, "regionsize", "For mirrors, the unit of data copied when synchronising devices.")
FIELD(SEGS, seg, NUM, "Region", region_size, 6, size32, "region_size", "For mirrors, the unit of data copied when synchronising devices.")
FIELD(SEGS, seg, NUM, "Chunk", list, 5, chunksize, "chunksize", "For snapshots, the unit of data used when tracking changes.")
FIELD(SEGS, seg, NUM, "Chunk", list, 5, chunksize, "chunk_size", "For snapshots, the unit of data used when tracking changes.")
FIELD(SEGS, seg, NUM, "Start", list, 5, segstart, "seg_start", "Offset within the LV to the start of the segment in current units.")
FIELD(SEGS, seg, NUM, "SSize", list, 5, segsize, "seg_size", "Size of segment in current units.")
FIELD(SEGS, seg, STR, "Seg Tags", tags, 8, tags, "seg_tags", "Tags, if any.")
FIELD(SEGS, seg, STR, "Devices", list, 5, devices, "devices", "Underlying devices used with starting extent numbers.")
FIELD(PVSEGS, pvseg, NUM, "Start", pe, 5, uint32, "pvseg_start")
FIELD(PVSEGS, pvseg, NUM, "SSize", len, 5, uint32, "pvseg_size")
FIELD(PVSEGS, pvseg, NUM, "Start", pe, 5, uint32, "pvseg_start", "Physical Extent number of start of segment.")
FIELD(PVSEGS, pvseg, NUM, "SSize", len, 5, uint32, "pvseg_size", "Number of extents in segment.")
/* *INDENT-ON* */

File diff suppressed because it is too large Load Diff

View File

@@ -90,7 +90,7 @@ install_ioctl_static: ioctl/libdevmapper.a
.PHONY: distclean_lib distclean
distclean_lib:
$(RM) libdm-common.h libdevmapper.pc
$(RM) libdevmapper.pc
distclean: distclean_lib

View File

@@ -230,12 +230,14 @@ void dm_hash_wipe(struct dm_hash_table *t)
t->num_nodes = 0u;
}
char *dm_hash_get_key(struct dm_hash_table *t, struct dm_hash_node *n)
char *dm_hash_get_key(struct dm_hash_table *t __attribute((unused)),
struct dm_hash_node *n)
{
return n->key;
}
void *dm_hash_get_data(struct dm_hash_table *t, struct dm_hash_node *n)
void *dm_hash_get_data(struct dm_hash_table *t __attribute((unused)),
struct dm_hash_node *n)
{
return n->data;
}

View File

@@ -149,7 +149,8 @@ static int _get_proc_number(const char *file, const char *name,
if (!strcmp(name, nm)) {
if (number) {
*number = num;
fclose(fl);
if (fclose(fl))
log_error("%s: fclose failed: %s", file, strerror(errno));
return 1;
}
dm_bit_set(_dm_bitset, num);
@@ -158,7 +159,8 @@ static int _get_proc_number(const char *file, const char *name,
c = fgetc(fl);
} while (c != EOF && c != '\n');
}
fclose(fl);
if (fclose(fl))
log_error("%s: fclose failed: %s", file, strerror(errno));
if (number) {
log_error("%s: No entry for %s found", file, name);
@@ -1322,7 +1324,7 @@ static int _process_mapper_dir(struct dm_task *dmt)
dir = dm_dir();
if (!(d = opendir(dir))) {
fprintf(stderr, "opendir %s: %s", dir, strerror(errno));
log_error("opendir %s: %s", dir, strerror(errno));
return 0;
}
@@ -1335,9 +1337,8 @@ static int _process_mapper_dir(struct dm_task *dmt)
dm_task_run(dmt);
}
if (closedir(d)) {
fprintf(stderr, "closedir %s: %s", dir, strerror(errno));
}
if (closedir(d))
log_error("closedir %s: %s", dir, strerror(errno));
return r;
}

View File

@@ -646,11 +646,13 @@ struct dm_report_field;
/*
* dm_report_field_type flags
*/
#define DM_REPORT_FIELD_MASK 0x0000000F
#define DM_REPORT_FIELD_MASK 0x000000FF
#define DM_REPORT_FIELD_ALIGN_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
#define DM_REPORT_FIELD_TYPE_MASK 0x000000F0
#define DM_REPORT_FIELD_TYPE_STRING 0x00000010
#define DM_REPORT_FIELD_TYPE_NUMBER 0x00000020
struct dm_report;
struct dm_report_field_type {
@@ -663,12 +665,13 @@ struct dm_report_field_type {
int (*report_fn)(struct dm_report *rh, struct dm_pool *mem,
struct dm_report_field *field, const void *data,
void *private);
const char *desc; /* description of the field */
};
/*
* dm_report_init output_flags
*/
#define DM_REPORT_OUTPUT_MASK 0x00000007
#define DM_REPORT_OUTPUT_MASK 0x000000FF
#define DM_REPORT_OUTPUT_ALIGNED 0x00000001
#define DM_REPORT_OUTPUT_BUFFERED 0x00000002
#define DM_REPORT_OUTPUT_HEADINGS 0x00000004
@@ -685,26 +688,27 @@ 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);
/*
* Report functions are provided for simple data types.
* They take care of allocating copies of the data.
*/
int dm_report_field_string(struct dm_report *rh, struct dm_report_field *field,
const char **data);
int dm_report_field_int32(struct dm_report *rh, struct dm_report_field *field,
const int32_t *data);
int dm_report_field_uint32(struct dm_report *rh, struct dm_report_field *field,
const uint32_t *data);
int dm_report_field_int(struct dm_report *rh, struct dm_report_field *field,
const int *data);
int dm_report_field_uint64(struct dm_report *rh, struct dm_report_field *field,
const uint64_t *data);
/*
* Helper function for custom reporting functions
* For custom fields, allocate the data in 'mem' and use
* dm_report_field_set_value().
* 'sortvalue' may be NULL if it matches 'value'
*/
/*
* 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);
void dm_report_field_set_value(struct dm_report_field *field, const void *value,
const void *sortvalue);
#endif /* LIB_DEVICE_MAPPER_H */

View File

@@ -38,8 +38,8 @@ static int _verbose = 0;
* Library users can provide their own logging
* function.
*/
static void _default_log(int level, const char *file, int line,
const char *f, ...)
static void _default_log(int level, const char *file __attribute((unused)),
int line __attribute((unused)), const char *f, ...)
{
va_list ap;

View File

@@ -28,6 +28,4 @@ int rm_dev_node(const char *dev_name);
int rename_dev_node(const char *old_name, const char *new_name);
void update_devs(void);
#define DM_LIB_VERSION @DM_LIB_VERSION@
#endif

View File

@@ -1212,7 +1212,9 @@ static int _build_dev_string(char *devbuf, size_t bufsize, struct dm_tree_node *
return 1;
}
static int _emit_areas_line(struct dm_task *dmt, struct load_segment *seg, char *params, size_t paramsize, int *pos)
static int _emit_areas_line(struct dm_task *dmt __attribute((unused)),
struct load_segment *seg, char *params,
size_t paramsize, int *pos)
{
struct seg_area *area;
char devbuf[10];

View File

@@ -60,7 +60,7 @@ struct field_properties {
struct list list;
uint32_t field_num;
uint32_t sort_posn;
int width;
unsigned width;
const struct dm_report_object_type *type;
uint32_t flags;
};
@@ -99,12 +99,12 @@ static const struct dm_report_object_type *_find_type(struct dm_report *rh,
* 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)
int dm_report_field_string(struct dm_report *rh,
struct dm_report_field *field, const char **data)
{
char *repstr;
if (!(repstr = dm_pool_strdup(rh->mem, *(const char **) data))) {
if (!(repstr = dm_pool_strdup(rh->mem, *data))) {
log_error("dm_report_field_string: dm_pool_strdup failed");
return 0;
}
@@ -115,10 +115,10 @@ int dm_report_field_string(struct dm_report *rh, struct dm_pool *mem,
return 1;
}
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_int(struct dm_report *rh,
struct dm_report_field *field, const int *data)
{
const int value = *(const int *) data;
const int value = *data;
uint64_t *sortval;
char *repstr;
@@ -144,10 +144,10 @@ int dm_report_field_int(struct dm_report *rh, struct dm_pool *mem,
return 1;
}
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_uint32(struct dm_report *rh,
struct dm_report_field *field, const uint32_t *data)
{
const uint32_t value = *(const uint32_t *) data;
const uint32_t value = *data;
uint64_t *sortval;
char *repstr;
@@ -173,10 +173,10 @@ int dm_report_field_uint32(struct dm_report *rh, struct dm_pool *mem,
return 1;
}
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_int32(struct dm_report *rh,
struct dm_report_field *field, const int32_t *data)
{
const int32_t value = *(const int32_t *) data;
const int32_t value = *data;
uint64_t *sortval;
char *repstr;
@@ -202,10 +202,10 @@ int dm_report_field_int32(struct dm_report *rh, struct dm_pool *mem,
return 1;
}
int dm_report_field_uint64(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_report_field *field, const uint64_t *data)
{
const int value = *(const uint64_t *) data;
const int value = *data;
uint64_t *sortval;
char *repstr;
@@ -248,6 +248,11 @@ static void _display_fields(struct dm_report *rh)
uint32_t f;
const struct dm_report_object_type *type;
const char *desc, *last_desc = "";
size_t id_len = 0;
for (f = 0; rh->fields[f].report_fn; f++)
if (strlen(rh->fields[f].id) > id_len)
id_len = strlen(rh->fields[f].id);
for (f = 0; rh->fields[f].report_fn; f++) {
if ((type = _find_type(rh, rh->fields[f].type)) && type->desc)
@@ -258,9 +263,14 @@ static void _display_fields(struct dm_report *rh)
if (*last_desc)
log_print(" ");
log_print("%s Fields", desc);
log_print("%*.*s", (int) strlen(desc) + 7,
(int) strlen(desc) + 7,
"------------------------------------------");
}
log_print("- %s", rh->fields[f].id);
/* FIXME Add line-wrapping at terminal width (or 80 cols) */
log_print(" %-*s - %s", (int) id_len, rh->fields[f].id, rh->fields[f].desc);
last_desc = desc;
}
}
@@ -416,8 +426,9 @@ static int _parse_options(struct dm_report *rh, const char *format)
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);
if (strcasecmp(ws, "help") && strcmp(ws, "?"))
log_error("Unrecognised field: %.*s",
(int) (we - ws), ws);
return 0;
}
}
@@ -667,12 +678,12 @@ 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;
int32_t cnt = -1;
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) {
if (sfa->props->flags & DM_REPORT_FIELD_TYPE_NUMBER) {
const uint64_t numa =
*(const uint64_t *) sfa->sort_value;
const uint64_t numb =
@@ -686,7 +697,7 @@ static int _row_compare(const void *a, const void *b)
} else { /* FLD_DESCENDING */
return (numa < numb) ? 1 : -1;
}
} else { /* DM_REPORT_FIELD_STRING */
} else { /* DM_REPORT_FIELD_TYPE_STRING */
const char *stra = (const char *) sfa->sort_value;
const char *strb = (const char *) sfb->sort_value;
int cmp = strcmp(stra, strb);
@@ -739,7 +750,8 @@ int dm_report_output(struct dm_report *rh)
struct dm_report_field *field;
const char *repstr;
char buf[4096];
int width;
unsigned width;
uint32_t align;
if (list_empty(&rh->rows))
return 1;
@@ -755,8 +767,7 @@ int dm_report_output(struct dm_report *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");
log_error("dm_report: Unable to allocate output line");
return 0;
}
row = list_item(rowh, struct row);
@@ -769,30 +780,49 @@ int dm_report_output(struct dm_report *rh)
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;
strlen(repstr))) {
log_error("dm_report: Unable to extend output line");
goto bad;
}
} else {
if (!(align = field->props->flags & DM_REPORT_FIELD_ALIGN_MASK))
align = (field->props->flags & DM_REPORT_FIELD_TYPE_NUMBER) ?
DM_REPORT_FIELD_ALIGN_RIGHT : DM_REPORT_FIELD_ALIGN_LEFT;
if (align & DM_REPORT_FIELD_ALIGN_LEFT) {
if (dm_snprintf(buf, sizeof(buf), "%-*.*s",
width, width, repstr) < 0) {
log_error("dm_report: left-aligned snprintf() failed");
goto bad;
}
if (!dm_pool_grow_object(rh->mem, buf, width)) {
log_error("dm_report: Unable to extend output line");
goto bad;
}
} else if (align & DM_REPORT_FIELD_ALIGN_RIGHT) {
if (dm_snprintf(buf, sizeof(buf), "%*.*s",
width, width, repstr) < 0) {
log_error("dm_report: right-aligned snprintf() failed");
goto bad;
}
if (!dm_pool_grow_object(rh->mem, buf, width)) {
log_error("dm_report: Unable to extend output line");
goto bad;
}
}
}
if (!list_end(&row->fields, fh))
if (!dm_pool_grow_object(rh->mem, rh->separator,
strlen(rh->separator)))
goto bad_grow;
strlen(rh->separator))) {
log_error("dm_report: Unable to extend output line");
goto bad;
}
list_del(&field->list);
}
if (!dm_pool_grow_object(rh->mem, "\0", 1))
goto bad_grow;
if (!dm_pool_grow_object(rh->mem, "\0", 1)) {
log_error("dm_report: Unable to terminate output line");
goto bad;
}
log_print("%s", (char *) dm_pool_end_object(rh->mem));
list_del(&row->list);
}
@@ -802,10 +832,7 @@ int dm_report_output(struct dm_report *rh)
return 1;
bad_snprintf:
log_error("dm_report: snprintf row failed");
bad_grow:
log_error("dm_report: Failed to generate row for printing");
bad:
dm_pool_abandon_object(rh->mem);
return 0;
}

View File

@@ -37,7 +37,8 @@ static int _isword(int c)
* Split buffer into NULL-separated words in argv.
* Returns number of words.
*/
int dm_split_words(char *buffer, unsigned max, unsigned ignore_comments,
int dm_split_words(char *buffer, unsigned max,
unsigned ignore_comments __attribute((unused)),
char **argv)
{
unsigned arg;

View File

@@ -231,7 +231,8 @@ void dm_bounds_check_debug(void)
}
}
void *dm_malloc_aux(size_t s, const char *file, int line)
void *dm_malloc_aux(size_t s, const char *file __attribute((unused)),
int line __attribute((unused)))
{
if (s > 50000000) {
log_error("Huge memory allocation (size %" PRIsize_t

View File

@@ -35,11 +35,13 @@ lv_uuid, lv_name, lv_attr, lv_major, lv_minor, lv_kernel_major, lv_kernel_minor,
lv_size, seg_count, origin, snap_percent,
copy_percent, move_pv, lv_tags,
segtype, stripes,
stripesize, chunksize, seg_start, seg_size, seg_tags, devices.
stripesize, chunksize, seg_start, seg_size, seg_tags, devices,
regionsize, mirror_log, modules.
.IP
With \-\-segments, any "seg_" prefixes are optional; otherwise any "lv_"
prefixes are optional. Columns mentioned in \fBvgs (8)\fP
can also be chosen.
Use \fb-o help\fP to view the full list of fields available.
.IP
The lv_attr bits are:
.RS

View File

@@ -31,9 +31,16 @@ if processing the output.
Comma-separated ordered list of columns. Precede the list with '+' to append
to the default selection of columns. Column names are: pv_fmt, pv_uuid,
pv_size, dev_size, pv_free, pv_used, pv_name, pv_attr, pv_pe_count,
pv_pe_alloc_count, pv_tags.
The "pv_" prefix is optional. Columns mentioned in \fBvgs (8)\fP can also
pv_pe_alloc_count, pv_tags, pvseg_start, pvseg_size, pe_start.
With --segments, any "pvseg_" prefixes are optional; otherwise any
"pv_" prefixes are optional. Columns mentioned in \fBvgs (8)\fP can also
be chosen. The pv_attr bits are: (a)llocatable and e(x)ported.
Use \fb-o help\fP to view the full list of fields available.
.TP
.I \-\-segments
Produces one line of output for each contiguous allocation of space on each
Physical Volume, showing the start (pvseg_start) and length (pvseg_size) in
units of physical extents.
.TP
.I \-O, \-\-sort
Comma-separated ordered list of columns to sort by. Replaces the default

View File

@@ -10,6 +10,7 @@ vgchange \- change attributes of a volume group
.RB [ \-A | \-\-autobackup " {" y | n }]
.RB [ \-a | \-\-available " [e|l] {" y | n }]
.RB [ \-\-monitor " {" y | n }]
.RB [ \-c | \-\-clustered " {" y | n }]
.RB [ \-d | \-\-debug]
.RB [ \-\-deltag
.IR Tag ]
@@ -44,12 +45,12 @@ snapshots should be removed (see
.SH OPTIONS
See \fBlvm\fP for common options.
.TP
.BR \-A ", " \-\-autobackup { y | n }
.BR \-A ", " \-\-autobackup " " { y | n }
Controls automatic backup of metadata after the change. See
.B vgcfgbackup (8).
Default is yes.
.TP
.BR \-a ", " \-\-available [e|l] { y | n }
.BR \-a ", " \-\-available " " [e|l] { y | n }
Controls the availability of the logical volumes in the volume
group for input/output.
In other words, makes the logical volumes known/unknown to the kernel.
@@ -60,6 +61,14 @@ on the local node.
Logical volumes with single-host snapshots are always activated
exclusively because they can only be used on one node at once.
.TP
.BR \-c ", " \-\-clustered " " { y | n }
If clustered locking is enabled, this indicates whether this
Volume Group is shared with other nodes in the cluster or whether
it contains only local disks that are not visible on the other nodes.
If the cluster infrastructure is unavailable on a particular node at a
particular time, you may still be able to use Volume Groups that
are not marked as clustered.
.TP
.BR \-\-monitor " " { y | n }
Controls whether or not a mirrored logical volume is monitored by
dmeventd, if it is installed.
@@ -108,7 +117,7 @@ impact on I/O performance to the logical volume. The smallest PE is 1KB.
The 2.4 kernel has a limitation of 2TB per block device.
.TP
.BR \-x ", " \-\-resizeable { y | n }
.BR \-x ", " \-\-resizeable " " { y | n }
Enables or disables the extension/reduction of this volume group
with/by physical volumes.
.SH EXAMPLES

View File

@@ -8,6 +8,7 @@ vgcreate \- create a volume group
.RB [ \-\-alloc
.IR AllocationPolicy ]
.RB [ \-A | \-\-autobackup " {" y | n }]
.RB [ \-c | \-\-clustered " {" y | n }]
.RB [ \-d | \-\-debug ]
.RB [ \-h | \-\-help ]
.RB [ \-l | \-\-maxlogicalvolumes
@@ -33,6 +34,14 @@ previously configured for LVM with
.SH OPTIONS
See \fBlvm\fP for common options.
.TP
.BR \-c ", " \-\-clustered " " { y | n }
If clustered locking is enabled, this indicates whether this
Volume Group is shared with other nodes in the cluster or whether
it contains only local disks that are not visible on the other nodes.
If the cluster infrastructure is unavailable on a particular node at a
particular time, you may still be able to use Volume Groups that
are not marked as clustered.
.TP
.BR \-l ", " \-\-maxlogicalvolumes " " \fIMaxLogicalVolumes\fR
Sets the maximum number of logical volumes allowed in this
volume group.

View File

@@ -38,6 +38,7 @@ Any "vg_" prefixes are optional. Columns mentioned in either \fBpvs (8)\fP
or \fBlvs (8)\fP can also be chosen, but columns cannot be taken from both
at the same time. The vg_attr bits are: (w)riteable, (r)eadonly,
resi(z)eable, e(x)ported, (p)artial and (c)lustered.
Use \fb-o help\fP to view the full list of fields available.
.TP
.I \-O, \-\-sort
Comma-separated ordered list of columns to sort by. Replaces the default

View File

@@ -0,0 +1,98 @@
#!/bin/bash
#
# Copyright (C) 2007 Red Hat, Inc. All rights reserved.
#
# 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
#
# This file is part of LVM2.
# It is required for the proper handling of failures of LVM2 mirror
# devices that were created using the -m option of lvcreate.
#
#
# chkconfig: 12345 02 99
# description: Starts and stops dmeventd monitoring for lvm2
#
### BEGIN INIT INFO
# Provides:
### END INIT INFO
. /etc/init.d/functions
VGCHANGE="/usr/sbin/vgchange"
start()
{
for ret in 0
do
# TODO do we want to separate out already active groups only?
VGS=`vgs --noheadings -o name`
for vg in $VGS
do
if ! action "Starting monitoring for VG $vg:" $VGCHANGE --monitor y $vg
then
ret=$?
fi
done
done
return $ret
}
stop()
{
for ret in 0
do
# TODO do we want to separate out already active groups only?
VGS=`vgs --noheadings -o name`
for vg in $VGS
do
if ! action "Starting monitoring for VG $vg:" $VGCHANGE --monitor n $vg
then
ret=$?
fi
done
done
}
ret=1
# See how we were called.
case "$1" in
start)
start
ret=$?
;;
stop)
stop
ret=$?
;;
restart)
if stop
then
start
fi
ret=$?
;;
status)
# TODO anyone with an idea how to dump monitored volumes?
;;
*)
echo $"Usage: $0 {start|stop|restart|status}"
;;
esac
exit $ret

View File

@@ -657,7 +657,7 @@ xx(vgcreate,
"\t[-A|--autobackup {y|n}] " "\n"
"\t[--addtag Tag] " "\n"
"\t[--alloc AllocationPolicy] " "\n"
"\t[-c|--clustered] " "\n"
"\t[-c|--clustered {y|n}] " "\n"
"\t[-d|--debug]" "\n"
"\t[-h|--help]" "\n"
"\t[-l|--maxlogicalvolumes MaxLogicalVolumes]" "\n"

View File

@@ -1,7 +1,7 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
* Copyright (C) 2005 NEC Corperation
* Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
* Copyright (C) 2005-2007 NEC Corperation
*
* This file is part of the device-mapper userspace tools.
*
@@ -114,7 +114,9 @@ enum {
NOOPENCOUNT_ARG,
NOTABLE_ARG,
OPTIONS_ARG,
SEPARATOR_ARG,
SHOWKEYS_ARG,
SORT_ARG,
TABLE_ARG,
TARGET_ARG,
TREE_ARG,
@@ -126,18 +128,30 @@ enum {
};
static int _switches[NUM_SWITCHES];
static int _values[NUM_SWITCHES];
static int _int_args[NUM_SWITCHES];
static char *_string_args[NUM_SWITCHES];
static int _num_devices;
static char *_uuid;
static char *_fields;
static char *_table;
static char *_target;
static char *_command;
static struct dm_tree *_dtree;
static struct dm_report *_report;
/*
* Commands
*/
typedef int (*command_fn) (int argc, char **argv, void *data);
struct command {
const char *name;
const char *help;
int min_args;
int max_args;
command_fn fn;
};
static int _parse_line(struct dm_task *dmt, char *buffer, const char *file,
int line)
{
@@ -217,71 +231,33 @@ static int _parse_file(struct dm_task *dmt, const char *file)
#else
free(buffer);
#endif
if (file)
fclose(fp);
if (file && fclose(fp))
fprintf(stderr, "%s: fclose failed: %s", file, strerror(errno));
return r;
}
static void _display_info_cols_noheadings(struct dm_task *dmt,
struct dm_info *info)
struct dmsetup_report_obj {
struct dm_task *task;
struct dm_info *info;
};
static int _display_info_cols(struct dm_task *dmt, struct dm_info *info)
{
const char *uuid;
if (!info->exists)
return;
uuid = dm_task_get_uuid(dmt);
if (_switches[OPTIONS_ARG])
printf("%s\n", dm_task_get_name(dmt));
else
printf("%s:%d:%d:%s%s%s%s:%d:%d:%" PRIu32 ":%s\n",
dm_task_get_name(dmt),
info->major, info->minor,
info->live_table ? "L" : "-",
info->inactive_table ? "I" : "-",
info->suspended ? "s" : "-",
info->read_only ? "r" : "w",
info->open_count, info->target_count, info->event_nr,
uuid && *uuid ? uuid : "");
}
static void _display_info_cols(struct dm_task *dmt, struct dm_info *info)
{
static int _headings = 0;
const char *uuid;
struct dmsetup_report_obj obj;
if (!info->exists) {
printf("Device does not exist.\n");
return;
fprintf(stderr, "Device does not exist.\n");
return 0;
}
if (!_headings) {
if (_switches[OPTIONS_ARG])
printf("Name\n");
else
printf("Name Maj Min Stat Open Targ "
"Event UUID\n");
_headings = 1;
}
obj.task = dmt;
obj.info = info;
if (_switches[OPTIONS_ARG])
printf("%s\n", dm_task_get_name(dmt));
else {
printf("%-16s %3d %3d %s%s%s%s %4d %4d %6" PRIu32 " ",
dm_task_get_name(dmt),
info->major, info->minor,
info->live_table ? "L" : "-",
info->inactive_table ? "I" : "-",
info->suspended ? "s" : "-",
info->read_only ? "r" : "w",
info->open_count, info->target_count, info->event_nr);
if (!dm_report_object(_report, &obj))
return 0;
if ((uuid = dm_task_get_uuid(dmt)) && *uuid)
printf("%s", uuid);
printf("\n");
}
return 1;
}
static void _display_info_long(struct dm_task *dmt, struct dm_info *info)
@@ -331,9 +307,8 @@ static int _display_info(struct dm_task *dmt)
if (!_switches[COLS_ARG])
_display_info_long(dmt, &info);
else if (_switches[NOHEADINGS_ARG])
_display_info_cols_noheadings(dmt, &info);
else
/* FIXME return code */
_display_info_cols(dmt, &info);
return info.exists ? 1 : 0;
@@ -348,8 +323,8 @@ static int _set_task_device(struct dm_task *dmt, const char *name, int optional)
if (!dm_task_set_uuid(dmt, _uuid))
return 0;
} else if (_switches[MAJOR_ARG] && _switches[MINOR_ARG]) {
if (!dm_task_set_major(dmt, _values[MAJOR_ARG]) ||
!dm_task_set_minor(dmt, _values[MINOR_ARG]))
if (!dm_task_set_major(dmt, _int_args[MAJOR_ARG]) ||
!dm_task_set_minor(dmt, _int_args[MINOR_ARG]))
return 0;
} else if (!optional) {
fprintf(stderr, "No device specified.\n");
@@ -440,19 +415,19 @@ static int _create(int argc, char **argv, void *data __attribute((unused)))
if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
goto out;
if (_switches[MAJOR_ARG] && !dm_task_set_major(dmt, _values[MAJOR_ARG]))
if (_switches[MAJOR_ARG] && !dm_task_set_major(dmt, _int_args[MAJOR_ARG]))
goto out;
if (_switches[MINOR_ARG] && !dm_task_set_minor(dmt, _values[MINOR_ARG]))
if (_switches[MINOR_ARG] && !dm_task_set_minor(dmt, _int_args[MINOR_ARG]))
goto out;
if (_switches[UID_ARG] && !dm_task_set_uid(dmt, _values[UID_ARG]))
if (_switches[UID_ARG] && !dm_task_set_uid(dmt, _int_args[UID_ARG]))
goto out;
if (_switches[GID_ARG] && !dm_task_set_gid(dmt, _values[GID_ARG]))
if (_switches[GID_ARG] && !dm_task_set_gid(dmt, _int_args[GID_ARG]))
goto out;
if (_switches[MODE_ARG] && !dm_task_set_mode(dmt, _values[MODE_ARG]))
if (_switches[MODE_ARG] && !dm_task_set_mode(dmt, _int_args[MODE_ARG]))
goto out;
if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
@@ -1496,6 +1471,194 @@ static int _tree(int argc, char **argv, void *data __attribute((unused)))
return 1;
}
/*
* Report device information
*/
/* dm specific display functions */
static int _int32_disp(struct dm_report *rh,
struct dm_pool *mem __attribute((unused)),
struct dm_report_field *field, const void *data,
void *private __attribute((unused)))
{
const int32_t value = *(const int32_t *)data;
return dm_report_field_int32(rh, field, &value);
}
static int _uint32_disp(struct dm_report *rh,
struct dm_pool *mem __attribute((unused)),
struct dm_report_field *field, const void *data,
void *private __attribute((unused)))
{
const uint32_t value = *(const int32_t *)data;
return dm_report_field_uint32(rh, field, &value);
}
static int _dm_name_disp(struct dm_report *rh,
struct dm_pool *mem __attribute((unused)),
struct dm_report_field *field, const void *data,
void *private __attribute((unused)))
{
const char *name = dm_task_get_name((struct dm_task *) data);
return dm_report_field_string(rh, field, &name);
}
static int _dm_uuid_disp(struct dm_report *rh,
struct dm_pool *mem __attribute((unused)),
struct dm_report_field *field,
const void *data, void *private __attribute((unused)))
{
const char *uuid = dm_task_get_uuid((struct dm_task *) data);
if (!uuid || !*uuid)
uuid = "";
return dm_report_field_string(rh, field, &uuid);
}
static int _dm_info_status_disp(struct dm_report *rh,
struct dm_pool *mem __attribute((unused)),
struct dm_report_field *field, const void *data,
void *private __attribute((unused)))
{
char buf[5];
const char *s = buf;
struct dm_info *info = (struct dm_info *) data;
buf[0] = info->live_table ? 'L' : '-';
buf[1] = info->inactive_table ? 'I' : '-';
buf[2] = info->suspended ? 's' : '-';
buf[3] = info->read_only ? 'r' : 'w';
buf[4] = '\0';
return dm_report_field_string(rh, field, &s);
}
/* Report types */
enum { DR_TASK = 1, DR_INFO = 2 };
static void *_task_get_obj(void *obj)
{
return ((struct dmsetup_report_obj *)obj)->task;
}
static void *_info_get_obj(void *obj)
{
return ((struct dmsetup_report_obj *)obj)->info;
}
static const struct dm_report_object_type _report_types[] = {
{ DR_TASK, "Mapped Device Name", "", _task_get_obj },
{ DR_INFO, "Mapped Device Information", "", _info_get_obj },
{ 0, "", "", NULL },
};
/* Column definitions */
#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},
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},
/* *INDENT-ON* */
};
#undef STR
#undef NUM
#undef FIELD_O
#undef FIELD_F
static const char *default_report_options = "name,major,minor,status,open_count,target_count,event_nr,uuid";
static int _report_init(struct command *c)
{
char *options = (char *) default_report_options;
const char *keys = "";
const char *separator = " ";
int aligned = 1, headings = 1, buffered = 0;
uint32_t report_type = 0;
uint32_t flags = 0;
size_t len = 0;
int r = 0;
/* emulate old dmsetup behaviour */
if (_switches[NOHEADINGS_ARG]) {
separator = ":";
aligned = 0;
headings = 0;
}
if (_switches[OPTIONS_ARG] && _string_args[OPTIONS_ARG]) {
if (*_string_args[OPTIONS_ARG] != '+')
options = _string_args[OPTIONS_ARG];
else {
len = strlen(default_report_options) +
strlen(_string_args[OPTIONS_ARG]) + 1;
if (!(options = dm_malloc(len))) {
err("Failed to allocate option string.");
return 0;
}
if (dm_snprintf(options, len, "%s,%s",
default_report_options,
&_string_args[OPTIONS_ARG][1]) < 0) {
err("snprintf failed");
goto out;
}
}
}
if (_switches[SORT_ARG] && _string_args[SORT_ARG]) {
keys = _string_args[SORT_ARG];
buffered = 1;
if (!strcmp(c->name, "status") || !strcmp(c->name, "table")) {
err("--sort is not yet supported with status and table");
goto out;
}
}
if (_switches[SEPARATOR_ARG] && _string_args[SEPARATOR_ARG]) {
separator = _string_args[SEPARATOR_ARG];
aligned = 0;
}
if (aligned)
flags |= DM_REPORT_OUTPUT_ALIGNED;
if (buffered)
flags |= DM_REPORT_OUTPUT_BUFFERED;
if (headings)
flags |= DM_REPORT_OUTPUT_HEADINGS;
if (!(_report = dm_report_init(&report_type,
_report_types, _report_fields,
options, separator, flags, keys, NULL)))
goto out;
r = 1;
out:
if (len)
dm_free(options);
return r;
}
/*
* List devices
*/
@@ -1511,18 +1674,8 @@ static int _ls(int argc, char **argv, void *data)
}
/*
* dispatch table
* Dispatch table
*/
typedef int (*command_fn) (int argc, char **argv, void *data);
struct command {
const char *name;
const char *help;
int min_args;
int max_args;
command_fn fn;
};
static struct command _commands[] = {
{"create", "<dev_name> [-j|--major <major> -m|--minor <minor>]\n"
"\t [-U|--uid <uid>] [-G|--gid <gid>] [-M|--mode <octal_mode>]\n"
@@ -1673,7 +1826,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] == '/') {
@@ -1703,7 +1856,8 @@ error:
/*
* create a table for a mapped device using the loop target.
*/
static int _loop_table(char *table, size_t tlen, char *file, char *dev, off_t off)
static int _loop_table(char *table, size_t tlen, char *file,
char *dev __attribute((unused)), off_t off)
{
struct stat fbuf;
off_t size, sectors;
@@ -1736,7 +1890,7 @@ static int _loop_table(char *table, size_t tlen, char *file, char *dev, off_t of
#ifdef HAVE_SYS_STATVFS_H
if (fstatvfs(fd, &fsbuf))
goto error;
goto error;
/* FIXME Fragment size currently unused */
blksize = fsbuf.f_frsize;
@@ -1744,7 +1898,7 @@ static int _loop_table(char *table, size_t tlen, char *file, char *dev, off_t of
close(fd);
if (dm_snprintf(table, tlen, "%llu %llu loop %s %llu\n", 0ULL,
if (dm_snprintf(table, tlen, "%llu %llu loop %s %llu\n", 0ULL,
(long long unsigned)sectors, file, off) < 0)
return 0;
@@ -1888,7 +2042,9 @@ static int _process_switches(int *argc, char ***argv)
{"noopencount", 0, &ind, NOOPENCOUNT_ARG},
{"notable", 0, &ind, NOTABLE_ARG},
{"options", 1, &ind, OPTIONS_ARG},
{"separator", 1, &ind, SEPARATOR_ARG},
{"showkeys", 0, &ind, SHOWKEYS_ARG},
{"sort", 1, &ind, SORT_ARG},
{"table", 1, &ind, TABLE_ARG},
{"target", 1, &ind, TARGET_ARG},
{"tree", 0, &ind, TREE_ARG},
@@ -1906,7 +2062,7 @@ static int _process_switches(int *argc, char ***argv)
* Zero all the index counts.
*/
memset(&_switches, 0, sizeof(_switches));
memset(&_values, 0, sizeof(_values));
memset(&_int_args, 0, sizeof(_int_args));
namebase = strdup((*argv)[0]);
base = basename(namebase);
@@ -1918,17 +2074,17 @@ static int _process_switches(int *argc, char ***argv)
_switches[OPTIONS_ARG]++;
_switches[MAJOR_ARG]++;
_switches[MINOR_ARG]++;
_fields = (char *) "name";
_string_args[OPTIONS_ARG] = (char *) "name";
if (*argc == 3) {
_values[MAJOR_ARG] = atoi((*argv)[1]);
_values[MINOR_ARG] = atoi((*argv)[2]);
_int_args[MAJOR_ARG] = atoi((*argv)[1]);
_int_args[MINOR_ARG] = atoi((*argv)[2]);
*argc -= 2;
*argv += 2;
} else if ((*argc == 2) &&
(2 == sscanf((*argv)[1], "%i:%i",
&_values[MAJOR_ARG],
&_values[MINOR_ARG]))) {
&_int_args[MAJOR_ARG],
&_int_args[MINOR_ARG]))) {
*argc -= 1;
*argv += 1;
} else {
@@ -1950,7 +2106,7 @@ static int _process_switches(int *argc, char ***argv)
optarg = 0;
optind = OPTIND_INIT;
while ((ind = -1, c = GETOPTLONG_FN(*argc, *argv, "cCfGj:m:Mno:ru:Uv",
while ((ind = -1, c = GETOPTLONG_FN(*argc, *argv, "cCfGj:m:Mno:O:ru:Uv",
long_options, NULL)) != -1) {
if (c == ':' || c == '?')
return 0;
@@ -1962,17 +2118,25 @@ static int _process_switches(int *argc, char ***argv)
_switches[READ_ONLY]++;
if (c == 'j' || ind == MAJOR_ARG) {
_switches[MAJOR_ARG]++;
_values[MAJOR_ARG] = atoi(optarg);
_int_args[MAJOR_ARG] = atoi(optarg);
}
if (c == 'm' || ind == MINOR_ARG) {
_switches[MINOR_ARG]++;
_values[MINOR_ARG] = atoi(optarg);
_int_args[MINOR_ARG] = atoi(optarg);
}
if (c == 'n' || ind == NOTABLE_ARG)
_switches[NOTABLE_ARG]++;
if (c == 'o' || ind == OPTIONS_ARG) {
_switches[OPTIONS_ARG]++;
_fields = optarg;
_string_args[OPTIONS_ARG] = optarg;
}
if (ind == SEPARATOR_ARG) {
_switches[SEPARATOR_ARG]++;
_string_args[SEPARATOR_ARG] = optarg;
}
if (c == 'O' || ind == SORT_ARG) {
_switches[SORT_ARG]++;
_string_args[SORT_ARG] = optarg;
}
if (c == 'v' || ind == VERBOSE_ARG)
_switches[VERBOSE_ARG]++;
@@ -1982,16 +2146,16 @@ static int _process_switches(int *argc, char ***argv)
}
if (c == 'G' || ind == GID_ARG) {
_switches[GID_ARG]++;
_values[GID_ARG] = atoi(optarg);
_int_args[GID_ARG] = atoi(optarg);
}
if (c == 'U' || ind == UID_ARG) {
_switches[UID_ARG]++;
_values[UID_ARG] = atoi(optarg);
_int_args[UID_ARG] = atoi(optarg);
}
if (c == 'M' || ind == MODE_ARG) {
_switches[MODE_ARG]++;
/* FIXME Accept modes as per chmod */
_values[MODE_ARG] = (int) strtol(optarg, NULL, 8);
_int_args[MODE_ARG] = (int) strtol(optarg, NULL, 8);
}
if ((ind == EXEC_ARG)) {
_switches[EXEC_ARG]++;
@@ -2031,13 +2195,7 @@ static int _process_switches(int *argc, char ***argv)
return 0;
}
if (_switches[COLS_ARG] && _switches[OPTIONS_ARG] &&
strcmp(_fields, "name")) {
fprintf(stderr, "Only -o name is supported so far.\n");
return 0;
}
if (_switches[TREE_ARG] && !_process_tree_options(_fields))
if (_switches[TREE_ARG] && !_process_tree_options(_string_args[OPTIONS_ARG]))
return 0;
if (_switches[TABLE_ARG] && _switches[NOTABLE_ARG]) {
@@ -2085,6 +2243,9 @@ int main(int argc, char **argv)
goto out;
}
if (_switches[COLS_ARG] && !_report_init(c))
goto out;
doit:
if (!c->fn(argc, argv, NULL)) {
fprintf(stderr, "Command failed\n");
@@ -2094,5 +2255,10 @@ int main(int argc, char **argv)
r = 0;
out:
if (_report) {
dm_report_output(_report);
dm_report_free(_report);
}
return r;
}

View File

@@ -80,10 +80,9 @@ static int lvchange_permission(struct cmd_context *cmd,
return 1;
}
static int lvchange_registration(struct cmd_context *cmd,
struct logical_volume *lv)
static int lvchange_monitoring(struct cmd_context *cmd,
struct logical_volume *lv)
{
int r;
struct lvinfo info;
if (!lv_info(cmd, lv, &info, 0) || !info.exists) {
@@ -91,27 +90,15 @@ static int lvchange_registration(struct cmd_context *cmd,
return 0;
}
/* do not register pvmove lv's */
/* do not monitor pvmove lv's */
if (lv->status & PVMOVE)
return 1;
log_verbose("%smonitoring logical volume \"%s\"",
(dmeventd_register_mode()) ? "" : "Not ", lv->name);
r = register_dev_for_events(cmd, lv, dmeventd_register_mode());
if ((dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) &&
!monitor_dev_for_events(cmd, lv, dmeventd_monitor_mode()))
stack;
if (r < 0) {
log_error("Unable to %smonitor logical volume, %s",
(dmeventd_register_mode()) ? "" : "un", lv->name);
r = 0;
} else if (!r) {
log_verbose("Logical volume %s needs no %smonitoring, or is already %smonitored",
(dmeventd_register_mode()) ? "" : "un",
lv->name,
(dmeventd_register_mode()) ? "" : "un");
r = 1;
}
return r;
return 1;
}
static int lvchange_availability(struct cmd_context *cmd,
@@ -605,7 +592,9 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
return ECMD_FAILED;
}
init_dmeventd_register(arg_int_value(cmd, monitor_ARG, DEFAULT_DMEVENTD_MONITOR));
init_dmeventd_monitor(arg_int_value(cmd, monitor_ARG,
cmd->is_static ?
DMEVENTD_MONITOR_IGNORE : DEFAULT_DMEVENTD_MONITOR));
/* access permission change */
if (arg_count(cmd, permission_ARG)) {
@@ -675,7 +664,7 @@ static int lvchange_single(struct cmd_context *cmd, struct logical_volume *lv,
if (!arg_count(cmd, available_ARG) &&
!arg_count(cmd, refresh_ARG) &&
arg_count(cmd, monitor_ARG)) {
if (!lvchange_registration(cmd, lv))
if (!lvchange_monitoring(cmd, lv))
return ECMD_FAILED;
}

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

@@ -1030,7 +1030,7 @@ struct cmd_context *init_lvm(unsigned is_static)
{
struct cmd_context *cmd;
if (!(cmd = create_toolcontext(&the_args[0], is_static))) {
if (!(cmd = create_toolcontext(&the_args[0], is_static, 0))) {
stack;
return NULL;
}
@@ -1065,8 +1065,9 @@ static int _run_script(struct cmd_context *cmd, int argc, char **argv)
char buffer[CMD_LEN];
int ret = 0;
int magic_number = 0;
char *script_file = argv[0];
if ((script = fopen(argv[0], "r")) == NULL)
if ((script = fopen(script_file, "r")) == NULL)
return ENO_SUCH_CMD;
while (fgets(buffer, sizeof(buffer), script) != NULL) {
@@ -1099,7 +1100,9 @@ static int _run_script(struct cmd_context *cmd, int argc, char **argv)
lvm_run_command(cmd, argc, argv);
}
fclose(script);
if (fclose(script))
log_sys_error("fclose", script_file);
return ret;
}

View File

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

@@ -15,7 +15,7 @@
#include "tools.h"
static int _register_lvs_in_vg(struct cmd_context *cmd,
static int _monitor_lvs_in_vg(struct cmd_context *cmd,
struct volume_group *vg, int reg)
{
struct lv_list *lvl;
@@ -23,7 +23,6 @@ static int _register_lvs_in_vg(struct cmd_context *cmd,
struct lvinfo info;
int lv_active;
int count = 0;
int r;
list_iterate_items(lvl, &vg->lvs) {
lv = lvl->lv;
@@ -39,16 +38,9 @@ static int _register_lvs_in_vg(struct cmd_context *cmd,
if ((lv->status & PVMOVE) || !lv_active)
continue;
r = register_dev_for_events(cmd, lv, reg);
if (r < 0) {
log_error("Failed to %s logical volume, %s",
(reg) ? "register" : "unregister",
lv->name);
if (!monitor_dev_for_events(cmd, lv, reg)) {
continue;
}
if (r)
} else
count++;
}
@@ -113,11 +105,12 @@ static int _vgchange_monitoring(struct cmd_context *cmd, struct volume_group *vg
{
int active, monitored;
if ((active = lvs_in_vg_activated(vg))) {
monitored = _register_lvs_in_vg(cmd, vg, dmeventd_register_mode());
if ((active = lvs_in_vg_activated(vg)) &&
dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) {
monitored = _monitor_lvs_in_vg(cmd, vg, dmeventd_monitor_mode());
log_print("%d logical volume(s) in volume group "
"\"%s\" %smonitored",
monitored, vg->name, (dmeventd_register_mode()) ? "" : "un");
monitored, vg->name, (dmeventd_monitor_mode()) ? "" : "un");
}
return ECMD_PROCESSED;
@@ -154,11 +147,13 @@ static int _vgchange_available(struct cmd_context *cmd, struct volume_group *vg)
if (activate && (active = lvs_in_vg_activated(vg))) {
log_verbose("%d logical volume(s) in volume group \"%s\" "
"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\" %smonitored",
monitored, vg->name,
dmeventd_register_mode() ? "" : "un");
if (dmeventd_monitor_mode() != DMEVENTD_MONITOR_IGNORE) {
monitored = _monitor_lvs_in_vg(cmd, vg, dmeventd_monitor_mode());
log_verbose("%d existing logical volume(s) in volume "
"group \"%s\" %smonitored",
monitored, vg->name,
dmeventd_monitor_mode() ? "" : "un");
}
}
if (activate && _activate_lvs_in_vg(cmd, vg, available))
@@ -540,7 +535,9 @@ static int vgchange_single(struct cmd_context *cmd, const char *vg_name,
return ECMD_FAILED;
}
init_dmeventd_register(arg_int_value(cmd, monitor_ARG, DEFAULT_DMEVENTD_MONITOR));
init_dmeventd_monitor(arg_int_value(cmd, monitor_ARG,
cmd->is_static ?
DMEVENTD_MONITOR_IGNORE : DEFAULT_DMEVENTD_MONITOR));
if (arg_count(cmd, available_ARG))
r = _vgchange_available(cmd, vg);