[Ocfs2-tools-devel] [PATCH 03/39] umount.ocfs2: Add umount.ocfs2 to pair mount.ocfs2

Joel Becker joel.becker at oracle.com
Fri Mar 14 16:52:26 PDT 2008


Rather than use a userspace_helper callout, use the umount.<fstype>
functionality available in mount(8) since 2.12j.

- Remove OCFS2_FSTYPE and promote OCFS2_FS_NAME to the o2cb header
- Remove ocfs2_hb_ctl calls from mount.ocfs2.  It now calls
  ocfs2_start_heartbeat() directly.
- Add umount.ocfs2 to call ocfs2_stop_heartbeat().

As we will rely on umount.ocfs2 to clear heartbeat when a volume is
unmounted, we don't want the kernel calling ocfs2_hb_ctl anymore.  Set
/proc/sys/fs/ocfs2/nm/hb_ctl_path to "/bin/true".  This will be a noop,
but will not break existing kernel modules.

Signed-off-by: Joel Becker <joel.becker at oracle.com>
---
 configure.in                              |   27 ++++
 include/o2cb/o2cb.h                       |    3 +
 mount.ocfs2/.gitignore                    |    1 +
 mount.ocfs2/Makefile                      |   20 ++-
 mount.ocfs2/mount.ocfs2.c                 |   56 ++------
 mount.ocfs2/umount.ocfs2.c                |  235 +++++++++++++++++++++++++++++
 vendor/common/o2cb.init.sh                |   12 ++
 vendor/common/ocfs2-tools.spec-generic.in |    5 +-
 8 files changed, 305 insertions(+), 54 deletions(-)
 create mode 100644 mount.ocfs2/umount.ocfs2.c

diff --git a/configure.in b/configure.in
index d3bf6bc..c1bf2c6 100644
--- a/configure.in
+++ b/configure.in
@@ -147,6 +147,33 @@ GLIB_REQUIRED_VERSION=2.2.3
 AM_PATH_GLIB_2_0($GLIB_REQUIRED_VERSION, have_glib=yes,
  AC_MSG_ERROR([GLib $GLIB_REQUIRED_VERSION or better is required]))
 
+umount_newp()
+{
+    NEEDVER="2.12j"
+    FOUNDVER="`/bin/umount -V | awk '
+        /util-linux/{sub(/\)$/, "", $3); print $3}
+        /mount-/{sub(/^.*mount-/, ""); print}'`"
+
+    test "x$FOUNDVER" = "x" && return 1
+    test "x$FOUNDVER" = "x$NEEDVER" && return 0
+
+    # If we don't have exactly NEEDVER, we better sort to something better.
+    RESVER="`(echo "$NEEDVER"; echo "$FOUNDVER") | sort -n | tail -1`"
+    if test "x$RESVER" = "x$NEEDVER"; then
+        return 1
+    else
+        return 0
+    fi
+}
+
+AC_MSG_CHECKING([for a new enough umount])
+if umount_newp; then
+    AC_MSG_RESULT([found])
+else
+    AC_MSG_RESULT([not found])
+    AC_MSG_ERROR([umount is not new enough to support umount.ocfs2])
+fi
+
 AC_MSG_CHECKING(whether to build fsck dynamically)
 AC_ARG_ENABLE([dynamic-fsck], [  --enable-dynamic-fsck=[yes/no]    Build fsck dynamically [default=no]],,enable_dynamic_fsck=no)
 OCFS2_DYNAMIC_FSCK=
diff --git a/include/o2cb/o2cb.h b/include/o2cb/o2cb.h
index 8147388..ada8f88 100644
--- a/include/o2cb/o2cb.h
+++ b/include/o2cb/o2cb.h
@@ -47,6 +47,9 @@
 #include <o2cb/ocfs2_nodemanager.h>
 #include <o2cb/ocfs2_heartbeat.h>
 
+
+#define OCFS2_FS_NAME		"ocfs2"
+
 errcode_t o2cb_init(void);
 
 errcode_t o2cb_create_cluster(const char *cluster_name);
