|
|
019928 |
autofs-5.1.1 - always set direct mounts catatonic at exit
|
|
|
019928 |
|
|
|
019928 |
From: Ian Kent <raven@themaw.net>
|
|
|
019928 |
|
|
|
019928 |
Direct mounts are all mounted at application start or when the map
|
|
|
019928 |
is re-read and entries have been added.
|
|
|
019928 |
|
|
|
019928 |
They are only ever umounted at application exit or when the map is
|
|
|
019928 |
re-read and entries have been removed.
|
|
|
019928 |
|
|
|
019928 |
If these mounts are in use (so that they are not umounted) and aren't
|
|
|
019928 |
set catatonic at exit and an application attempts to access the path
|
|
|
019928 |
it will lead to a hang as there is no daemon to answer the mount
|
|
|
019928 |
request.
|
|
|
019928 |
|
|
|
019928 |
It's questionable whether to set busy direct mounts catatonic when
|
|
|
019928 |
attempting to umount them when re-reading the map as the mount may
|
|
|
019928 |
then expire leaving an unresponsive direct mount trigger that hasn't
|
|
|
019928 |
yet been cleaned from the map entry cache.
|
|
|
019928 |
|
|
|
019928 |
Signed-off-by: Ian Kent <raven@themaw.net>
|
|
|
019928 |
---
|
|
|
019928 |
CHANGELOG | 1
|
|
|
019928 |
daemon/direct.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
|
|
|
019928 |
2 files changed, 92 insertions(+), 8 deletions(-)
|
|
|
019928 |
|
|
|
019928 |
--- autofs-5.0.7.orig/CHANGELOG
|
|
|
019928 |
+++ autofs-5.0.7/CHANGELOG
|
|
|
019928 |
@@ -186,6 +186,7 @@
|
|
|
019928 |
- add remote-fs.target systemd dependency.
|
|
|
019928 |
- gaurd against incorrect umount return.
|
|
|
019928 |
- fix typo in autofs.conf.
|
|
|
019928 |
+- always set direct mounts catatonic at exit.
|
|
|
019928 |
|
|
|
019928 |
25/07/2012 autofs-5.0.7
|
|
|
019928 |
=======================
|
|
|
019928 |
--- autofs-5.0.7.orig/daemon/direct.c
|
|
|
019928 |
+++ autofs-5.0.7/daemon/direct.c
|
|
|
019928 |
@@ -82,6 +82,65 @@ static void mnts_cleanup(void *arg)
|
|
|
019928 |
return;
|
|
|
019928 |
}
|
|
|
019928 |
|
|
|
019928 |
+/* When exiting direct mount triggers must be set catatonic, regardless
|
|
|
019928 |
+ * of whether they are busy on not, to avoid a hang on access once the
|
|
|
019928 |
+ * daemon has gone away.
|
|
|
019928 |
+ */
|
|
|
019928 |
+static int set_direct_mount_catatonic(struct autofs_point *ap, struct mapent *me, int ioctlfd)
|
|
|
019928 |
+{
|
|
|
019928 |
+ struct ioctl_ops *ops = get_ioctl_ops();
|
|
|
019928 |
+ unsigned int opened = 0;
|
|
|
019928 |
+ char buf[MAX_ERR_BUF];
|
|
|
019928 |
+ int fd = -1;
|
|
|
019928 |
+ int error;
|
|
|
019928 |
+
|
|
|
019928 |
+ /* In case the miscellaneous device isn't being used try
|
|
|
019928 |
+ * and use an existing ioctl control fd. In this case if
|
|
|
019928 |
+ * we don't already have an ioctl fd the mount can't be
|
|
|
019928 |
+ * set catatonic if it's covered.
|
|
|
019928 |
+ */
|
|
|
019928 |
+ if (ioctlfd >= 0)
|
|
|
019928 |
+ fd = ioctlfd;
|
|
|
019928 |
+ else if (me->ioctlfd >= 0)
|
|
|
019928 |
+ fd = me->ioctlfd;
|
|
|
019928 |
+ else {
|
|
|
019928 |
+ error = ops->open(ap->logopt, &fd, me->dev, me->key);
|
|
|
019928 |
+ if (error == -1) {
|
|
|
019928 |
+ int err = errno;
|
|
|
019928 |
+ char *estr;
|
|
|
019928 |
+
|
|
|
019928 |
+ estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
|
019928 |
+ error(ap->logopt,
|
|
|
019928 |
+ "failed to open ioctlfd for %s, error: %s",
|
|
|
019928 |
+ me->key, estr);
|
|
|
019928 |
+ return err;
|
|
|
019928 |
+ }
|
|
|
019928 |
+ opened = 1;
|
|
|
019928 |
+ }
|
|
|
019928 |
+
|
|
|
019928 |
+ if (fd >= 0) {
|
|
|
019928 |
+ error = ops->catatonic(ap->logopt, fd);
|
|
|
019928 |
+ if (error == -1) {
|
|
|
019928 |
+ int err = errno;
|
|
|
019928 |
+ char *estr;
|
|
|
019928 |
+
|
|
|
019928 |
+ estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
|
019928 |
+ error(ap->logopt,
|
|
|
019928 |
+ "failed to set %s catatonic, error: %s",
|
|
|
019928 |
+ me->key, estr);
|
|
|
019928 |
+ if (opened)
|
|
|
019928 |
+ ops->close(ap->logopt, fd);
|
|
|
019928 |
+ return err;
|
|
|
019928 |
+ }
|
|
|
019928 |
+ if (opened)
|
|
|
019928 |
+ ops->close(ap->logopt, fd);
|
|
|
019928 |
+ }
|
|
|
019928 |
+
|
|
|
019928 |
+ debug(ap->logopt, "set %s catatonic", me->key);
|
|
|
019928 |
+
|
|
|
019928 |
+ return 0;
|
|
|
019928 |
+}
|
|
|
019928 |
+
|
|
|
019928 |
int do_umount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me)
|
|
|
019928 |
{
|
|
|
019928 |
struct ioctl_ops *ops = get_ioctl_ops();
|
|
|
019928 |
@@ -97,7 +156,8 @@ int do_umount_autofs_direct(struct autof
|
|
|
019928 |
}
|
|
|
019928 |
|
|
|
019928 |
if (me->ioctlfd != -1) {
|
|
|
019928 |
- if (tree_is_mounted(mnts, me->key, MNTS_REAL)) {
|
|
|
019928 |
+ if (ap->state == ST_READMAP &&
|
|
|
019928 |
+ tree_is_mounted(mnts, me->key, MNTS_REAL)) {
|
|
|
019928 |
error(ap->logopt,
|
|
|
019928 |
"attempt to umount busy direct mount %s",
|
|
|
019928 |
me->key);
|
|
|
019928 |
@@ -116,7 +176,12 @@ int do_umount_autofs_direct(struct autof
|
|
|
019928 |
if (rv) {
|
|
|
019928 |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
|
019928 |
error(ap->logopt, "ioctl failed: %s", estr);
|
|
|
019928 |
- if (opened && ioctlfd != -1)
|
|
|
019928 |
+ /* The ioctl failed so this probably won't
|
|
|
019928 |
+ * work either but since we opened it here
|
|
|
019928 |
+ * try anyway. We should set these catatonic
|
|
|
019928 |
+ * too but ....
|
|
|
019928 |
+ */
|
|
|
019928 |
+ if (opened)
|
|
|
019928 |
ops->close(ap->logopt, ioctlfd);
|
|
|
019928 |
return 1;
|
|
|
019928 |
} else if (!status) {
|
|
|
019928 |
@@ -124,18 +189,20 @@ int do_umount_autofs_direct(struct autof
|
|
|
019928 |
error(ap->logopt,
|
|
|
019928 |
"ask umount returned busy for %s",
|
|
|
019928 |
me->key);
|
|
|
019928 |
- if (opened && ioctlfd != -1)
|
|
|
019928 |
+ if (ap->state != ST_READMAP)
|
|
|
019928 |
+ set_direct_mount_catatonic(ap, me, ioctlfd);
|
|
|
019928 |
+ if (opened)
|
|
|
019928 |
ops->close(ap->logopt, ioctlfd);
|
|
|
019928 |
return 1;
|
|
|
019928 |
} else {
|
|
|
019928 |
me->ioctlfd = -1;
|
|
|
019928 |
- ops->catatonic(ap->logopt, ioctlfd);
|
|
|
019928 |
+ set_direct_mount_catatonic(ap, me, ioctlfd);
|
|
|
019928 |
ops->close(ap->logopt, ioctlfd);
|
|
|
019928 |
goto force_umount;
|
|
|
019928 |
}
|
|
|
019928 |
}
|
|
|
019928 |
me->ioctlfd = -1;
|
|
|
019928 |
- ops->catatonic(ap->logopt, ioctlfd);
|
|
|
019928 |
+ set_direct_mount_catatonic(ap, me, ioctlfd);
|
|
|
019928 |
ops->close(ap->logopt, ioctlfd);
|
|
|
019928 |
} else {
|
|
|
019928 |
error(ap->logopt,
|
|
|
019928 |
@@ -212,15 +279,31 @@ int umount_autofs_direct(struct autofs_p
|
|
|
019928 |
cache_readlock(mc);
|
|
|
019928 |
me = cache_enumerate(mc, NULL);
|
|
|
019928 |
while (me) {
|
|
|
019928 |
+ int error;
|
|
|
019928 |
+
|
|
|
019928 |
ne = cache_lookup_distinct(nc, me->key);
|
|
|
019928 |
if (ne && map->master_line > ne->age) {
|
|
|
019928 |
me = cache_enumerate(mc, me);
|
|
|
019928 |
continue;
|
|
|
019928 |
}
|
|
|
019928 |
|
|
|
019928 |
- /* TODO: check return, locking me */
|
|
|
019928 |
- do_umount_autofs_direct(ap, mnts, me);
|
|
|
019928 |
-
|
|
|
019928 |
+ /* The daemon is exiting so ...
|
|
|
019928 |
+ * If we get a fail here we must make our
|
|
|
019928 |
+ * best effort to set the direct mount trigger
|
|
|
019928 |
+ * catatonic regardless of the reason for the
|
|
|
019928 |
+ * failed umount.
|
|
|
019928 |
+ */
|
|
|
019928 |
+ error = do_umount_autofs_direct(ap, mnts, me);
|
|
|
019928 |
+ if (!error)
|
|
|
019928 |
+ goto done;
|
|
|
019928 |
+
|
|
|
019928 |
+ error = set_direct_mount_catatonic(ap, me, me->ioctlfd);
|
|
|
019928 |
+ if (!error)
|
|
|
019928 |
+ goto done;
|
|
|
019928 |
+
|
|
|
019928 |
+ /* We really need to set this, last ditch attempt */
|
|
|
019928 |
+ set_direct_mount_catatonic(ap, me, -1);
|
|
|
019928 |
+done:
|
|
|
019928 |
me = cache_enumerate(mc, me);
|
|
|
019928 |
}
|
|
|
019928 |
pthread_cleanup_pop(1);
|