|
|
29d2b9 |
autofs-5.1.7 - eliminate clean_stale_multi_triggers()
|
|
|
29d2b9 |
|
|
|
29d2b9 |
From: Ian Kent <raven@themaw.net>
|
|
|
29d2b9 |
|
|
|
29d2b9 |
Eliminate clean_stale_multi_triggers() by checking for stale offsets at
|
|
|
29d2b9 |
the time mount_subtree() is called.
|
|
|
29d2b9 |
|
|
|
29d2b9 |
This should result in the same behaviour but eliminate an additional
|
|
|
29d2b9 |
seperate traversal of the offset list.
|
|
|
29d2b9 |
|
|
|
29d2b9 |
Signed-off-by: Ian Kent <raven@themaw.net>
|
|
|
29d2b9 |
---
|
|
|
29d2b9 |
CHANGELOG | 1
|
|
|
29d2b9 |
lib/mounts.c | 209 ++++++++++-----------------------------------------
|
|
|
29d2b9 |
modules/parse_sun.c | 10 --
|
|
|
29d2b9 |
3 files changed, 43 insertions(+), 177 deletions(-)
|
|
|
29d2b9 |
|
|
|
29d2b9 |
diff --git a/CHANGELOG b/CHANGELOG
|
|
|
29d2b9 |
index 5a3bedc1..b1ce7b69 100644
|
|
|
29d2b9 |
--- a/CHANGELOG
|
|
|
29d2b9 |
+++ b/CHANGELOG
|
|
|
29d2b9 |
@@ -12,6 +12,7 @@
|
|
|
29d2b9 |
- remove redundant variables from mount_autofs_offset().
|
|
|
29d2b9 |
- remove unused parameter form do_mount_autofs_offset().
|
|
|
29d2b9 |
- refactor umount_multi_triggers().
|
|
|
29d2b9 |
+- eliminate clean_stale_multi_triggers().
|
|
|
29d2b9 |
|
|
|
29d2b9 |
25/01/2021 autofs-5.1.7
|
|
|
29d2b9 |
- make bind mounts propagation slave by default.
|
|
|
29d2b9 |
diff --git a/lib/mounts.c b/lib/mounts.c
|
|
|
29d2b9 |
index 5268ba5b..a9abbebf 100644
|
|
|
29d2b9 |
--- a/lib/mounts.c
|
|
|
29d2b9 |
+++ b/lib/mounts.c
|
|
|
29d2b9 |
@@ -2601,10 +2601,44 @@ static int do_umount_offset(struct autofs_point *ap, struct mapent *oe, const ch
|
|
|
29d2b9 |
oe_base = oe->key + strlen(root);
|
|
|
29d2b9 |
left += do_umount_multi_triggers(ap, oe, root, oe_base);
|
|
|
29d2b9 |
|
|
|
29d2b9 |
+ /*
|
|
|
29d2b9 |
+ * If an offset that has an active mount has been removed
|
|
|
29d2b9 |
+ * from the multi-mount we don't want to attempt to trigger
|
|
|
29d2b9 |
+ * mounts for it. Obviously this is because it has been
|
|
|
29d2b9 |
+ * removed, but less obvious is the potential strange
|
|
|
29d2b9 |
+ * behaviour that can result if we do try and mount it
|
|
|
29d2b9 |
+ * again after it's been expired. For example, if an NFS
|
|
|
29d2b9 |
+ * file system is no longer exported and is later umounted
|
|
|
29d2b9 |
+ * it can be mounted again without any error message but
|
|
|
29d2b9 |
+ * shows as an empty directory. That's going to confuse
|
|
|
29d2b9 |
+ * people for sure.
|
|
|
29d2b9 |
+ *
|
|
|
29d2b9 |
+ * If the mount cannot be umounted (the process is now
|
|
|
29d2b9 |
+ * using a stale mount) the offset needs to be invalidated
|
|
|
29d2b9 |
+ * so no further mounts will be attempted but the offset
|
|
|
29d2b9 |
+ * cache entry must remain so expires can continue to
|
|
|
29d2b9 |
+ * attempt to umount it. If the mount can be umounted and
|
|
|
29d2b9 |
+ * the offset is removed, at least for NFS we will get
|
|
|
29d2b9 |
+ * ESTALE errors when attempting list the directory.
|
|
|
29d2b9 |
+ */
|
|
|
29d2b9 |
if (oe->ioctlfd != -1 ||
|
|
|
29d2b9 |
is_mounted(oe->key, MNTS_REAL)) {
|
|
|
29d2b9 |
- left++;
|
|
|
29d2b9 |
- return left;
|
|
|
29d2b9 |
+ if (umount_ent(ap, oe->key) &&
|
|
|
29d2b9 |
+ is_mounted(oe->key, MNTS_REAL)) {
|
|
|
29d2b9 |
+ debug(ap->logopt,
|
|
|
29d2b9 |
+ "offset %s has active mount, invalidate",
|
|
|
29d2b9 |
+ oe->key);
|
|
|
29d2b9 |
+ /*
|
|
|
29d2b9 |
+ * Ok, so we shouldn't modify the mapent but
|
|
|
29d2b9 |
+ * mount requests are blocked at a point above
|
|
|
29d2b9 |
+ * this and expire only uses the mapent key.
|
|
|
29d2b9 |
+ */
|
|
|
29d2b9 |
+ if (oe->mapent) {
|
|
|
29d2b9 |
+ free(oe->mapent);
|
|
|
29d2b9 |
+ oe->mapent = NULL;
|
|
|
29d2b9 |
+ }
|
|
|
29d2b9 |
+ return ++left;
|
|
|
29d2b9 |
+ }
|
|
|
29d2b9 |
}
|
|
|
29d2b9 |
|
|
|
29d2b9 |
debug(ap->logopt, "umount offset %s", oe->key);
|
|
|
29d2b9 |
@@ -2666,6 +2700,11 @@ int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
|
|
|
29d2b9 |
oe = cache_lookup_distinct(me->mc, key);
|
|
|
29d2b9 |
if (!oe || !oe->mapent)
|
|
|
29d2b9 |
goto cont;
|
|
|
29d2b9 |
+ if (oe->age != me->multi->age) {
|
|
|
29d2b9 |
+ /* Best effort */
|
|
|
29d2b9 |
+ do_umount_offset(ap, oe, root);
|
|
|
29d2b9 |
+ goto cont;
|
|
|
29d2b9 |
+ }
|
|
|
29d2b9 |
|
|
|
29d2b9 |
mounted += do_mount_autofs_offset(ap, oe, root);
|
|
|
29d2b9 |
|
|
|
29d2b9 |
@@ -2725,169 +2764,3 @@ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root
|
|
|
29d2b9 |
|
|
|
29d2b9 |
return left;
|
|
|
29d2b9 |
}
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
-int clean_stale_multi_triggers(struct autofs_point *ap,
|
|
|
29d2b9 |
- struct mapent *me, char *top, const char *base)
|
|
|
29d2b9 |
-{
|
|
|
29d2b9 |
- char *root;
|
|
|
29d2b9 |
- char mm_top[PATH_MAX + 1];
|
|
|
29d2b9 |
- char path[PATH_MAX + 1];
|
|
|
29d2b9 |
- char *offset;
|
|
|
29d2b9 |
- struct mapent *oe;
|
|
|
29d2b9 |
- struct list_head *mm_root, *pos;
|
|
|
29d2b9 |
- const char o_root[] = "/";
|
|
|
29d2b9 |
- const char *mm_base;
|
|
|
29d2b9 |
- int left, start;
|
|
|
29d2b9 |
- unsigned int root_len;
|
|
|
29d2b9 |
- unsigned int mm_base_len;
|
|
|
29d2b9 |
- time_t age;
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- if (top)
|
|
|
29d2b9 |
- root = top;
|
|
|
29d2b9 |
- else {
|
|
|
29d2b9 |
- if (!strchr(me->multi->key, '/'))
|
|
|
29d2b9 |
- /* Indirect multi-mount root */
|
|
|
29d2b9 |
- /* sprintf okay - if it's mounted, it's
|
|
|
29d2b9 |
- * PATH_MAX or less bytes */
|
|
|
29d2b9 |
- sprintf(mm_top, "%s/%s", ap->path, me->multi->key);
|
|
|
29d2b9 |
- else
|
|
|
29d2b9 |
- strcpy(mm_top, me->multi->key);
|
|
|
29d2b9 |
- root = mm_top;
|
|
|
29d2b9 |
- }
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- left = 0;
|
|
|
29d2b9 |
- start = strlen(root);
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- mm_root = &me->multi->multi_list;
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- if (!base)
|
|
|
29d2b9 |
- mm_base = o_root;
|
|
|
29d2b9 |
- else
|
|
|
29d2b9 |
- mm_base = base;
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- pos = NULL;
|
|
|
29d2b9 |
- offset = path;
|
|
|
29d2b9 |
- root_len = start;
|
|
|
29d2b9 |
- mm_base_len = strlen(mm_base);
|
|
|
29d2b9 |
- age = me->multi->age;
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
|
|
|
29d2b9 |
- char key[PATH_MAX + 1];
|
|
|
29d2b9 |
- int key_len = root_len + strlen(offset);
|
|
|
29d2b9 |
- char *oe_base;
|
|
|
29d2b9 |
- int ret;
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- if (mm_base_len > 1)
|
|
|
29d2b9 |
- key_len += mm_base_len;
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- if (key_len > PATH_MAX) {
|
|
|
29d2b9 |
- warn(ap->logopt, "path loo long");
|
|
|
29d2b9 |
- continue;
|
|
|
29d2b9 |
- }
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- strcpy(key, root);
|
|
|
29d2b9 |
- if (mm_base_len > 1)
|
|
|
29d2b9 |
- strcat(key, mm_base);
|
|
|
29d2b9 |
- strcat(key, offset);
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- oe = cache_lookup_distinct(me->mc, key);
|
|
|
29d2b9 |
- /* root offset is a special case */
|
|
|
29d2b9 |
- if (!oe || (strlen(oe->key) - start) == 1)
|
|
|
29d2b9 |
- continue;
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- /* Check for and umount stale subtree offsets */
|
|
|
29d2b9 |
- oe_base = oe->key + strlen(root);
|
|
|
29d2b9 |
- ret = clean_stale_multi_triggers(ap, oe, root, oe_base);
|
|
|
29d2b9 |
- left += ret;
|
|
|
29d2b9 |
- if (ret)
|
|
|
29d2b9 |
- continue;
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- if (oe->age == age)
|
|
|
29d2b9 |
- continue;
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- /*
|
|
|
29d2b9 |
- * If an offset that has an active mount has been removed
|
|
|
29d2b9 |
- * from the multi-mount we don't want to attempt to trigger
|
|
|
29d2b9 |
- * mounts for it. Obviously this is because it has been
|
|
|
29d2b9 |
- * removed, but less obvious is the potential strange
|
|
|
29d2b9 |
- * behaviour that can result if we do try and mount it
|
|
|
29d2b9 |
- * again after it's been expired. For example, if an NFS
|
|
|
29d2b9 |
- * file system is no longer exported and is later umounted
|
|
|
29d2b9 |
- * it can be mounted again without any error message but
|
|
|
29d2b9 |
- * shows as an empty directory. That's going to confuse
|
|
|
29d2b9 |
- * people for sure.
|
|
|
29d2b9 |
- *
|
|
|
29d2b9 |
- * If the mount cannot be umounted (the process is now
|
|
|
29d2b9 |
- * using a stale mount) the offset needs to be invalidated
|
|
|
29d2b9 |
- * so no further mounts will be attempted but the offset
|
|
|
29d2b9 |
- * cache entry must remain so expires can continue to
|
|
|
29d2b9 |
- * attempt to umount it. If the mount can be umounted and
|
|
|
29d2b9 |
- * the offset is removed, at least for NFS we will get
|
|
|
29d2b9 |
- * ESTALE errors when attempting list the directory.
|
|
|
29d2b9 |
- */
|
|
|
29d2b9 |
- if (oe->ioctlfd != -1 ||
|
|
|
29d2b9 |
- is_mounted(oe->key, MNTS_REAL)) {
|
|
|
29d2b9 |
- if (umount_ent(ap, oe->key) &&
|
|
|
29d2b9 |
- is_mounted(oe->key, MNTS_REAL)) {
|
|
|
29d2b9 |
- debug(ap->logopt,
|
|
|
29d2b9 |
- "offset %s has active mount, invalidate",
|
|
|
29d2b9 |
- oe->key);
|
|
|
29d2b9 |
- if (oe->mapent) {
|
|
|
29d2b9 |
- free(oe->mapent);
|
|
|
29d2b9 |
- oe->mapent = NULL;
|
|
|
29d2b9 |
- }
|
|
|
29d2b9 |
- left++;
|
|
|
29d2b9 |
- continue;
|
|
|
29d2b9 |
- }
|
|
|
29d2b9 |
- }
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- debug(ap->logopt, "umount offset %s", oe->key);
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- if (umount_autofs_offset(ap, oe)) {
|
|
|
29d2b9 |
- warn(ap->logopt, "failed to umount offset %s", key);
|
|
|
29d2b9 |
- left++;
|
|
|
29d2b9 |
- } else {
|
|
|
29d2b9 |
- struct stat st;
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- /* Mount point not ours to delete ? */
|
|
|
29d2b9 |
- if (!(oe->flags & MOUNT_FLAG_DIR_CREATED)) {
|
|
|
29d2b9 |
- debug(ap->logopt, "delete offset key %s", key);
|
|
|
29d2b9 |
- if (cache_delete_offset(oe->mc, key) == CHE_FAIL)
|
|
|
29d2b9 |
- error(ap->logopt,
|
|
|
29d2b9 |
- "failed to delete offset key %s", key);
|
|
|
29d2b9 |
- continue;
|
|
|
29d2b9 |
- }
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- /*
|
|
|
29d2b9 |
- * An error due to partial directory removal is
|
|
|
29d2b9 |
- * ok so only try and remount the offset if the
|
|
|
29d2b9 |
- * actual mount point still exists.
|
|
|
29d2b9 |
- */
|
|
|
29d2b9 |
- ret = rmdir_path_offset(ap, oe);
|
|
|
29d2b9 |
- if (ret == -1 && !stat(oe->key, &st)) {
|
|
|
29d2b9 |
- ret = do_mount_autofs_offset(ap, oe, root);
|
|
|
29d2b9 |
- if (ret) {
|
|
|
29d2b9 |
- left++;
|
|
|
29d2b9 |
- /* But we did origianlly create this */
|
|
|
29d2b9 |
- oe->flags |= MOUNT_FLAG_DIR_CREATED;
|
|
|
29d2b9 |
- continue;
|
|
|
29d2b9 |
- }
|
|
|
29d2b9 |
- /*
|
|
|
29d2b9 |
- * Fall through if the trigger can't be mounted
|
|
|
29d2b9 |
- * again, since there is no offset there can't
|
|
|
29d2b9 |
- * be any mount requests so remove the map
|
|
|
29d2b9 |
- * entry from the cache. There's now a dead
|
|
|
29d2b9 |
- * offset mount, but what else can we do ....
|
|
|
29d2b9 |
- */
|
|
|
29d2b9 |
- }
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- debug(ap->logopt, "delete offset key %s", key);
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- if (cache_delete_offset(oe->mc, key) == CHE_FAIL)
|
|
|
29d2b9 |
- error(ap->logopt,
|
|
|
29d2b9 |
- "failed to delete offset key %s", key);
|
|
|
29d2b9 |
- }
|
|
|
29d2b9 |
- }
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
- return left;
|
|
|
29d2b9 |
-}
|
|
|
29d2b9 |
diff --git a/modules/parse_sun.c b/modules/parse_sun.c
|
|
|
29d2b9 |
index f42af7b7..f4d5125c 100644
|
|
|
29d2b9 |
--- a/modules/parse_sun.c
|
|
|
29d2b9 |
+++ b/modules/parse_sun.c
|
|
|
29d2b9 |
@@ -1176,7 +1176,7 @@ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
|
|
|
29d2b9 |
|
|
|
29d2b9 |
/* Mount root offset if it exists */
|
|
|
29d2b9 |
ro = cache_lookup_distinct(me->mc, key);
|
|
|
29d2b9 |
- if (ro) {
|
|
|
29d2b9 |
+ if (ro && ro->age == me->multi->age) {
|
|
|
29d2b9 |
char *myoptions, *ro_loc;
|
|
|
29d2b9 |
int namelen = name ? strlen(name) : 0;
|
|
|
29d2b9 |
int ro_len;
|
|
|
29d2b9 |
@@ -1610,14 +1610,6 @@ dont_expand:
|
|
|
29d2b9 |
free(myoptions);
|
|
|
29d2b9 |
} while (*p == '/' || (*p == '"' && *(p + 1) == '/'));
|
|
|
29d2b9 |
|
|
|
29d2b9 |
- /*
|
|
|
29d2b9 |
- * We've got the ordered list of multi-mount entries so go
|
|
|
29d2b9 |
- * through and remove any stale entries if this is the top
|
|
|
29d2b9 |
- * of the multi-mount and set the parent entry of each.
|
|
|
29d2b9 |
- */
|
|
|
29d2b9 |
- if (me == me->multi)
|
|
|
29d2b9 |
- clean_stale_multi_triggers(ap, me, NULL, NULL);
|
|
|
29d2b9 |
-
|
|
|
29d2b9 |
rv = mount_subtree(ap, me, name, NULL, options, ctxt);
|
|
|
29d2b9 |
|
|
|
29d2b9 |
cache_multi_unlock(me);
|