diff --git a/mount.ocfs2/.gitignore b/mount.ocfs2/.gitignore
index 12254f9..7b2665f 100644
--- a/mount.ocfs2/.gitignore
+++ b/mount.ocfs2/.gitignore
@@ -1,5 +1,6 @@
 .*.sw?
 mount.ocfs2
+umount.ocfs2
 mount.ocfs2.8
 *.d
 cscope.*
diff --git a/mount.ocfs2/Makefile b/mount.ocfs2/Makefile
index 75072a6..cb1dc4b 100644
--- a/mount.ocfs2/Makefile
+++ b/mount.ocfs2/Makefile
@@ -3,7 +3,7 @@ TOPDIR = ..
 include $(TOPDIR)/Preamble.make
 
 sbindir = $(root_sbindir)
-SBIN_PROGRAMS = mount.ocfs2
+SBIN_PROGRAMS = mount.ocfs2 umount.ocfs2
 
 INCLUDES = -I$(TOPDIR)/include
 LIBOCFS2_LIBS = -L$(TOPDIR)/libocfs2 -locfs2
@@ -15,20 +15,24 @@ LIBO2CB_DEPS = $(TOPDIR)/libo2cb/libo2cb.a
 
 DEFINES = -DVERSION=\"$(VERSION)\"
 
-CFILES = opts.c mount.ocfs2.c
-CFILES += fstab.c mntent.c realpath.c sundries.c xmalloc.c
+CORE_CFILES = fstab.c mntent.c realpath.c sundries.c xmalloc.c opts.c
+MOUNT_CFILES = mount.ocfs2.c
+UMOUNT_CFILES = umount.ocfs2.c
 
-HFILES = $(subst .c,.h,$(CFILES))
+HFILES = $(subst .c,.h,$(MOUNT_CFILES) $(CORE_CFILES))
 HFILES += mount_constants.h nls.h paths.h
 
-OBJS = $(subst .c,.o,$(CFILES))
+MOUNT_OBJS = $(subst .c,.o,$(MOUNT_CFILES) $(CORE_CFILES))
+UMOUNT_OBJS = $(subst .c,.o,$(UMOUNT_CFILES) $(CORE_CFILES))
 MANS = mount.ocfs2.8
 
-DIST_FILES = $(CFILES) $(HFILES) $(addsuffix .in,$(MANS))
+DIST_FILES = $(CORE_CFILES) $(MOUNT_CFILES) $(UMOUNT_CFILES) \
+	     $(HFILES) $(addsuffix .in,$(MANS))
 
-all: mount.ocfs2
+mount.ocfs2: $(MOUNT_OBJS) $(LIBOCFS2_DEPS) $(LIBO2DLM_DEPS) $(LIBO2CB_DEPS)
+	$(LINK) $(LIBOCFS2_LIBS) $(LIBO2DLM_LIBS) $(LIBO2CB_LIBS) $(COM_ERR_LIBS)
 
-mount.ocfs2: $(OBJS) $(LIBOCFS2_DEPS) $(LIBO2DLM_DEPS) $(LIBO2CB_DEPS)
+umount.ocfs2: $(UMOUNT_OBJS) $(LIBOCFS2_DEPS) $(LIBO2DLM_DEPS) $(LIBO2CB_DEPS)
 	$(LINK) $(LIBOCFS2_LIBS) $(LIBO2DLM_LIBS) $(LIBO2CB_LIBS) $(COM_ERR_LIBS)
 
 include $(TOPDIR)/Postamble.make
