|
|
23b4c9 |
autofs-5.1.2 - add ref counting to struct map_source
|
|
|
23b4c9 |
|
|
|
23b4c9 |
From: Ian Kent <raven@themaw.net>
|
|
|
23b4c9 |
|
|
|
23b4c9 |
amd map format maps that are type "auto" frequently refer to the
|
|
|
23b4c9 |
current map in their map entries.
|
|
|
23b4c9 |
|
|
|
23b4c9 |
While this isn't a problem for relatively small maps it can be very
|
|
|
23b4c9 |
wasteful for large maps and even more so for maps that have multi-
|
|
|
23b4c9 |
component keys that trigger type "auto" mounts as they progress down
|
|
|
23b4c9 |
the directory tree.
|
|
|
23b4c9 |
|
|
|
23b4c9 |
So add a reference count in order for amd type "auto" mounts to use
|
|
|
23b4c9 |
the parent map if it matches.
|
|
|
23b4c9 |
|
|
|
23b4c9 |
sun format maps are much less likley to use the same map and if they
|
|
|
23b4c9 |
do they are usually trivial, one line maps, so it isn't a problem.
|
|
|
23b4c9 |
|
|
|
23b4c9 |
But, more importantly, sun format maps need to track recursive inclusion
|
|
|
23b4c9 |
and inclusion depth for a given map source when plus map inclusion is
|
|
|
23b4c9 |
used which prevents the map soucre from being shared.
|
|
|
23b4c9 |
|
|
|
23b4c9 |
Signed-off-by: Ian Kent <raven@themaw.net>
|
|
|
23b4c9 |
---
|
|
|
23b4c9 |
CHANGELOG | 1
|
|
|
23b4c9 |
daemon/indirect.c | 7 ++++-
|
|
|
23b4c9 |
include/master.h | 3 ++
|
|
|
23b4c9 |
lib/master.c | 22 +++++++++++++++++
|
|
|
23b4c9 |
modules/mount_autofs.c | 60 ++++++++++++++++++++++++++++++++-----------------
|
|
|
23b4c9 |
5 files changed, 72 insertions(+), 21 deletions(-)
|
|
|
23b4c9 |
|
|
|
23b4c9 |
--- autofs-5.0.7.orig/CHANGELOG
|
|
|
23b4c9 |
+++ autofs-5.0.7/CHANGELOG
|
|
|
23b4c9 |
@@ -223,6 +223,7 @@
|
|
|
23b4c9 |
- fix argc off by one in mount_autofs.c.
|
|
|
23b4c9 |
- fix _strncmp() usage.
|
|
|
23b4c9 |
- fix typos in README.amd-maps.
|
|
|
23b4c9 |
+- add ref counting to struct map_source.
|
|
|
23b4c9 |
|
|
|
23b4c9 |
25/07/2012 autofs-5.0.7
|
|
|
23b4c9 |
=======================
|
|
|
23b4c9 |
--- autofs-5.0.7.orig/daemon/indirect.c
|
|
|
23b4c9 |
+++ autofs-5.0.7/daemon/indirect.c
|
|
|
23b4c9 |
@@ -96,7 +96,12 @@ static int do_mount_autofs_indirect(stru
|
|
|
23b4c9 |
struct mnt_list *mnts;
|
|
|
23b4c9 |
int ret;
|
|
|
23b4c9 |
|
|
|
23b4c9 |
- ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
|
|
|
23b4c9 |
+ /* If the map is being shared the exp_timeout can't be inherited
|
|
|
23b4c9 |
+ * from the map source since it may be different so the autofs
|
|
|
23b4c9 |
+ * point exp_runfreq must have already been set.
|
|
|
23b4c9 |
+ */
|
|
|
23b4c9 |
+ if (ap->entry->maps->ref <= 1)
|
|
|
23b4c9 |
+ ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
|
|
|
23b4c9 |
|
|
|
23b4c9 |
if (ops->version && !do_force_unlink) {
|
|
|
23b4c9 |
ap->flags |= MOUNT_FLAG_REMOUNT;
|
|
|
23b4c9 |
--- autofs-5.0.7.orig/include/master.h
|
|
|
23b4c9 |
+++ autofs-5.0.7/include/master.h
|
|
|
23b4c9 |
@@ -23,6 +23,7 @@
|
|
|
23b4c9 |
#define MAP_FLAG_FORMAT_AMD 0x0001
|
|
|
23b4c9 |
|
|
|
23b4c9 |
struct map_source {
|
|
|
23b4c9 |
+ unsigned int ref;
|
|
|
23b4c9 |
unsigned int flags;
|
|
|
23b4c9 |
char *type;
|
|
|
23b4c9 |
char *format;
|
|
|
23b4c9 |
@@ -89,6 +90,8 @@ struct map_source *
|
|
|
23b4c9 |
master_add_map_source(struct master_mapent *, char *, char *, time_t, int, const char **);
|
|
|
23b4c9 |
struct map_source *
|
|
|
23b4c9 |
master_find_map_source(struct master_mapent *, const char *, const char *, int, const char **);
|
|
|
23b4c9 |
+struct map_source *
|
|
|
23b4c9 |
+master_get_map_source(struct master_mapent *, const char *, const char *, int, const char **);
|
|
|
23b4c9 |
void master_free_map_source(struct map_source *, unsigned int);
|
|
|
23b4c9 |
struct map_source *
|
|
|
23b4c9 |
master_find_source_instance(struct map_source *, const char *, const char *, int, const char **);
|
|
|
23b4c9 |
--- autofs-5.0.7.orig/lib/master.c
|
|
|
23b4c9 |
+++ autofs-5.0.7/lib/master.c
|
|
|
23b4c9 |
@@ -180,6 +180,7 @@ master_add_map_source(struct master_mape
|
|
|
23b4c9 |
if (!source)
|
|
|
23b4c9 |
return NULL;
|
|
|
23b4c9 |
memset(source, 0, sizeof(struct map_source));
|
|
|
23b4c9 |
+ source->ref = 1;
|
|
|
23b4c9 |
|
|
|
23b4c9 |
if (type) {
|
|
|
23b4c9 |
ntype = strdup(type);
|
|
|
23b4c9 |
@@ -231,6 +232,8 @@ master_add_map_source(struct master_mape
|
|
|
23b4c9 |
|
|
|
23b4c9 |
this = __master_find_map_source(entry, type, format, argc, tmpargv);
|
|
|
23b4c9 |
if (this) {
|
|
|
23b4c9 |
+ error(entry->ap->logopt,
|
|
|
23b4c9 |
+ "map source used without taking reference");
|
|
|
23b4c9 |
this->age = age;
|
|
|
23b4c9 |
master_free_map_source(source, 0);
|
|
|
23b4c9 |
master_source_unlock(entry);
|
|
|
23b4c9 |
@@ -329,8 +332,27 @@ struct map_source *master_find_map_sourc
|
|
|
23b4c9 |
return source;
|
|
|
23b4c9 |
}
|
|
|
23b4c9 |
|
|
|
23b4c9 |
+struct map_source *
|
|
|
23b4c9 |
+master_get_map_source(struct master_mapent *entry,
|
|
|
23b4c9 |
+ const char *type, const char *format,
|
|
|
23b4c9 |
+ int argc, const char **argv)
|
|
|
23b4c9 |
+{
|
|
|
23b4c9 |
+ struct map_source *source = NULL;
|
|
|
23b4c9 |
+
|
|
|
23b4c9 |
+ master_source_readlock(entry);
|
|
|
23b4c9 |
+ source = __master_find_map_source(entry, type, format, argc, argv);
|
|
|
23b4c9 |
+ if (source)
|
|
|
23b4c9 |
+ source->ref++;
|
|
|
23b4c9 |
+ master_source_unlock(entry);
|
|
|
23b4c9 |
+
|
|
|
23b4c9 |
+ return source;
|
|
|
23b4c9 |
+}
|
|
|
23b4c9 |
+
|
|
|
23b4c9 |
static void __master_free_map_source(struct map_source *source, unsigned int free_cache)
|
|
|
23b4c9 |
{
|
|
|
23b4c9 |
+ /* instance map sources are not ref counted */
|
|
|
23b4c9 |
+ if (source->ref && --source->ref)
|
|
|
23b4c9 |
+ return;
|
|
|
23b4c9 |
if (source->type)
|
|
|
23b4c9 |
free(source->type);
|
|
|
23b4c9 |
if (source->format)
|
|
|
23b4c9 |
--- autofs-5.0.7.orig/modules/mount_autofs.c
|
|
|
23b4c9 |
+++ autofs-5.0.7/modules/mount_autofs.c
|
|
|
23b4c9 |
@@ -208,18 +208,37 @@ int mount_mount(struct autofs_point *ap,
|
|
|
23b4c9 |
}
|
|
|
23b4c9 |
if (info->map)
|
|
|
23b4c9 |
argv[0] = info->map;
|
|
|
23b4c9 |
+
|
|
|
23b4c9 |
+ if (options) {
|
|
|
23b4c9 |
+ p = options;
|
|
|
23b4c9 |
+ while ((p = strchr(p, ',')) != NULL) {
|
|
|
23b4c9 |
+ if (*p == ',') {
|
|
|
23b4c9 |
+ *p = '\0';
|
|
|
23b4c9 |
+ p++;
|
|
|
23b4c9 |
+ }
|
|
|
23b4c9 |
+ argv[argc++] = p;
|
|
|
23b4c9 |
+ }
|
|
|
23b4c9 |
+ }
|
|
|
23b4c9 |
+ argv[argc] = NULL;
|
|
|
23b4c9 |
+
|
|
|
23b4c9 |
/*
|
|
|
23b4c9 |
- * If the parent map format is amd and the format isn't
|
|
|
23b4c9 |
- * specified in the map entry set it from the parent map
|
|
|
23b4c9 |
- * source.
|
|
|
23b4c9 |
+ * For amd type "auto" the map is often re-used so check
|
|
|
23b4c9 |
+ * if the the parent map can be used and use it if it
|
|
|
23b4c9 |
+ * matches.
|
|
|
23b4c9 |
+ *
|
|
|
23b4c9 |
+ * Also if the parent map format is amd and the format
|
|
|
23b4c9 |
+ * isn't specified in the map entry set it from the parent
|
|
|
23b4c9 |
+ * map source.
|
|
|
23b4c9 |
*/
|
|
|
23b4c9 |
- if (!info->format && ap->entry->maps) {
|
|
|
23b4c9 |
+ source = NULL;
|
|
|
23b4c9 |
+ if (ap->entry->maps && ap->entry->maps->flags & MAP_FLAG_FORMAT_AMD) {
|
|
|
23b4c9 |
struct map_source *s = ap->entry->maps;
|
|
|
23b4c9 |
+
|
|
|
23b4c9 |
/*
|
|
|
23b4c9 |
* For amd maps, if the format and source type aren't
|
|
|
23b4c9 |
* specified try and set them from the parent.
|
|
|
23b4c9 |
*/
|
|
|
23b4c9 |
- if (s->flags & MAP_FLAG_FORMAT_AMD) {
|
|
|
23b4c9 |
+ if (!info->format) {
|
|
|
23b4c9 |
info->format = strdup("amd");
|
|
|
23b4c9 |
if (!info->format)
|
|
|
23b4c9 |
warn(ap->logopt, MODPREFIX
|
|
|
23b4c9 |
@@ -231,23 +250,18 @@ int mount_mount(struct autofs_point *ap,
|
|
|
23b4c9 |
"failed to set amd map type");
|
|
|
23b4c9 |
}
|
|
|
23b4c9 |
}
|
|
|
23b4c9 |
- }
|
|
|
23b4c9 |
|
|
|
23b4c9 |
- if (options) {
|
|
|
23b4c9 |
- p = options;
|
|
|
23b4c9 |
- while ((p = strchr(p, ',')) != NULL) {
|
|
|
23b4c9 |
- if (*p == ',') {
|
|
|
23b4c9 |
- *p = '\0';
|
|
|
23b4c9 |
- p++;
|
|
|
23b4c9 |
- }
|
|
|
23b4c9 |
- argv[argc++] = p;
|
|
|
23b4c9 |
- }
|
|
|
23b4c9 |
+ source = master_get_map_source(ap->entry,
|
|
|
23b4c9 |
+ info->type, info->format,
|
|
|
23b4c9 |
+ argc, argv);
|
|
|
23b4c9 |
+ if (source)
|
|
|
23b4c9 |
+ entry->maps = source;
|
|
|
23b4c9 |
}
|
|
|
23b4c9 |
- argv[argc] = NULL;
|
|
|
23b4c9 |
|
|
|
23b4c9 |
- source = master_add_map_source(entry,
|
|
|
23b4c9 |
- info->type, info->format,
|
|
|
23b4c9 |
- time(NULL), argc, argv);
|
|
|
23b4c9 |
+ if (!source)
|
|
|
23b4c9 |
+ source = master_add_map_source(entry,
|
|
|
23b4c9 |
+ info->type, info->format,
|
|
|
23b4c9 |
+ time(NULL), argc, argv);
|
|
|
23b4c9 |
if (!source) {
|
|
|
23b4c9 |
error(ap->logopt,
|
|
|
23b4c9 |
MODPREFIX "failed to add map source to entry");
|
|
|
23b4c9 |
@@ -256,7 +270,13 @@ int mount_mount(struct autofs_point *ap,
|
|
|
23b4c9 |
return 1;
|
|
|
23b4c9 |
}
|
|
|
23b4c9 |
free_map_type_info(info);
|
|
|
23b4c9 |
- source->exp_timeout = timeout;
|
|
|
23b4c9 |
+ /* The exp_timeout can't be inherited if the map is shared, so
|
|
|
23b4c9 |
+ * the autofs point exp_runfreq must be set here.
|
|
|
23b4c9 |
+ */
|
|
|
23b4c9 |
+ if (source->ref <= 1)
|
|
|
23b4c9 |
+ source->exp_timeout = timeout;
|
|
|
23b4c9 |
+ else
|
|
|
23b4c9 |
+ nap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
|
|
|
23b4c9 |
|
|
|
23b4c9 |
mounts_mutex_lock(ap);
|
|
|
23b4c9 |
|