[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[lvm-devel] [PATCH] let dmeventd unmount invalid snapshots (BZ 189462)



Hi,

this is the second part of the snapshot monitoring stuff for
dmeventd. This one will remove mounts of a snapshot when it is
invalidated.

There are some trade-offs involved. I have opted for using an umount
syscall directly since it's simpler and more robust. The downside is
that /etc/mtab will go out of sync and people may actually think that
the snapshot is still mounted (mount(8) just prints mtab without
thinking twice about it). We could just fork off umount(8) instead, but
that can fail in new and interesting ways.

The other possible issue with the patch is that I am not sure whether
it's actually safe to read /proc/mounts incrementally, with possibly
intervening mount/umount calls. It *seems* to be, but a confirmation
would be nice.

The code comes (as usual) with an automated test:
test/t-snapshot-autoumount-dmeventd.sh

Yours,
   Petr.

diff -rN -u -p old-snapshot-monitoring/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c new-snapshot-monitoring/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c
--- old-snapshot-monitoring/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c	2010-10-07 15:08:26.000000000 +0200
+++ new-snapshot-monitoring/daemons/dmeventd/plugins/snapshot/dmeventd_snapshot.c	2010-10-07 15:08:27.000000000 +0200
@@ -21,6 +21,7 @@
 
 #include "lvm-string.h"
 
+#include <sys/mount.h>
 #include <syslog.h> /* FIXME Replace syslog with multilog */
 /* FIXME Missing openlog? */
 
@@ -93,6 +94,44 @@ static int _extend(const char *device)
 	return r == ECMD_PROCESSED;
 }
 
+static void _umount(struct dm_task *dmt)
+{
+	struct dm_info info;
+	const char *device = dm_task_get_name(dmt);
+	FILE *mounts;
+	char buffer[4096];
+	char *words[3];
+	struct stat st;
+
+	if (!dm_task_get_info(dmt, &info))
+		return; /* too bad, but this is best-effort thing... */
+
+	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) == info.major &&
+		    minor(st.st_rdev) == info.minor) {
+			syslog(LOG_ERR, "Unmounting invalid snapshot %s from %s.", device, words[1]);
+			umount2(words[1], MNT_FORCE | MNT_DETACH);
+		}
+	}
+}
+
 void process_event(struct dm_task *dmt,
 		   enum dm_event_mask event __attribute__((unused)),
 		   void **private)
@@ -117,6 +156,9 @@ void process_event(struct dm_task *dmt,
 
 	_parse_snapshot_params(params, &status);
 
+	if (status.invalid)
+		_umount(dmt);
+
 	/*
 	 * If the snapshot has been invalidated or we failed to parse
 	 * the status string. Report the full status string to syslog.
diff -rN -u -p old-snapshot-monitoring/test/test-utils.sh new-snapshot-monitoring/test/test-utils.sh
--- old-snapshot-monitoring/test/test-utils.sh	2010-10-07 15:08:26.000000000 +0200
+++ new-snapshot-monitoring/test/test-utils.sh	2010-10-07 15:08:27.000000000 +0200
@@ -121,6 +121,7 @@ teardown_devs() {
 		init_udev_transaction
 		while dmsetup table | grep -q ^$PREFIX; do
 			for s in `dmsetup info -c -o name --noheading | grep ^$PREFIX`; do
+				umount -fl $DM_DEV_DIR/mapper/$s || true
 				dmsetup remove $s >& /dev/null || true
 			done
 		done
@@ -360,6 +361,11 @@ prepare_lvmconf() {
 	test -z "$filter" && \
 		filter='[ "a/dev\/mirror/", "a/dev\/mapper\/.*pv[0-9_]*$/", "r/.*/" ]'
         locktype=
+	if test -z "$LVM_TEST_CONFIG_SNAPSHOT_AUTOEXTEND"; then
+		LVM_TEST_CONFIG_SNAPSHOT_AUTOEXTEND="\
+   snapshot_autoextend_percent = 50\n\
+   snapshot_autoextend_threshold = 50"
+	fi
 	if test -n "$LVM_TEST_LOCKING"; then locktype="locking_type = $LVM_TEST_LOCKING"; fi
 	cat > $TESTDIR/etc/lvm.conf.new <<-EOF
   $LVM_TEST_CONFIG
@@ -394,8 +400,7 @@ prepare_lvmconf() {
     udev_sync = 1
     udev_rules = 1
     polling_interval = 0
-    snapshot_autoextend_percent = 50
-    snapshot_autoextend_threshold = 50
+    $LVM_TEST_CONFIG_SNAPSHOT_AUTOEXTEND
   }
 EOF
 	# FIXME remove this workaround after mmap & truncating file problems solved
diff -rN -u -p old-snapshot-monitoring/test/t-snapshot-autoumount-dmeventd.sh new-snapshot-monitoring/test/t-snapshot-autoumount-dmeventd.sh
--- old-snapshot-monitoring/test/t-snapshot-autoumount-dmeventd.sh	1970-01-01 01:00:00.000000000 +0100
+++ new-snapshot-monitoring/test/t-snapshot-autoumount-dmeventd.sh	2010-10-07 15:08:27.000000000 +0200
@@ -0,0 +1,41 @@
+#!/bin/bash
+# Copyright (C) 2010 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
+
+# no extensions please
+LVM_TEST_CONFIG_SNAPSHOT_AUTOEXTEND="\
+   snapshot_autoextend_percent = 0\
+   snapshot_autoextend_threshold = 100"
+
+. ./test-utils.sh
+
+which mkfs.ext2 || exit 200
+
+prepare_lvmconf
+
+aux prepare_vg 2
+aux prepare_dmeventd
+
+lvcreate -l 8 -n base $vg
+mkfs.ext2 $DM_DEV_DIR/$vg/base
+
+lvcreate -s -l 4 -n snap $vg/base
+lvchange --monitor y $vg/snap
+
+mkdir mnt
+mount $DM_DEV_DIR/$vg/snap mnt
+mount
+cat /proc/mounts | grep $vg-snap
+
+dd if=/dev/zero of=mnt/file$1 bs=1M count=17
+sync
+sleep 10 # dmeventd only checks every 10 seconds :(
+
+cat /proc/mounts | not grep $vg-snap

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]