--- Begin Message ---
Package: autofs
Version: 5.0.6-2
Severity: important
User: [email protected]
Usertags: origin-ubuntu quantal ubuntu-patch
After merging 5.0.6-2 for Ubuntu I have noticed that upstart init daemon
was tracking the wrong PID of the daemon. [1]
This resulted me into digging what has changed and I noticed the three
patches, which I have attached to this email.
These patches [0001-0003] do three things:
* Check mount.nfs version to be >= 1.1.1
* Check kernel version is >= 2.6.22
* Do above by calling nfs_version_check at pre-demonisation, hence
upstart ending up tracking `mount.nfs -V` call
* all for the sake of figuring out if probing optimisation can be used
(or something, not too sure):
"""
The change to have the kernel process text based mount options can
introduce lengthy timeout waits when attempting a mount to a host
that is not available.
To avoid these waits autofs should probe singleton mounts if it
thinks mount.nfs will pass text options to the kernel (which of
course implies the kernel supports this).
"""
But, mount.nfs 1.1.1 is acient and so is linux kernel 2.6.22... so I'm
thinking to make this a no-op. and simply remove those checks. See mine
Remove-*.patch attached.
With that patch I want to revert the upstream patches [0001-0003].
Setting priority to important as this is change of daemon behaviour and
resource waste to fork calls like this. Feel free to lower severity, if
you wish.
[1] Upstart does not rely on pidfiles, instead it counts forks/clones
and chooses the correct pid to track, such that it notices if it dies /
gets killed. This is more reliable than pidfiles. Upstart can also run
daemons in foreground mode.
--
Regards,
Dmitrijs.
From 5b53c6b01476517df8dd35d48bb72a2e52b833b8 Mon Sep 17 00:00:00 2001
From: Ian Kent <[email protected]>
Date: Thu, 23 Feb 2012 15:58:11 +0800
Subject: [PATCH 1/3] autofs-5.0.6 - add kernel verion check function
Add a function to check kernel version.
---
CHANGELOG | 1 +
include/mounts.h | 17 +++++++++++++++++
2 files changed, 18 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index 29e4049..7e5783f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -27,6 +27,7 @@
- teach automount about sss source.
- fix init script usage message.
- ignore duplicate exports in auto.net.
+- add kernel verion check function.
28/06/2011 autofs-5.0.6
-----------------------
diff --git a/include/mounts.h b/include/mounts.h
index 4d932ca..3947d83 100644
--- a/include/mounts.h
+++ b/include/mounts.h
@@ -16,6 +16,9 @@
#ifndef MOUNTS_H
#define MOUNTS_H
+#include <linux/version.h>
+#include <sys/utsname.h>
+
#ifndef AUTOFS_TYPE_ANY
#define AUTOFS_TYPE_ANY 0x0000
#endif
@@ -72,6 +75,20 @@ struct mnt_list {
struct list_head ordered;
};
+static inline unsigned int linux_version_code(void)
+{
+ struct utsname my_utsname;
+ unsigned int p, q, r;
+
+ if (uname(&my_utsname))
+ return 0;
+
+ p = (unsigned int)atoi(strtok(my_utsname.release, "."));
+ q = (unsigned int)atoi(strtok(NULL, "."));
+ r = (unsigned int)atoi(strtok(NULL, "."));
+ return KERNEL_VERSION(p, q, r);
+}
+
unsigned int query_kproto_ver(void);
unsigned int get_kver_major(void);
unsigned int get_kver_minor(void);
--
1.7.10.4
From 4f15a6b80b67c306ec3ea8bda4cafd2b9b16bd49 Mon Sep 17 00:00:00 2001
From: Ian Kent <[email protected]>
Date: Thu, 23 Feb 2012 15:58:40 +0800
Subject: [PATCH 2/3] autofs-5.0.6 - add function to check mount.nfs version
Add a function to check if the mount.nfs version is greater than or
equal to a given version.
---
CHANGELOG | 1 +
configure | 62 ++++++++++++++++++++++
configure.in | 1 +
include/config.h.in | 6 +++
include/mounts.h | 7 +++
lib/mounts.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 224 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index 7e5783f..359c293 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -28,6 +28,7 @@
- fix init script usage message.
- ignore duplicate exports in auto.net.
- add kernel verion check function.
+- add function to check mount.nfs version.
28/06/2011 autofs-5.0.6
-----------------------
diff --git a/configure b/configure
index f78b322..ec394e7 100755
--- a/configure
+++ b/configure
@@ -645,6 +645,8 @@ HAVE_E2FSCK
E2FSCK
HAVE_UMOUNT
UMOUNT
+HAVE_MOUNT_NFS
+MOUNT_NFS
HAVE_MOUNT
MOUNT
DMALLOCLIB
@@ -3248,6 +3250,66 @@ else
HAVE_MOUNT=0
fi
+for ac_prog in mount.nfs
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_MOUNT_NFS+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $MOUNT_NFS in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_MOUNT_NFS="$MOUNT_NFS" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $searchpath
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_path_MOUNT_NFS="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+MOUNT_NFS=$ac_cv_path_MOUNT_NFS
+if test -n "$MOUNT_NFS"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MOUNT_NFS" >&5
+$as_echo "$MOUNT_NFS" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$MOUNT_NFS" && break
+done
+test -n "$MOUNT_NFS" || MOUNT_NFS="/sbin/mount.nfs "
+
+if test -n "$MOUNT_NFS"; then
+
+$as_echo "#define HAVE_MOUNT_NFS 1" >>confdefs.h
+
+
+cat >>confdefs.h <<_ACEOF
+#define PATH_MOUNT_NFS "$MOUNT_NFS"
+_ACEOF
+
+ HAVE_MOUNT_NFS=1
+else
+ HAVE_MOUNT_NFS=0
+fi
+
for ac_prog in umount
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
diff --git a/configure.in b/configure.in
index c017829..5477508 100644
--- a/configure.in
+++ b/configure.in
@@ -137,6 +137,7 @@ AC_SUBST(DMALLOCLIB)
# Programs needed for various system functions or modules
#
AF_PATH_INCLUDE(MOUNT, mount, /bin/mount, $searchpath)
+AF_PATH_INCLUDE(MOUNT_NFS, mount.nfs, /sbin/mount.nfs , $searchpath)
AF_PATH_INCLUDE(UMOUNT, umount, /bin/umount, $searchpath)
AF_PATH_INCLUDE(E2FSCK, fsck.ext2 e2fsck, , $searchpath)
AF_PATH_INCLUDE(E3FSCK, fsck.ext3 e3fsck, , $searchpath)
diff --git a/include/config.h.in b/include/config.h.in
index fb4aadb..f79d579 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -45,6 +45,9 @@
/* define if you have MOUNT */
#undef HAVE_MOUNT
+/* define if you have MOUNT_NFS */
+#undef HAVE_MOUNT_NFS
+
/* define if the mount command supports the -s option */
#undef HAVE_SLOPPY_MOUNT
@@ -111,6 +114,9 @@
/* define if you have MOUNT */
#undef PATH_MOUNT
+/* define if you have MOUNT_NFS */
+#undef PATH_MOUNT_NFS
+
/* define if you have RANLIB */
#undef PATH_RANLIB
diff --git a/include/mounts.h b/include/mounts.h
index 3947d83..6a6ebab 100644
--- a/include/mounts.h
+++ b/include/mounts.h
@@ -89,6 +89,13 @@ static inline unsigned int linux_version_code(void)
return KERNEL_VERSION(p, q, r);
}
+struct nfs_mount_vers {
+ unsigned int major;
+ unsigned int minor;
+ unsigned int fix;
+};
+int check_nfs_mount_version(struct nfs_mount_vers *, struct nfs_mount_vers *);
+
unsigned int query_kproto_ver(void);
unsigned int get_kver_major(void);
unsigned int get_kver_minor(void);
diff --git a/lib/mounts.c b/lib/mounts.c
index f26579e..efe0438 100644
--- a/lib/mounts.c
+++ b/lib/mounts.c
@@ -19,6 +19,8 @@
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
+#include <sys/wait.h>
+#include <ctype.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/vfs.h>
@@ -30,6 +32,8 @@
#define MAX_OPTIONS_LEN 80
#define MAX_MNT_NAME_LEN 30
+#define EBUFSIZ 1024
+
const unsigned int t_indirect = AUTOFS_TYPE_INDIRECT;
const unsigned int t_direct = AUTOFS_TYPE_DIRECT;
const unsigned int t_offset = AUTOFS_TYPE_OFFSET;
@@ -131,6 +135,149 @@ unsigned int get_kver_minor(void)
return kver.minor;
}
+#ifdef HAVE_MOUNT_NFS
+static int extract_version(char *start, struct nfs_mount_vers *vers)
+{
+ char *s_ver = strchr(start, ' ');
+ while (*s_ver && !isdigit(*s_ver)) {
+ s_ver++;
+ if (!*s_ver)
+ return 0;
+ break;
+ }
+ vers->major = atoi(strtok(s_ver, "."));
+ vers->minor = (unsigned int) atoi(strtok(NULL, "."));
+ vers->fix = (unsigned int) atoi(strtok(NULL, "."));
+ return 1;
+}
+
+int check_nfs_mount_version(struct nfs_mount_vers *vers,
+ struct nfs_mount_vers *check)
+{
+ pid_t f;
+ int ret, status, pipefd[2];
+ char errbuf[EBUFSIZ + 1], *p, *sp;
+ int errp, errn;
+ sigset_t allsigs, tmpsig, oldsig;
+ char *s_ver;
+ int cancel_state;
+
+ if (pipe(pipefd))
+ return -1;
+
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_state);
+
+ sigfillset(&allsigs);
+ pthread_sigmask(SIG_BLOCK, &allsigs, &oldsig);
+
+ f = fork();
+ if (f == 0) {
+ reset_signals();
+ close(pipefd[0]);
+ dup2(pipefd[1], STDOUT_FILENO);
+ dup2(pipefd[1], STDERR_FILENO);
+ close(pipefd[1]);
+
+ execl(PATH_MOUNT_NFS, PATH_MOUNT_NFS, "-V", (char *) NULL);
+ _exit(255); /* execv() failed */
+ }
+
+ ret = 0;
+
+ tmpsig = oldsig;
+
+ sigaddset(&tmpsig, SIGCHLD);
+ pthread_sigmask(SIG_SETMASK, &tmpsig, NULL);
+
+ close(pipefd[1]);
+
+ if (f < 0) {
+ close(pipefd[0]);
+ pthread_sigmask(SIG_SETMASK, &oldsig, NULL);
+ pthread_setcancelstate(cancel_state, NULL);
+ return -1;
+ }
+
+ errp = 0;
+ do {
+ while (1) {
+ errn = read(pipefd[0], errbuf + errp, EBUFSIZ - errp);
+ if (errn == -1 && errno == EINTR)
+ continue;
+ break;
+ }
+
+ if (errn > 0) {
+ errp += errn;
+
+ sp = errbuf;
+ while (errp && (p = memchr(sp, '\n', errp))) {
+ *p++ = '\0';
+ errp -= (p - sp);
+ sp = p;
+ }
+
+ if (errp && sp != errbuf)
+ memmove(errbuf, sp, errp);
+
+ if (errp >= EBUFSIZ) {
+ /* Line too long, split */
+ errbuf[errp] = '\0';
+ if ((s_ver = strstr(errbuf, "nfs-utils"))) {
+ if (extract_version(s_ver, vers))
+ ret = 1;
+ }
+ errp = 0;
+ }
+
+ if ((s_ver = strstr(errbuf, "nfs-utils"))) {
+ if (extract_version(s_ver, vers))
+ ret = 1;
+ }
+ }
+ } while (errn > 0);
+
+ close(pipefd[0]);
+
+ if (errp > 0) {
+ /* End of file without \n */
+ errbuf[errp] = '\0';
+ if ((s_ver = strstr(errbuf, "nfs-utils"))) {
+ if (extract_version(s_ver, vers))
+ ret = 1;
+ }
+ }
+
+ if (ret) {
+ if (vers->major == check->major &&
+ vers->minor == check->minor &&
+ vers->fix == check->fix)
+ ;
+ else {
+ if (vers->major < check->major)
+ ret = 0;
+ else if (vers->minor < check->minor)
+ ret = 0;
+ else if (vers->fix < check->fix)
+ ret = 0;
+ }
+ }
+
+ if (waitpid(f, &status, 0) != f) ;
+
+ pthread_sigmask(SIG_SETMASK, &oldsig, NULL);
+ pthread_setcancelstate(cancel_state, NULL);
+
+ return ret;
+}
+#else
+int check_nfs_mount_version(struct nfs_mount_vers *vers,
+ struct nfs_mount_vers *check)
+{
+ return 0;
+}
+#endif
+
/*
* Make common autofs mount options string
*/
--
1.7.10.4
From 15fcfcd29b47a71ae9dde006f12a87d5e6f19421 Mon Sep 17 00:00:00 2001
From: Ian Kent <[email protected]>
Date: Thu, 23 Feb 2012 15:59:09 +0800
Subject: [PATCH 3/3] autofs-5.0.6 - reinstate singleton mount probe
The change to have the kernel process text based mount options can
introduce lengthy timeout waits when attempting a mount to a host
that is not available.
To avoid these waits autofs should probe singleton mounts if it
thinks mount.nfs will pass text options to the kernel (which of
course implies the kernel supports this).
---
CHANGELOG | 1 +
daemon/automount.c | 7 +++++++
include/mounts.h | 1 +
modules/replicated.c | 18 ++++++++++++++++--
4 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 359c293..5a6af1c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -29,6 +29,7 @@
- ignore duplicate exports in auto.net.
- add kernel verion check function.
- add function to check mount.nfs version.
+- reinstate singleton mount probe.
28/06/2011 autofs-5.0.6
-----------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index c0b4b85..31dd564 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -51,6 +51,9 @@ const char *libdir = AUTOFS_LIB_DIR; /* Location of library modules */
const char *mapdir = AUTOFS_MAP_DIR; /* Location of mount maps */
const char *confdir = AUTOFS_CONF_DIR; /* Location of autofs config file */
+unsigned int nfs_mount_uses_string_options = 0;
+static struct nfs_mount_vers vers, check = {1, 1, 1};
+
/* autofs fifo name prefix */
const char *fifodir = AUTOFS_FIFO_DIR "/autofs.fifo";
@@ -1273,6 +1276,8 @@ static int do_hup_signal(struct master *master, time_t age)
if (status)
fatal(status);
+ nfs_mount_uses_string_options = check_nfs_mount_version(&vers, &check);
+
master_mutex_lock();
if (master->reading) {
status = pthread_mutex_unlock(&mrc.mutex);
@@ -1936,6 +1941,8 @@ int main(int argc, char *argv[])
defaults_read_config(0);
+ nfs_mount_uses_string_options = check_nfs_mount_version(&vers, &check);
+
kpkt_len = get_kpkt_len();
timeout = defaults_get_timeout();
ghost = defaults_get_browse_mode();
diff --git a/include/mounts.h b/include/mounts.h
index 6a6ebab..9aac90f 100644
--- a/include/mounts.h
+++ b/include/mounts.h
@@ -95,6 +95,7 @@ struct nfs_mount_vers {
unsigned int fix;
};
int check_nfs_mount_version(struct nfs_mount_vers *, struct nfs_mount_vers *);
+extern unsigned int nfs_mount_uses_string_options;
unsigned int query_kproto_ver(void);
unsigned int get_kver_major(void);
diff --git a/modules/replicated.c b/modules/replicated.c
index 65634bd..84134b6 100644
--- a/modules/replicated.c
+++ b/modules/replicated.c
@@ -901,6 +901,7 @@ int prune_host_list(unsigned logopt, struct host **list,
unsigned int v2_udp_count, v3_udp_count, v4_udp_count;
unsigned int max_udp_count, max_tcp_count, max_count;
int status;
+ int kern_vers;
if (!*list)
return 0;
@@ -920,9 +921,22 @@ int prune_host_list(unsigned logopt, struct host **list,
* or a single host entry whose proximity isn't local. If so
* return immediately as we don't want to add probe latency for
* the common case of a single filesystem mount request.
+ *
+ * But, if the kernel understands text nfs mount options then
+ * mount.nfs most likely bypasses its probing and lets the kernel
+ * do all the work. This can lead to long timeouts for hosts that
+ * are not available so check the kernel version and mount.nfs
+ * version and probe singleton mounts if the kernel version is
+ * greater than 2.6.22 and mount.nfs version is greater than 1.1.1.
*/
- if (!this || !this->next)
- return 1;
+ if (nfs_mount_uses_string_options &&
+ (kern_vers = linux_version_code()) > KERNEL_VERSION(2, 6, 22)) {
+ if (!this)
+ return 1;
+ } else {
+ if (!this || !this->next)
+ return 1;
+ }
proximity = this->proximity;
while (this) {
--
1.7.10.4
From 97a2254514b131a4dbf3f0b7f50c3b7d5d03b803 Mon Sep 17 00:00:00 2001
From: Dmitrijs Ledkovs <[email protected]>
Date: Fri, 22 Jun 2012 18:02:09 +0100
Subject: [PATCH] Remove kernel & mount.nfs version checks on Debian/Ubuntu.
---
modules/replicated.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/modules/replicated.c b/modules/replicated.c
index 10e1429..049fabd 100644
--- a/modules/replicated.c
+++ b/modules/replicated.c
@@ -964,9 +964,8 @@ int prune_host_list(unsigned logopt, struct host **list,
* But also allow the MOUNT_WAIT configuration parameter to override
* the probing.
*/
- if (nfs_mount_uses_string_options &&
- defaults_get_mount_wait() == -1 &&
- (kern_vers = linux_version_code()) > KERNEL_VERSION(2, 6, 22)) {
+
+ if (defaults_get_mount_wait() == -1) {
if (!this)
return 1;
} else {
--
1.7.10.4
--- End Message ---