summaryrefslogtreecommitdiffstats
path: root/daemons/dmeventd/plugins
diff options
context:
space:
mode:
authorPetr Rockai <prockai@redhat.com>2010-10-29 16:43:51 +0000
committerPetr Rockai <prockai@redhat.com>2010-10-29 16:43:51 +0000
commitfe9ac4d3f4e4d5b8153189bd3b2ecc2c8385e977 (patch)
treee490b0296000b56e8c74a5dc65ac6215d8ee6320 /daemons/dmeventd/plugins
parent63b8dfbde70f61cf318df70f83b078e28115faca (diff)
downloadlvm2-fe9ac4d3f4e4d5b8153189bd3b2ecc2c8385e977.tar.gz
lvm2-fe9ac4d3f4e4d5b8153189bd3b2ecc2c8385e977.tar.xz
lvm2-fe9ac4d3f4e4d5b8153189bd3b2ecc2c8385e977.zip
Add code to the dmeventd snapshot plugin to automatically unmount snapshots
that have been invalidated.
Diffstat (limited to 'daemons/dmeventd/plugins')
-rw-r--r--daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c b/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c
index e3d0b4eb..00fc4362 100644
--- a/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c
+++ b/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c
@@ -21,6 +21,7 @@
#include "lvm-string.h"
+#include <sys/wait.h>
#include <syslog.h> /* FIXME Replace syslog with multilog */
/* FIXME Missing openlog? */
@@ -31,6 +32,8 @@
/* Do not bother checking snapshots less than 50% full. */
#define CHECK_MINIMUM 50
+#define UMOUNT_COMMAND "/bin/umount"
+
struct snap_status {
int invalid;
int used;
@@ -71,6 +74,47 @@ static void _parse_snapshot_params(char *params, struct snap_status *status)
status->max = atoi(p);
}
+static int _run(const char *cmd, ...)
+{
+ va_list ap;
+ int argc = 1; /* for argv[0], i.e. cmd */
+ int i = 0;
+ const char **argv;
+ pid_t pid = fork();
+ int status;
+
+ if (pid == 0) { /* child */
+ va_start(ap, cmd);
+ while (va_arg(ap, const char *))
+ ++ argc;
+ va_end(ap);
+
+ /* + 1 for the terminating NULL */
+ argv = alloca(sizeof(const char *) * (argc + 1));
+
+ argv[0] = cmd;
+ va_start(ap, cmd);
+ while ((argv[++i] = va_arg(ap, const char *)));
+ va_end(ap);
+
+ execvp(cmd, (char **)argv);
+ syslog(LOG_ERR, "Failed to execute %s: %s.\n", cmd, strerror(errno));
+ exit(127);
+ }
+
+ if (pid > 0) { /* parent */
+ if (waitpid(pid, &status, 0) != pid)
+ return 0; /* waitpid failed */
+ if (!WIFEXITED(status) || WEXITSTATUS(status))
+ return 0; /* the child failed */
+ }
+
+ if (pid < 0)
+ return 0; /* fork failed */
+
+ return 1; /* all good */
+}
+
static int _extend(const char *device)
{
char *vg = NULL, *lv = NULL, *layer = NULL;
@@ -93,6 +137,41 @@ static int _extend(const char *device)
return r == ECMD_PROCESSED;
}
+static void _umount(const char *device, int major, int minor)
+{
+ FILE *mounts;
+ char buffer[4096];
+ char *words[3];
+ struct stat st;
+
+ if (!(mounts = fopen("/proc/mounts", "r"))) {
+ syslog(LOG_ERR, "Could not read /proc/mounts. Not umounting %s.\n", device);
+ return;
+ }
+
+ while (!feof(mounts)) {
+ /* read a line of /proc/mounts */
+ if (!fgets(buffer, sizeof(buffer), mounts))
+ break; /* eof, likely */
+
+ /* words[0] is the mount point and words[1] is the device path */
+ dm_split_words(buffer, 3, 0, words);
+
+ /* find the major/minor of the device */
+ if (stat(words[0], &st))
+ continue; /* can't stat, skip this one */
+
+ if (S_ISBLK(st.st_mode) &&
+ major(st.st_rdev) == major &&
+ minor(st.st_rdev) == minor) {
+ syslog(LOG_ERR, "Unmounting invalid snapshot %s from %s.", device, words[1]);
+ if (!_run(UMOUNT_COMMAND, "-fl", words[1], NULL))
+ syslog(LOG_ERR, "Failed to umount snapshot %s from %s: %s.",
+ device, words[1], strerror(errno));
+ }
+ }
+}
+
void process_event(struct dm_task *dmt,
enum dm_event_mask event __attribute__((unused)),
void **private)
@@ -117,6 +196,16 @@ void process_event(struct dm_task *dmt,
_parse_snapshot_params(params, &status);
+ if (status.invalid) {
+ syslog(LOG_ERR, "Trying to umount invalid snapshot %s...\n", device);
+ struct dm_info info;
+ if (dm_task_get_info(dmt, &info)) {
+ dmeventd_lvm2_unlock();
+ _umount(device, info.major, info.minor);
+ return;
+ } /* else; too bad, but this is best-effort thing... */
+ }
+
/*
* If the snapshot has been invalidated or we failed to parse
* the status string. Report the full status string to syslog.