diff --git a/mount.ocfs2/mount.ocfs2.c b/mount.ocfs2/mount.ocfs2.c
index 96da2cd..845c65f 100644
--- a/mount.ocfs2/mount.ocfs2.c
+++ b/mount.ocfs2/mount.ocfs2.c
@@ -1,4 +1,6 @@
-/*
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
  * mount.ocfs2.c  Mounts ocfs2 volume
  *
  * Copyright (C) 2005 Oracle.  All rights reserved.
@@ -22,8 +24,6 @@
 
 #include "mount.ocfs2.h"
 
-#define OCFS2_FS_NAME		"ocfs2"
-
 int verbose = 0;
 int mount_quiet = 0;
 char *progname = NULL;
@@ -211,19 +211,6 @@ static int check_dev_readonly(const char *dev, int *dev_ro)
 	return 0;
 }
 
-static int check_for_hb_ctl(const char *hb_ctl_path)
-{
-	int ret;
-
-	ret = access(hb_ctl_path, X_OK);
-	if (ret < 0) {
-		ret = errno;
-		return ret;
-	}
-
-	return ret;
-}
-
 static int run_hb_ctl(const char *hb_ctl_path,
 		      const char *device, const char *arg)
 {
@@ -263,25 +250,6 @@ bail:
 	return ret;
 }
 
-static int start_heartbeat(const char *hb_ctl_path,
-			   const char *device)
-{
-	int ret;
-
-	ret = check_for_hb_ctl(hb_ctl_path);
-	if (ret)
-		return ret;
-
-	ret = run_hb_ctl(hb_ctl_path, device, "-S");
-
-	return ret;
-}
-
-static int stop_heartbeat(const char *hb_ctl_path,
-			  const char *device)
-{
-	return run_hb_ctl(hb_ctl_path, device, "-K");
-}
 
 int main(int argc, char **argv)
 {
@@ -320,15 +288,13 @@ int main(int argc, char **argv)
 		goto bail;
 
 	ret = ocfs2_open(mo.dev, OCFS2_FLAG_RO, 0, 0, &fs); //O_EXCL?
-	if (!ret) {
-		clustered = (0 == ocfs2_mount_local(fs));
-		ocfs2_close(fs);
-		fs = NULL;
-	} else {
+	if (ret) {
 		com_err(progname, ret, "while opening device %s", mo.dev);
 		goto bail;
 	}
 
+	clustered = (0 == ocfs2_mount_local(fs));
+
 	if (verbose)
 		printf("device=%s\n", mo.dev);
 
@@ -358,11 +324,11 @@ int main(int argc, char **argv)
 	block_signals (SIG_BLOCK);
 
 	if (!(mo.flags & MS_REMOUNT) && !dev_ro && clustered) {
-		ret = start_heartbeat(hb_ctl_path, mo.dev);
+		ret = ocfs2_start_heartbeat(fs);
 		if (ret) {
 			block_signals (SIG_UNBLOCK);
-			com_err(progname, 0, "Error when attempting to run %s: "
-				"\"%s\"", hb_ctl_path, strerror(ret));
+			com_err(progname, ret,
+				"while trying to start heartbeat");
 			goto bail;
 		}
 		hb_started = 1;
@@ -384,7 +350,7 @@ int main(int argc, char **argv)
 	if (ret) {
 		ret = errno;
 		if (hb_started)
-			stop_heartbeat(hb_ctl_path, mo.dev);
+			ocfs2_stop_heartbeat(fs);
 		block_signals (SIG_UNBLOCK);
 		com_err(progname, ret, "while mounting %s on %s. "
 			"Check 'dmesg' for more information on this error.",
@@ -402,6 +368,8 @@ int main(int argc, char **argv)
 	block_signals (SIG_UNBLOCK);
 
 bail:
+	if (fs)
+		ocfs2_close(fs);
 	if (extra)
 		free(extra);
 	if (mo.dev)
diff --git a/mount.ocfs2/umount.ocfs2.c b/mount.ocfs2/umount.ocfs2.c
new file mode 100644
index 0000000..9232ade
--- /dev/null
+++ b/mount.ocfs2/umount.ocfs2.c
@@ -0,0 +1,235 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * umount.ocfs2.c  Unounts ocfs2 volume
+ *
+ * Copyright (C) 2007 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include "mount.ocfs2.h"
+#include "o2cb/o2cb.h"
+
+/* Do not try to include <linux/mount.h> -- lots of errors */
+#if !defined(MNT_DETACH)
+# define MNT_DETACH 2
+#endif
+
+int verbose = 0;
+int mount_quiet = 0;
+char *progname = NULL;
+
+static int nomtab = 0;
+
+struct mount_options {
+	char *dir;
+	char *dev;
+	int flags;
+};
+
+static void handle_signal(int sig)
+{
+	switch (sig) {
+	case SIGTERM:
+	case SIGINT:
+		printf("\numount interrupted\n");
+		exit(1);
+	}
+}
+
+static void read_options(int argc, char **argv, struct mount_options *mo)
+{
+	int c;
+
+	progname = basename(argv[0]);
+
+	if (argc < 2)
+		return;
+
+	while(1) {
+		c = getopt(argc, argv, "flvn");
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'v':
+			++verbose;
+			break;
+
+		case 'n':
+			++nomtab;
+			break;
+
+		case 'f':
+			/*
+			 * Do nothing, as we don't support MNT_FORCE.  We
+			 * need to handle this option for autofs
+			 */
+			break;
+
+		case 'l':
+			mo->flags |= MNT_DETACH;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	if (optind < argc && argv[optind])
+		mo->dir = xstrdup(argv[optind]);
+}
+
+static int process_options(struct mount_options *mo)
+{
+	struct mntentchn *mc;
+
+	if (!mo->dir) {
+		com_err(progname, OCFS2_ET_INVALID_ARGUMENT, "no mountpoint specified");
+		return -1;
+	}
+
+	/*
+	 * We need the device to read heartbeat information, etc.  Find
+	 * the *last* entry matching our mo->dir.  This may be a mountpoint
+	 * or a device, so we try a mountpoint first (the usual case).
+	 */
+	mc = getmntdirbackward(mo->dir, NULL);
+	if (mc) {
+		mo->dev = xstrdup(mc->m.mnt_fsname);
+	} else {
+		mc = getmntdevbackward(mo->dir, NULL);
+		if (!mc) {
+			fprintf(stderr, "Unable to find %s in mount list\n",
+				mo->dir);
+			return -1;
+		}
+		mo->dev = mo->dir;
+		mo->dir = xstrdup(mc->m.mnt_dir);
+	}
+
+	return 0;
+}
+
+static int check_dev_readonly(const char *dev, int *dev_ro)
+{
+	int fd;
+	int ret;
+
+	fd = open(dev, O_RDONLY);
+	if (fd < 0)
+		return errno;
+
+	ret = ioctl(fd, BLKROGET, dev_ro);
+	if (ret < 0)
+		return errno;
+
+	close(fd);
+
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+	errcode_t ret = 0;
+	struct mount_options mo;
+	ocfs2_filesys *fs = NULL;
+	int clustered = 1;
+
+	initialize_ocfs_error_table();
+	initialize_o2dl_error_table();
+	initialize_o2cb_error_table();
+
+	setbuf(stdout, NULL);
+	setbuf(stderr, NULL);
+
+	if (signal(SIGTERM, handle_signal) == SIG_ERR) {
+		fprintf(stderr, "Could not set SIGTERM\n");
+		exit(1);
+	}
+
+	if (signal(SIGINT, handle_signal) == SIG_ERR) {
+		fprintf(stderr, "Could not set SIGINT\n");
+		exit(1);
+	}
+
+	memset(&mo, 0, sizeof(mo));
+	read_options (argc, argv, &mo);
+
+	ret = process_options(&mo);
+	if (ret)
+		goto bail;
+
+	ret = ocfs2_open(mo.dev, OCFS2_FLAG_RO, 0, 0, &fs); //O_EXCL?
+	if (ret) {
+		com_err(progname, ret, "while opening device %s", mo.dev);
+		goto bail;
+	}
+
+	clustered = (0 == ocfs2_mount_local(fs));
+
+	if (verbose)
+		printf("device=%s\n", mo.dev);
+
+	if (clustered) {
+		ret = o2cb_init();
+		if (ret) {
+			com_err(progname, ret, "Cannot initialize cluster");
+			goto bail;
+		}
+	}
+
+	block_signals (SIG_BLOCK);
+
+	rc = -ENOSYS;
+	if (mo.flags) {
+		rc = umount2(mo.dir, mo.flags);
+		if (rc) {
+			rc = -errno;
+			fprintf(stderr, "Error calling umount2(): %s",
+				strerror(-rc));
+			if ((rc == -ENOSYS) && verbose)
+				fprintf(stdout,
+					"No umount2(), trying umount()...\n");
+		}
+	}
+	if (rc == -ENOSYS) {
+		rc = umount(mo.dir);
+		if (rc) {
+			rc = -errno;
+			fprintf(stderr, "Error unmounting %s: %s\n", mo.dir,
+				strerror(-rc));
+		}
+	}
+
+	if (rc)
+		goto unblock;
+
+	if (clustered)
+		ocfs2_stop_heartbeat(fs);
+
+	if (!nomtab)
+		update_mtab(mo.dir, NULL);
+
+unblock:
+	block_signals (SIG_UNBLOCK);
+
+bail:
+	if (fs)
+		ocfs2_close(fs);
+	if (mo.dev)
+		free(mo.dev);
+	if (mo.dir)
+		free(mo.dir);
+
+	return ret ? 1 : 0;
+}
diff --git a/vendor/common/o2cb.init.sh b/vendor/common/o2cb.init.sh
index 0ba3d99..d3075a5 100644
--- a/vendor/common/o2cb.init.sh
+++ b/vendor/common/o2cb.init.sh
@@ -815,6 +815,18 @@ load()
     mount_filesystem "ocfs2_dlmfs" "/dlm"
     if_fail $?
 
+    #
+    # This version of ocfs2-tools relies on umount.ocfs2, so we don't need
+    # to call ocfs2_hb_ctl from the kernel.  Given that older drivers may
+    # still want to, we have them just call /bin/true.
+    #
+    echo "/bin/true" >/proc/sys/fs/ocfs2/nm/hb_ctl_path
+    if [ $? != 0 ]
+    then
+        echo -n "Clearing kernel heartbeat control path: "
+        if_fail 1 "Unable to set hb_ctl_path"
+    fi
+
     return 0
 }
 
