On Mon, Jan 19, 2009 at 11:24 PM, Ian Kent <[email protected]> wrote:
autofs tries to not load an entire map into the internal cache unless it
> has to. For maps that do get loaded into the cache it relies on checks to
> work out if a map is up to date in order to trigger a map read. This is
> fine for maps that can do direct key lookups but file maps need to do a
> linear search through the file when locating an entry for a key. For large
> maps this can be a huge overhead. This patch make autofs always load file
> based maps at start and makes use of the map file mtime to discover if the
> cache needs to be refreshed.
> ---
>
> daemon/lookup.c | 9 +++++--
> modules/lookup_file.c | 59
> +++++++++++++++++--------------------------------
> 2 files changed, 27 insertions(+), 41 deletions(-)
>
> diff --git a/daemon/lookup.c b/daemon/lookup.c
> index 741d846..e034348 100644
> --- a/daemon/lookup.c
> +++ b/daemon/lookup.c
> @@ -283,10 +283,13 @@ static int do_read_map(struct autofs_point *ap,
> struct map_source *map, time_t a
> * for the fail cases to function correctly and to cache the
> * lookup handle.
> *
> - * We always need to whole map for direct mounts in order to
> - * mount the triggers.
> + * We always need to read the whole map for direct mounts in
> + * order to mount the triggers. We also want to read the whole
> + * map if it's a file map to avoid potentially lengthy linear
> + * file scanning.
> */
> - if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT)
> + if (strcmp(map->type, "file") &&
> + !(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT)
> return NSS_STATUS_SUCCESS;
>
> if (!map->stale)
> diff --git a/modules/lookup_file.c b/modules/lookup_file.c
> index 95b9f6f..7672725 100644
> --- a/modules/lookup_file.c
> +++ b/modules/lookup_file.c
> @@ -44,7 +44,6 @@ typedef enum { esc_none, esc_char, esc_val, esc_all }
> ESCAPES;
>
> struct lookup_context {
> const char *mapname;
> - time_t mtime;
> struct parse_mod *parse;
> };
>
> @@ -54,7 +53,6 @@ int lookup_init(const char *mapfmt, int argc, const char
> *const *argv, void **co
> {
> struct lookup_context *ctxt;
> char buf[MAX_ERR_BUF];
> - struct stat st;
>
> *context = NULL;
>
> @@ -87,15 +85,6 @@ int lookup_init(const char *mapfmt, int argc, const char
> *const *argv, void **co
> return 1;
> }
>
> - if (stat(ctxt->mapname, &st)) {
> - free(ctxt);
> - logmsg(MODPREFIX "file map %s, could not stat",
> - argv[0]);
> - return 1;
> - }
> -
> - ctxt->mtime = st.st_mtime;
> -
> if (!mapfmt)
> mapfmt = MAPFMT_DEFAULT;
>
> @@ -391,7 +380,6 @@ int lookup_read_master(struct master *master, time_t
> age, void *context)
> int blen;
> char *path;
> char *ent;
> - struct stat st;
> FILE *f;
> int fd;
You should be able to get rid of `fd' and the fileno(3) call now.
unsigned int path_len, ent_len;
> @@ -504,13 +492,6 @@ int lookup_read_master(struct master *master, time_t
> age, void *context)
> break;
> }
>
> - if (fstat(fd, &st)) {
> - crit(logopt, MODPREFIX "file map %s, could not stat",
> - ctxt->mapname);
> - return NSS_STATUS_UNAVAIL;
> - }
> - ctxt->mtime = st.st_mtime;
> -
> fclose(f);
>
> return NSS_STATUS_SUCCESS;
> @@ -642,7 +623,6 @@ int lookup_read_map(struct autofs_point *ap, time_t
> age, void *context)
> struct mapent_cache *mc;
> char *key;
> char *mapent;
> - struct stat st;
> FILE *f;
> int fd;
You should be able to get rid of `fd' and the fileno(3) call now.
unsigned int k_len, m_len;
> @@ -748,13 +728,6 @@ int lookup_read_map(struct autofs_point *ap, time_t
> age, void *context)
> break;
> }
>
> - if (fstat(fd, &st)) {
> - crit(ap->logopt,
> - MODPREFIX "file map %s, could not stat",
> - ctxt->mapname);
> - return NSS_STATUS_UNAVAIL;
> - }
> - ctxt->mtime = st.st_mtime;
> source->age = age;
>
> fclose(f);
> @@ -951,9 +924,6 @@ static int check_map_indirect(struct autofs_point *ap,
> if (ret == CHE_FAIL)
> return NSS_STATUS_NOTFOUND;
>
> - if (ret & CHE_UPDATED)
> - source->stale = 1;
> -
> pthread_cleanup_push(cache_lock_cleanup, mc);
> cache_writelock(mc);
> exists = cache_lookup_distinct(mc, key);
> @@ -963,7 +933,6 @@ static int check_map_indirect(struct autofs_point *ap,
> free(exists->mapent);
> exists->mapent = NULL;
> exists->status = 0;
> - source->stale = 1;
> }
> }
> pthread_cleanup_pop(1);
> @@ -985,14 +954,8 @@ static int check_map_indirect(struct autofs_point *ap,
> we = cache_lookup_distinct(mc, "*");
> if (we) {
> /* Wildcard entry existed and is now gone */
> - if (we->source == source && (wild & CHE_MISSING)) {
> + if (we->source == source && (wild & CHE_MISSING))
> cache_delete(mc, "*");
> - source->stale = 1;
> - }
> - } else {
> - /* Wildcard not in map but now is */
> - if (wild & (CHE_OK | CHE_UPDATED))
> - source->stale = 1;
> }
> pthread_cleanup_pop(1);
>
> @@ -1062,9 +1025,28 @@ int lookup_mount(struct autofs_point *ap, const char
> *name, int name_len, void *
> * we never know about it.
> */
> if (ap->type == LKP_INDIRECT && *key != '/') {
> + struct stat st;
> char *lkp_key;
>
> + /*
> + * We can skip the map lookup and cache update altogether
> + * if we know the map hasn't been modified since it was
> + * last read. If it has then we can mark the map stale
> + * so a re-read is triggered following the lookup.
> + */
> + if (stat(ctxt->mapname, &st)) {
> + error(ap->logopt, MODPREFIX
> + "file map %s, could not stat",
> ctxt->mapname);
> + return NSS_STATUS_UNAVAIL;
> + }
> +
> cache_readlock(mc);
> + me = cache_lookup_first(mc);
> + if (me && st.st_mtime <= me->age)
> + goto do_cache_lookup;
> + else
> + source->stale = 1;
Perhaps some output for debugging purposes wouldn't go astray?
+
> me = cache_lookup_distinct(mc, key);
> if (me && me->multi)
> lkp_key = strdup(me->multi->key);
> @@ -1088,6 +1070,7 @@ int lookup_mount(struct autofs_point *ap, const char
> *name, int name_len, void *
> }
>
> cache_readlock(mc);
> +do_cache_lookup:
> me = cache_lookup(mc, key);
> /* Stale mapent => check for entry in alternate source or wildcard
> */
> if (me && !me->mapent) {
>
>
_______________________________________________
autofs mailing list
[email protected]
http://linux.kernel.org/mailman/listinfo/autofs