|
|
9a499a |
autofs-5.1.7 - fix direct mount deadlock
|
|
|
9a499a |
|
|
|
9a499a |
From: Ian Kent <raven@themaw.net>
|
|
|
9a499a |
|
|
|
9a499a |
When umounting direct mounts at exit or when umounting mounts no
|
|
|
9a499a |
longer in the map on re-load a deadlock can occur.
|
|
|
9a499a |
|
|
|
9a499a |
Signed-off-by: Ian Kent <raven@themaw.net>
|
|
|
9a499a |
---
|
|
|
9a499a |
CHANGELOG | 1 +
|
|
|
9a499a |
daemon/direct.c | 22 +++++++++++++++++++++-
|
|
|
9a499a |
daemon/state.c | 14 +++++++++-----
|
|
|
9a499a |
3 files changed, 31 insertions(+), 6 deletions(-)
|
|
|
9a499a |
|
|
|
9a499a |
--- autofs-5.1.4.orig/CHANGELOG
|
|
|
9a499a |
+++ autofs-5.1.4/CHANGELOG
|
|
|
9a499a |
@@ -72,6 +72,7 @@
|
|
|
9a499a |
- use mapent tree root for tree_mapent_add_node().
|
|
|
9a499a |
- eliminate redundant cache lookup in tree_mapent_add_node().
|
|
|
9a499a |
- fix hosts map offset order.
|
|
|
9a499a |
+- fix direct mount deadlock.
|
|
|
9a499a |
|
|
|
9a499a |
xx/xx/2018 autofs-5.1.5
|
|
|
9a499a |
- fix flag file permission.
|
|
|
9a499a |
--- autofs-5.1.4.orig/daemon/direct.c
|
|
|
9a499a |
+++ autofs-5.1.4/daemon/direct.c
|
|
|
9a499a |
@@ -84,11 +84,27 @@ static void mnts_cleanup(void *arg)
|
|
|
9a499a |
int do_umount_autofs_direct(struct autofs_point *ap, struct mapent *me)
|
|
|
9a499a |
{
|
|
|
9a499a |
struct ioctl_ops *ops = get_ioctl_ops();
|
|
|
9a499a |
+ struct mapent_cache *mc = me->mc;
|
|
|
9a499a |
char buf[MAX_ERR_BUF];
|
|
|
9a499a |
int ioctlfd = -1, rv, left, retries;
|
|
|
9a499a |
+ char key[PATH_MAX + 1];
|
|
|
9a499a |
+ struct mapent *tmp;
|
|
|
9a499a |
int opened = 0;
|
|
|
9a499a |
|
|
|
9a499a |
- left = umount_multi(ap, me->key, 0);
|
|
|
9a499a |
+ if (me->len > PATH_MAX) {
|
|
|
9a499a |
+ error(ap->logopt, "path too long");
|
|
|
9a499a |
+ return 1;
|
|
|
9a499a |
+ }
|
|
|
9a499a |
+ strcpy(key, me->key);
|
|
|
9a499a |
+
|
|
|
9a499a |
+ cache_unlock(mc);
|
|
|
9a499a |
+ left = umount_multi(ap, key, 0);
|
|
|
9a499a |
+ cache_readlock(mc);
|
|
|
9a499a |
+ tmp = cache_lookup_distinct(mc, key);
|
|
|
9a499a |
+ if (tmp != me) {
|
|
|
9a499a |
+ error(ap->logopt, "key %s no longer in mapent cache", key);
|
|
|
9a499a |
+ return -1;
|
|
|
9a499a |
+ }
|
|
|
9a499a |
if (left) {
|
|
|
9a499a |
warn(ap->logopt, "could not unmount %d dirs under %s",
|
|
|
9a499a |
left, me->key);
|
|
|
9a499a |
@@ -213,6 +229,7 @@ int umount_autofs_direct(struct autofs_p
|
|
|
9a499a |
mc = map->mc;
|
|
|
9a499a |
pthread_cleanup_push(cache_lock_cleanup, mc);
|
|
|
9a499a |
cache_readlock(mc);
|
|
|
9a499a |
+restart:
|
|
|
9a499a |
me = cache_enumerate(mc, NULL);
|
|
|
9a499a |
while (me) {
|
|
|
9a499a |
int error;
|
|
|
9a499a |
@@ -230,6 +247,9 @@ int umount_autofs_direct(struct autofs_p
|
|
|
9a499a |
* failed umount.
|
|
|
9a499a |
*/
|
|
|
9a499a |
error = do_umount_autofs_direct(ap, me);
|
|
|
9a499a |
+ /* cache became invalid, restart */
|
|
|
9a499a |
+ if (error == -1)
|
|
|
9a499a |
+ goto restart;
|
|
|
9a499a |
if (!error)
|
|
|
9a499a |
goto done;
|
|
|
9a499a |
|
|
|
9a499a |
--- autofs-5.1.4.orig/daemon/state.c
|
|
|
9a499a |
+++ autofs-5.1.4/daemon/state.c
|
|
|
9a499a |
@@ -348,11 +348,12 @@ static void do_readmap_cleanup(void *arg
|
|
|
9a499a |
return;
|
|
|
9a499a |
}
|
|
|
9a499a |
|
|
|
9a499a |
-static void do_readmap_mount(struct autofs_point *ap,
|
|
|
9a499a |
+static int do_readmap_mount(struct autofs_point *ap,
|
|
|
9a499a |
struct map_source *map, struct mapent *me, time_t now)
|
|
|
9a499a |
{
|
|
|
9a499a |
struct mapent_cache *nc;
|
|
|
9a499a |
struct mapent *ne, *nested, *valid;
|
|
|
9a499a |
+ int ret = 0;
|
|
|
9a499a |
|
|
|
9a499a |
nc = ap->entry->master->nc;
|
|
|
9a499a |
|
|
|
9a499a |
@@ -411,7 +412,7 @@ static void do_readmap_mount(struct auto
|
|
|
9a499a |
cache_unlock(vmc);
|
|
|
9a499a |
error(ap->logopt,
|
|
|
9a499a |
"failed to find expected existing valid map entry");
|
|
|
9a499a |
- return;
|
|
|
9a499a |
+ return ret;
|
|
|
9a499a |
}
|
|
|
9a499a |
/* Take over the mount if there is one */
|
|
|
9a499a |
valid->ioctlfd = me->ioctlfd;
|
|
|
9a499a |
@@ -430,14 +431,14 @@ static void do_readmap_mount(struct auto
|
|
|
9a499a |
ap->exp_runfreq = runfreq;
|
|
|
9a499a |
}
|
|
|
9a499a |
} else if (!is_mounted(me->key, MNTS_REAL))
|
|
|
9a499a |
- do_umount_autofs_direct(ap, me);
|
|
|
9a499a |
+ ret = do_umount_autofs_direct(ap, me);
|
|
|
9a499a |
else
|
|
|
9a499a |
debug(ap->logopt,
|
|
|
9a499a |
"%s is mounted", me->key);
|
|
|
9a499a |
} else
|
|
|
9a499a |
do_mount_autofs_direct(ap, me, get_exp_timeout(ap, map));
|
|
|
9a499a |
|
|
|
9a499a |
- return;
|
|
|
9a499a |
+ return ret;
|
|
|
9a499a |
}
|
|
|
9a499a |
|
|
|
9a499a |
static void *do_readmap(void *arg)
|
|
|
9a499a |
@@ -504,9 +505,12 @@ static void *do_readmap(void *arg)
|
|
|
9a499a |
mc = map->mc;
|
|
|
9a499a |
pthread_cleanup_push(cache_lock_cleanup, mc);
|
|
|
9a499a |
cache_readlock(mc);
|
|
|
9a499a |
+restart:
|
|
|
9a499a |
me = cache_enumerate(mc, NULL);
|
|
|
9a499a |
while (me) {
|
|
|
9a499a |
- do_readmap_mount(ap, map, me, now);
|
|
|
9a499a |
+ int ret = do_readmap_mount(ap, map, me, now);
|
|
|
9a499a |
+ if (ret == -1)
|
|
|
9a499a |
+ goto restart;
|
|
|
9a499a |
me = cache_enumerate(mc, me);
|
|
|
9a499a |
}
|
|
|
9a499a |
lookup_prune_one_cache(ap, map->mc, now);
|