- make am-utils work with autofs (since NFSv2 client is disabled) and add misc bug fixes (bz1074376).

This commit is contained in:
Ian Kent 2014-03-20 15:19:26 +08:00
parent 47dd6a17a1
commit 74b172da44
10 changed files with 472 additions and 1 deletions

View File

@ -0,0 +1,24 @@
From: Ian Kent <raven@themaw.net>
---
conf/autofs/autofs_linux.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/conf/autofs/autofs_linux.c b/conf/autofs/autofs_linux.c
index 5e6a171..fd5dbc6 100644
--- a/conf/autofs/autofs_linux.c
+++ b/conf/autofs/autofs_linux.c
@@ -753,6 +753,10 @@ autofs_umount_succeeded(am_node *mp)
autofs_fh_t *fh = mp->am_parent->am_autofs_fh;
struct autofs_pending_umount **pp, *p;
+ /* Already gone? */
+ if (fh == NULL)
+ return 0;
+
pp = &fh->pending_umounts;
while (*pp && !STREQ((*pp)->name, mp->am_name))
pp = &(*pp)->next;

View File

@ -0,0 +1,35 @@
am-utils-6.1.5 - dont background autofs umount
From: Ian Kent <ikent@redhat.com>
When using an autofs multi-level mount map amd can fail to umount
NFS leaf mounts causing shutdown to fail. It also can cause amd to
SEGV because, even though umounts fail, the autofs mount control
structure is freed and a later umount attempt doesn't check if this
struct is valid before using it.
The cause of the umount failure appears to be the background umount
of NFS mounts at the leaf of the tree not finishing before the autofs
file system mounts above are attempted.
It isn't worth adding a patch to check if the autofs mount control
structure is valid because if it isn't, in this case, amd doesn't
crash but still becomes unresponsive.
---
amd/map.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/amd/map.c b/amd/map.c
index 2fad4b7..8e86b39 100644
--- a/amd/map.c
+++ b/amd/map.c
@@ -946,7 +946,8 @@ unmount_mp(am_node *mp)
#endif /* HAVE_FS_AUTOFS */
if ((mf->mf_fsflags & FS_UBACKGROUND) &&
- (mf->mf_flags & MFF_MOUNTED)) {
+ (mf->mf_flags & MFF_MOUNTED) &&
+ !(mf->mf_flags & MFF_ON_AUTOFS)) {
dlog("Trying unmount in background");
run_task(unmount_node, (opaque_t) mp,
free_map_if_success, (opaque_t) mp);

View File

@ -0,0 +1,28 @@
am-utils-6.1.5 - fix autofs proto version define
From: Ian Kent <raven@themaw.net>
I don't think am-utils works with autofs protocol version 5.
---
conf/autofs/autofs_linux.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/conf/autofs/autofs_linux.c b/conf/autofs/autofs_linux.c
index f56befa..eeb211f 100644
--- a/conf/autofs/autofs_linux.c
+++ b/conf/autofs/autofs_linux.c
@@ -59,8 +59,11 @@
*/
#define AUTOFS_MIN_VERSION 3
+#if AUTOFS_MAX_PROTO_VERSION >= 5
+#define AUTOFS_MAX_VERSION 4
+#else
#define AUTOFS_MAX_VERSION AUTOFS_MAX_PROTO_VERSION
-
+#endif
/*
* STRUCTURES:

View File

@ -0,0 +1,33 @@
am-utils-6.1.5 - handle ENOENT umount return for autofs mounts
From: Ian Kent <ikent@redhat.com>
An ENOENT return from umount(2) means the kernel path walk couldn't
resolve the path of the mount to a dentry. In that case there can't
be an autofs waitq entry waiting for notification, since there's no
dentry, so don't even try to notify the kernel.
---
amd/map.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/amd/map.c b/amd/map.c
index 8e86b39..e6d14b8 100644
--- a/amd/map.c
+++ b/amd/map.c
@@ -873,10 +873,12 @@ free_map_if_success(int rc, int term, opaque_t arg)
else
plog(XLOG_ERROR, "%s: unmount: %s", mp->am_path, strerror(rc));
#ifdef HAVE_FS_AUTOFS
- if (mf->mf_flags & MFF_IS_AUTOFS)
- autofs_get_mp(mp);
- if (mp->am_flags & AMF_AUTOFS)
- autofs_umount_failed(mp);
+ if (rc != ENOENT) {
+ if (mf->mf_flags & MFF_IS_AUTOFS)
+ autofs_get_mp(mp);
+ if (mp->am_flags & AMF_AUTOFS)
+ autofs_umount_failed(mp);
+ }
#endif /* HAVE_FS_AUTOFS */
amd_stats.d_uerr++;
} else {

View File

@ -0,0 +1,13 @@
diff -up am-utils-6.1.5/amd/map.c.orig am-utils-6.1.5/amd/map.c
--- am-utils-6.1.5/amd/map.c.orig 2014-03-19 19:45:45.000000000 +0800
+++ am-utils-6.1.5/amd/map.c 2014-03-19 19:47:42.741848068 +0800
@@ -748,7 +748,8 @@ umount_exported(void)
} else {
am_unmounted(mp);
}
- exported_ap[i] = NULL;
+ if (!(mf->mf_flags && (MFF_UNMOUNTING|MFF_MOUNTED)))
+ exported_ap[i] = NULL;
} else {
/*
* Any other node gets forcibly timed out.

View File

@ -0,0 +1,50 @@
am-utils-6.2-0.git.9b652fb4 - linux umount wait on ebusy
From: Ian Kent <ikent@redhat.com>
For some reason, when umounting autofs mounts after closing the ioctl
file handle, the kernel can return EBUSY for some small amount of time.
This can cause umounts to incorrectly fail when in fact they should
succeed.
Retrying for about a second and a half seems to work quite well.
---
conf/umount/umount_linux.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/conf/umount/umount_linux.c b/conf/umount/umount_linux.c
index 782c2cd..81b0527 100644
--- a/conf/umount/umount_linux.c
+++ b/conf/umount/umount_linux.c
@@ -63,6 +63,7 @@ umount_fs(char *mntdir, const char *mnttabname, u_int unmount_flags)
char loopstr[] = "loop=";
char *loopdev;
#endif /* HAVE_LOOP_DEVICE */
+ unsigned int retries = 8;
mp = mlist = read_mtab(mntdir, mnttabname);
@@ -94,6 +95,7 @@ umount_fs(char *mntdir, const char *mnttabname, u_int unmount_flags)
unlock_mntlist();
#endif /* MOUNT_TABLE_ON_FILE */
+again:
#if defined(HAVE_UMOUNT2) && defined(MNT2_GEN_OPT_DETACH)
/*
* If user asked to try forced unmounts, then do a quick check to see if
@@ -111,6 +113,14 @@ umount_fs(char *mntdir, const char *mnttabname, u_int unmount_flags)
} else
#endif /* defined(HAVE_UMOUNT2) && defined(MNT2_GEN_OPT_DETACH) */
error = UNMOUNT_TRAP(mp_save->mnt);
+
+ /* Linux kernel can be sluggish for some reason */
+ if (error == EBUSY && retries--) {
+ struct timespec tm = {0, 200000000};
+ nanosleep(&tm, NULL);
+ goto again;
+ }
+
if (error < 0) {
plog(XLOG_WARNING, "unmount(%s) failed: %m", mp_save->mnt->mnt_dir);
switch ((error = errno)) {

View File

@ -0,0 +1,82 @@
am-utils-6.2-1.git.e03592f0 - fix debug log deadlock
From: Ian Kent <raven@themaw.net>
It's possible (and likely) a SIGCHLD signal can arrive while in syslog(2)
and also attempt log log a message leading to deadlock.
---
libamu/xutil.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/libamu/xutil.c b/libamu/xutil.c
index b3e3a0f..0d9d2ec 100644
--- a/libamu/xutil.c
+++ b/libamu/xutil.c
@@ -420,14 +420,33 @@ debug_option(char *opt)
void
dplog(const char *fmt, ...)
{
+#ifdef HAVE_SIGACTION
+ sigset_t old, chld;
+#else /* not HAVE_SIGACTION */
+ int mask;
+#endif /* not HAVE_SIGACTION */
va_list ap;
+#ifdef HAVE_SIGACTION
+ sigemptyset(&chld);
+ sigaddset(&chld, SIGCHLD);
+#else /* not HAVE_SIGACTION */
+ mask = sigblock(sigmask(SIGCHLD));
+#endif /* not HAVE_SIGACTION */
+
+ sigprocmask(SIG_BLOCK, &chld, &old);
if (!logfp)
logfp = stderr; /* initialize before possible first use */
va_start(ap, fmt);
real_plog(XLOG_DEBUG, fmt, ap);
va_end(ap);
+
+#ifdef HAVE_SIGACTION
+ sigprocmask(SIG_SETMASK, &old, NULL);
+#else /* not HAVE_SIGACTION */
+ mask = sigblock(sigmask(SIGCHLD));
+#endif /* not HAVE_SIGACTION */
}
#endif /* DEBUG */
@@ -435,14 +454,33 @@ dplog(const char *fmt, ...)
void
plog(int lvl, const char *fmt, ...)
{
+#ifdef HAVE_SIGACTION
+ sigset_t old, chld;
+#else /* not HAVE_SIGACTION */
+ int mask;
+#endif /* not HAVE_SIGACTION */
va_list ap;
+#ifdef HAVE_SIGACTION
+ sigemptyset(&chld);
+ sigaddset(&chld, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &chld, &old);
+#else /* not HAVE_SIGACTION */
+ mask = sigblock(sigmask(SIGCHLD));
+#endif /* not HAVE_SIGACTION */
+
if (!logfp)
logfp = stderr; /* initialize before possible first use */
va_start(ap, fmt);
real_plog(lvl, fmt, ap);
va_end(ap);
+
+#ifdef HAVE_SIGACTION
+ sigprocmask(SIG_SETMASK, &old, NULL);
+#else /* not HAVE_SIGACTION */
+ sigsetmask(mask);
+#endif /* not HAVE_SIGACTION */
}

View File

@ -0,0 +1,22 @@
am-utils-6.2-1.git.e03592f0 - fix get_nfs_version() message
From: Ian Kent <ikent@redhat.com>
Fix a error message formating mistake in get_nfs_version().
---
conf/transp/transp_sockets.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/conf/transp/transp_sockets.c b/conf/transp/transp_sockets.c
index d5e729f..5036b26 100644
--- a/conf/transp/transp_sockets.c
+++ b/conf/transp/transp_sockets.c
@@ -478,7 +478,7 @@ try_again:
}
if (errstr) {
- plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s%s",
+ plog(XLOG_INFO, "get_nfs_version NFS(%d,%s) failed for %s: %s",
(int) nfs_version, proto, host, errstr);
if (again) {
#ifdef HAVE_FS_NFS3

View File

@ -0,0 +1,152 @@
diff -up am-utils-6.1.5/amd/map.c.orig am-utils-6.1.5/amd/map.c
--- am-utils-6.1.5/amd/map.c.orig 2014-03-19 19:34:23.000000000 +0800
+++ am-utils-6.1.5/amd/map.c 2014-03-19 19:44:17.918101095 +0800
@@ -687,68 +687,80 @@ make_root_node(void)
void
umount_exported(void)
{
- int i;
+ int i, work_done;
- for (i = last_used_map; i >= 0; --i) {
- am_node *mp = exported_ap[i];
- mntfs *mf;
+ do {
+ work_done = 0;
- if (!mp)
- continue;
+ for (i = last_used_map; i >= 0; --i) {
+ am_node *mp = exported_ap[i];
+ mntfs *mf;
- mf = mp->am_mnt;
- if (mf->mf_flags & MFF_UNMOUNTING) {
- /*
- * If this node is being unmounted then just ignore it. However,
- * this could prevent amd from finishing if the unmount gets blocked
- * since the am_node will never be free'd. am_unmounted needs
- * telling about this possibility. - XXX
- */
- continue;
- }
+ if (!mp)
+ continue;
- if (!(mf->mf_fsflags & FS_DIRECTORY))
/*
- * When shutting down this had better
- * look like a directory, otherwise it
- * can't be unmounted!
+ * Wait for children to be removed first
*/
- mk_fattr(&mp->am_fattr, NFDIR);
+ if (mp->am_child)
+ continue;
- if ((--immediate_abort < 0 &&
- !(mp->am_flags & AMF_ROOT) && mp->am_parent) ||
- (mf->mf_flags & MFF_RESTART)) {
+ mf = mp->am_mnt;
+ if (mf->mf_flags & MFF_UNMOUNTING) {
+ /*
+ * If this node is being unmounted then just ignore it. However,
+ * this could prevent amd from finishing if the unmount gets blocked
+ * since the am_node will never be free'd. am_unmounted needs
+ * telling about this possibility. - XXX
+ */
+ continue;
+ }
- /*
- * Just throw this node away without bothering to unmount it. If
- * the server is not known to be up then don't discard the mounted
- * on directory or Amd might hang...
- */
- if (mf->mf_server &&
+ if (!(mf->mf_fsflags & FS_DIRECTORY))
+ /*
+ * When shutting down this had better
+ * look like a directory, otherwise it
+ * can't be unmounted!
+ */
+ mk_fattr(&mp->am_fattr, NFDIR);
+
+ if ((--immediate_abort < 0 &&
+ !(mp->am_flags & AMF_ROOT) && mp->am_parent) ||
+ (mf->mf_flags & MFF_RESTART)) {
+
+ work_done++;
+
+ /*
+ * Just throw this node away without bothering to unmount it. If
+ * the server is not known to be up then don't discard the mounted
+ * on directory or Amd might hang...
+ */
+ if (mf->mf_server &&
(mf->mf_server->fs_flags & (FSF_DOWN | FSF_VALID)) != FSF_VALID)
mf->mf_flags &= ~MFF_MKMNT;
- if (gopt.flags & CFM_UNMOUNT_ON_EXIT || mp->am_flags & AMF_AUTOFS) {
- plog(XLOG_INFO, "on-exit attempt to unmount %s", mf->mf_mount);
- /*
- * use unmount_mp, not unmount_node, so that unmounts be
- * backgrounded as needed.
- */
- unmount_mp((opaque_t) mp);
- } else {
- am_unmounted(mp);
- }
- exported_ap[i] = 0;
- } else {
- /*
- * Any other node gets forcibly timed out.
- */
- mp->am_flags &= ~AMF_NOTIMEOUT;
- mp->am_mnt->mf_flags &= ~MFF_RSTKEEP;
- mp->am_ttl = 0;
- mp->am_timeo = 1;
- mp->am_timeo_w = 0;
- }
- }
+ if (gopt.flags & CFM_UNMOUNT_ON_EXIT || mp->am_flags & AMF_AUTOFS) {
+ plog(XLOG_INFO, "on-exit attempt to unmount %s", mf->mf_mount);
+ /*
+ * use unmount_mp, not unmount_node, so that unmounts be
+ * backgrounded as needed.
+ */
+ unmount_mp((opaque_t) mp);
+ } else {
+ am_unmounted(mp);
+ }
+ exported_ap[i] = NULL;
+ } else {
+ /*
+ * Any other node gets forcibly timed out.
+ */
+ mp->am_flags &= ~AMF_NOTIMEOUT;
+ mp->am_mnt->mf_flags &= ~MFF_RSTKEEP;
+ mp->am_ttl = 0;
+ mp->am_timeo = 1;
+ mp->am_timeo_w = 0;
+ }
+ }
+ } while (work_done);
}
diff -U0 am-utils-6.1.5/ChangeLog.orig am-utils-6.1.5/ChangeLog
--- am-utils-6.1.5/ChangeLog.orig 2006-05-12 01:25:47.000000000 +0800
+++ am-utils-6.1.5/ChangeLog 2014-03-19 19:36:27.335598581 +0800
@@ -0,0 +1,12 @@
+2009-12-10 Christos Zoulas <christos@zoulas.com>
+
+ * Make sure to remove nodes in the proper order when going
+ down. Depending on what order the nodes got created it's
+ possible that the parent of a node has a bigger am_mapno
+ (index in exported_ap[]) so that it gets freed before
+ its child while the child's am_parent pointer is still
+ pointing to the already freed block of memory.
+ This change makes sure that umount_exported() cleans up
+ all children of a node first before freeing the node.
+ From: Krisztian Kovacs <Kris.Kovacs@morganstanley.com>
+

View File

@ -1,7 +1,7 @@
Summary: Automount utilities including an updated version of Amd
Name: am-utils
Version: 6.1.5
Release: 29%{?dist}
Release: 30%{?dist}
License: BSD
Epoch: 5
Group: System Environment/Daemons
@ -59,6 +59,17 @@ Patch8: am-utils-6.1.5-use-_hardened_build-flag.patch
# Fix documentation build fails.
Patch9: am-utils-6.1.5-texinfo-documentation-build-fixes.patch
Patch10: am-utils-6.1.5-dont-background-autofs-umount.patch
Patch11: am-utils-6.1.5-check-fh-on-umount-succeeded.patch
Patch12: am-utils-6.1.5-handle-ENOENT-umount-return-for-autofs-mounts.patch
Patch13: am-utils-6.2-1.git.e03592f0-fix-get_nfs_version-message.patch
Patch14: am-utils-6.2-1.git.e03592f0-fix-debug-log-deadlock.patch
Patch15: am-utils-6.2-0.git.9b652fb4-linux-umount-wait-on-ebusy.patch
Patch16: am-utils-6.2-make-sure-to-remove-nodes-in-the-proper-order-when-going-down.patch
Patch17: am-utils-6.2-0.git.9b652fb4-fix-handle-failed-umount-on-exit.patch
# Don't attempt to use v5 protocol
Patch18: am-utils-6.1.5-fix-autofs-proto-version-define.patch
%global _hardened_build 1
# We need to filter out some perl requirements for now.
@ -88,6 +99,15 @@ mounting and unmounting filesystems.
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1
find_requires=%{old_find_requires}
echo "$find_requires | grep -v lostaltmail.conf" > find-requires
@ -199,6 +219,18 @@ fi
%{_libdir}/libamu.so*
%changelog
* Fri Mar 20 2014 Ian Kent <ikent@redhat.com> - 5:6.1.5-30
- bz1074376 - am-utils will no longer start due to missing NFSv2
- dont background autofs umount.
- check fh on umount succeeded.
- handle ENOENT umount return for autofs mounts.
- fix get_nfs_version() message.
- fix debug log deadlock.
- linux umount wait on ebusy.
- make sure to remove nodes in the proper order when going down.
- fix handle failed umount on exit.
- fix autofs proto version define.
* Sat Aug 03 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 5:6.1.5-29
- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild