diff --git a/WHATS_NEW b/WHATS_NEW index be3d93cf2..db7f9fc41 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.11 - ===================================== + Capture error messages in clvmd and pass them back to the user. Remove unused #defines from filter-md.c. Make clvmd restart init script wait until clvmd has died before starting it. Add -R to clvmd which tells running clvmds to reload their device cache. diff --git a/daemons/clvmd/clvmd-command.c b/daemons/clvmd/clvmd-command.c index 53ca4a2ad..9ba6e49b4 100644 --- a/daemons/clvmd/clvmd-command.c +++ b/daemons/clvmd/clvmd-command.c @@ -117,7 +117,7 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen, if (status == EIO) { *retlen = 1 + snprintf(*buf, buflen, - "Internal lvm error, check syslog"); + get_last_lvm_error()); return EIO; } break; diff --git a/daemons/clvmd/clvmd.c b/daemons/clvmd/clvmd.c index df13ef897..a8e037aa8 100644 --- a/daemons/clvmd/clvmd.c +++ b/daemons/clvmd/clvmd.c @@ -1689,6 +1689,7 @@ static void *lvm_thread_fn(void *arg) } pthread_mutex_unlock(&lvm_thread_mutex); } + return NULL; } /* Pass down some work to the LVM thread */ diff --git a/daemons/clvmd/lvm-functions.c b/daemons/clvmd/lvm-functions.c index 987f39426..9891b26d9 100644 --- a/daemons/clvmd/lvm-functions.c +++ b/daemons/clvmd/lvm-functions.c @@ -50,12 +50,18 @@ static struct cmd_context *cmd = NULL; static struct dm_hash_table *lv_hash = NULL; static pthread_mutex_t lv_hash_lock; +static char last_error[1024]; struct lv_info { int lock_id; int lock_mode; }; +char *get_last_lvm_error() +{ + return last_error; +} + /* Return the mode a lock is currently held at (or -1 if not held) */ static int get_current_lock(char *resource) { @@ -201,8 +207,17 @@ static int do_activate_lv(char *resource, unsigned char lock_flags, int mode) /* Try to get the lock if it's a clustered volume group */ if (lock_flags & LCK_CLUSTER_VG) { status = hold_lock(resource, mode, LKF_NOQUEUE); - if (status) + if (status) { + /* Return an LVM-sensible error for this. + * Forcing EIO makes the upper level return this text + * rather than the strerror text for EAGAIN. + */ + if (errno == EAGAIN) { + sprintf(last_error, "Volume is busy on another node"); + errno = EIO; + } return errno; + } } /* If it's suspended then resume it */ @@ -512,6 +527,19 @@ static void *get_initial_state() return NULL; } +static void lvm2_log_fn(int level, const char *file, int line, + const char *message) +{ + /* + * Ignore non-error messages, but store the latest one for returning + * to the user. + */ + if (level != _LOG_ERR && level != _LOG_FATAL) + return; + + strcpy(last_error, message); +} + /* This checks some basic cluster-LVM configuration stuff */ static void check_config() { @@ -564,5 +592,8 @@ int init_lvm(int using_gulm) get_initial_state(); + /* Trap log messages so we can pass them back to the user */ + init_log_fn(lvm2_log_fn); + return 1; } diff --git a/daemons/clvmd/lvm-functions.h b/daemons/clvmd/lvm-functions.h index 1cd2a81d4..d04964bf7 100644 --- a/daemons/clvmd/lvm-functions.h +++ b/daemons/clvmd/lvm-functions.h @@ -32,5 +32,6 @@ extern void init_lvhash(void); extern int hold_unlock(char *resource); extern int hold_lock(char *resource, int mode, int flags); extern void unlock_all(void); +extern char *get_last_lvm_error(void); #endif