[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