diff --git a/vendor/common/ocfs2-tools.spec-generic.in b/vendor/common/ocfs2-tools.spec-generic.in
index 01de00d..7673742 100644
--- a/vendor/common/ocfs2-tools.spec-generic.in
+++ b/vendor/common/ocfs2-tools.spec-generic.in
@@ -28,8 +28,8 @@ Distribution: Oracle
 Vendor: Oracle
 Packager: nobody <nobody at oracle.com>
 Exclusiveos: Linux
-Requires: bash, coreutils, net-tools, modutils, e2fsprogs, @@CHKCONFIG_DEP@@, glib2 >= 2.2.3
-BuildRequires: e2fsprogs-devel, glib2-devel >= 2.2.3, @@PYGTK_NAME@@ >= 1.99.16, python-devel >= @@PYVERSION@@
+Requires: bash, coreutils, net-tools, modutils, e2fsprogs, @@CHKCONFIG_DEP@@, glib2 >= 2.2.3, util-linux >= 2.12j
+BuildRequires: e2fsprogs-devel, glib2-devel >= 2.2.3, @@PYGTK_NAME@@ >= 1.99.16, python-devel >= @@PYVERSION@@, util-linux >= 2.12j
 
 BuildRoot: %{_tmppath}/ocfs2-tools-%{PACKAGE_VERSION}-%{PACKAGE_RELEASE}-root
 
@@ -117,6 +117,7 @@ fi
 /sbin/debugfs.ocfs2
 /sbin/o2cb_ctl
 /sbin/mount.ocfs2
+/sbin/umount.ocfs2
 /sbin/ocfs2cdsl
 /sbin/ocfs2_hb_ctl
 /etc/init.d/o2cb
-- 
1.5.3.8




More information about the Ocfs2-tools-devel mailing list