On Fri, 19 Nov 2004, Jeff Moyer wrote:
> Hi, Ian, list,
>
> In my proposed fix, I meant to say:
>
> We could expire the cache in lookup_ghost, and then go ahead and only
> insert new entries (instead of overwriting what was there).
>
> So, I've implemented this, though it isn't tested just yet. There were
> some other bugs.
>
> In lookup_multi, we iterate through each map's lookup_ghost function. The
> problem here is that you will end up doing the following:
>
> static int read_map(const char *root, struct lookup_context *ctxt)
> {
> char key[KEY_MAX_LEN + 1];
> char mapent[MAPENT_MAX_LEN + 1];
> char *mapname;
> FILE *f;
> int entry;
> time_t age = time(NULL); <=================
>
> mapname = alloca(strlen(ctxt->mapname) + 6);
> sprintf(mapname, "file:%s", ctxt->mapname);
>
> f = fopen(ctxt->mapname, "r");
> if (!f) {
> error(MODPREFIX "could not open map file %s", ctxt->mapname);
> return 0;
> }
>
> while(1) {
> entry = read_one(f, key, mapent);
> if (entry)
> cache_update(root, key, mapent, age); <==========
>
> if (feof(f))
> break;
> }
>
> fclose(f);
>
> /* Clean stale entries from the cache */
> cache_clean(root, age); <=============
>
> return 1;
> }
>
> Notice the lines I've pointed out. We decide what the expiration age
> should be at the beginning of the function. We update entries and give
> them that "age." And finally, we expire all entries that were made prior
> to that. The problem arises in that we call the read_map routine for each
> map in the list in order. What will happen is that each map, as it is
> processed, will end up with a new value for age. Thus, we expire all of
> the work done by the previous read_maps! This is bad. To fix this, I've
> passed in the age field from the top-level.
>
> I've changed ldap's lookup_ghost routine (well, a function it calls,
> anyway) to use cache_insert_unique instead of cache_add.
>
> Please let me know what you think. If you only like some parts, let me
> know which ones and I'll break them out from the rest of the patch. BTW,
> this patch is applied on top of your map expiration changes. I can rediff
> the thing to any version of the code you want.
Understand the problem.
I've had a look at the patch and it looks good.
I had a slightly different idea though.
I think the cache_insert_unique might be a problem later as if people add
multiple attributes (map entries) for multi-mount keys, instead of one
attribute containing multiple mounts, in what they think is "the LDAP way"
it probably won't work. I can't say we've seen this problem yet but I have
been trying to allow for it in the code.
The other thing that occured to me was that, together with passing the
time to keep things consistent, processing the maps in reverse order in
lookup_ghost of the multi map module would fix most of the issues. Along
with modifying cache_add to append to any existing entries, rather than
prepend.
I spotted something you missed in the yp module. Have a look at the
lookup_yp patch chunks in the attached map-entry-order patch.
Have a look at what I've tried to do and let me know what you think. I've
done some basic testing but not against the issue we are trying to fix. So
let me know how it goes.
Also, I found a couple of other bugs and have attached a couple of other
patches as well.
Ian
--- autofs-4.1.3/daemon/automount.c.map-entry-order 2004-11-21
12:55:38.000000000 +0800
+++ autofs-4.1.3/daemon/automount.c 2004-11-21 12:55:39.000000000 +0800
@@ -825,7 +825,7 @@ static int st_readmap(void)
{
int status;
- status = ap.lookup->lookup_ghost(ap.path, ap.ghost, ap.lookup->context);
+ status = ap.lookup->lookup_ghost(ap.path, ap.ghost, 0,
ap.lookup->context);
debug("st_readmap: status %d\n", status);
@@ -1502,7 +1502,7 @@ static void sig_supervisor(int sig)
break;
case SIGHUP:
- ap.lookup->lookup_ghost(ap.path, ap.ghost, ap.lookup->context);
+ ap.lookup->lookup_ghost(ap.path, ap.ghost, 0,
ap.lookup->context);
/* Pass on the reread event and ignore self signal */
kill(0, SIGHUP);
@@ -1520,7 +1520,7 @@ int supervisor(char *path)
ap.path = alloca(strlen(path) + 1);
strcpy(ap.path, path);
- map = ap.lookup->lookup_ghost(ap.path, ap.ghost, ap.lookup->context);
+ map = ap.lookup->lookup_ghost(ap.path, ap.ghost, 0, ap.lookup->context);
if (map & LKP_FAIL) {
error("failed to load map exiting");
cleanup_exit(ap.path, 1);
@@ -1588,7 +1588,7 @@ int handle_mounts(char *path)
alarm(ap.exp_runfreq + my_pid % ap.exp_runfreq);
}
- map = ap.lookup->lookup_ghost(ap.path, ap.ghost, ap.lookup->context);
+ map = ap.lookup->lookup_ghost(ap.path, ap.ghost, 0, ap.lookup->context);
if (map & LKP_FAIL) {
if (map & LKP_INDIRECT) {
error("bad map format: found indirect, "
--- autofs-4.1.3/include/automount.h.map-entry-order 2004-11-21
12:55:37.000000000 +0800
+++ autofs-4.1.3/include/automount.h 2004-11-21 12:55:39.000000000 +0800
@@ -140,12 +140,12 @@ int is_mounted(const char *path);
#ifdef MODULE_LOOKUP
int lookup_init(const char *mapfmt, int argc, const char *const *argv, void
**context);
-int lookup_ghost(const char *, int, void *);
+int lookup_ghost(const char *, int, time_t, void *);
int lookup_mount(const char *, const char *, int, void *);
int lookup_done(void *);
#endif
typedef int (*lookup_init_t) (const char *, int, const char *const *, void **);
-typedef int (*lookup_ghost_t) (const char *, int, void *);
+typedef int (*lookup_ghost_t) (const char *, int, time_t, void *);
typedef int (*lookup_mount_t) (const char *, const char *, int, void *);
typedef int (*lookup_done_t) (void *);
--- autofs-4.1.3/lib/cache.c.map-entry-order 2004-11-21 12:55:37.000000000
+0800
+++ autofs-4.1.3/lib/cache.c 2004-11-21 12:58:08.000000000 +0800
@@ -165,7 +165,7 @@ struct mapent_cache *cache_partial_match
int cache_add(const char *root, const char *key, const char *mapent, time_t
age)
{
- struct mapent_cache *me = NULL;
+ struct mapent_cache *me = NULL, *existing = NULL;
char *pkey, *pent;
unsigned int hashval = hash(key);
char *path;
@@ -191,8 +191,27 @@ int cache_add(const char *root, const ch
me->mapent = strcpy(pent, mapent);
me->age = age;
- me->next = mapent_hash[hashval];
- mapent_hash[hashval] = me;
+ /*
+ * We need to add to the end if values exist in order to
+ * preserve the order in which the map was read on lookup.
+ */
+ existing = cache_lookup(key);
+ if (!existing) {
+ me->next = mapent_hash[hashval];
+ mapent_hash[hashval] = me;
+ } else {
+ while (1) {
+ struct mapent_cache *next;
+
+ next = cache_lookup_next(existing);
+ if (!next)
+ break;
+
+ existing = next;
+ }
+ me->next = existing->next;
+ existing->next = me;
+ }
return CHE_OK;
}
--- autofs-4.1.3/modules/lookup_file.c.map-entry-order 2004-11-21
12:55:38.000000000 +0800
+++ autofs-4.1.3/modules/lookup_file.c 2004-11-21 12:55:39.000000000 +0800
@@ -227,14 +227,14 @@ static int read_one(FILE *f, char *key,
return 0;
}
-static int read_map(const char *root, struct lookup_context *ctxt)
+static int read_map(const char *root, time_t now, struct lookup_context *ctxt)
{
char key[KEY_MAX_LEN + 1];
char mapent[MAPENT_MAX_LEN + 1];
char *mapname;
FILE *f;
int entry;
- time_t age = time(NULL);
+ time_t age = now ? now : time(NULL);
mapname = alloca(strlen(ctxt->mapname) + 6);
sprintf(mapname, "file:%s", ctxt->mapname);
@@ -262,14 +262,14 @@ static int read_map(const char *root, st
return 1;
}
-int lookup_ghost(const char *root, int ghost, void *context)
+int lookup_ghost(const char *root, int ghost, time_t now, void *context)
{
struct lookup_context *ctxt = (struct lookup_context *) context;
struct mapent_cache *me;
struct stat st;
int status = 1;
- if (!read_map(root, ctxt))
+ if (!read_map(root, now, ctxt))
return LKP_FAIL;
if (stat(ctxt->mapname, &st)) {
--- autofs-4.1.3/modules/lookup_hesiod.c.map-entry-order 2004-11-21
12:55:37.000000000 +0800
+++ autofs-4.1.3/modules/lookup_hesiod.c 2004-11-21 12:55:39.000000000
+0800
@@ -66,7 +66,7 @@ int lookup_init(const char *mapfmt, int
return !(ctxt->parser = open_parse(mapfmt, MODPREFIX, argc - 1, argv +
1));
}
-int lookup_ghost(const char *root, int ghost, void *context)
+int lookup_ghost(const char *root, int ghost, time_t now, void *context)
{
return LKP_NOTSUP;
}
--- autofs-4.1.3/modules/lookup_ldap.c.map-entry-order 2004-11-21
12:55:38.000000000 +0800
+++ autofs-4.1.3/modules/lookup_ldap.c 2004-11-21 12:55:39.000000000 +0800
@@ -174,10 +174,9 @@ static int read_one_map(const char *root
const char *class, char *key,
const char *keyval, int keyvallen, char *type,
struct lookup_context *ctxt,
- int *result_ldap)
+ time_t age, int *result_ldap)
{
int rv, i, l, count;
- time_t age = time(NULL);
char *query;
LDAPMessage *result, *e;
char **keyValue = NULL;
@@ -280,17 +279,16 @@ static int read_one_map(const char *root
}
static int read_map(const char *root, struct lookup_context *ctxt,
- const char *key, int keyvallen, int *result_ldap)
+ const char *key, int keyvallen, time_t age, int
*result_ldap)
{
- time_t age = time(NULL);
int rv = LDAP_SUCCESS;
/* all else fails read entire map */
if (!read_one_map(root, "nisObject", "cn",
- key, keyvallen, "nisMapEntry", ctxt, &rv)) {
+ key, keyvallen, "nisMapEntry", ctxt, age, &rv)) {
if ((rv != LDAP_SUCCESS) ||
!read_one_map(root, "automount", "cn", key, keyvallen,
- "automountInformation", ctxt, &rv)) {
+ "automountInformation", ctxt, age, &rv)) {
if (result_ldap != NULL)
*result_ldap = rv;
return 0;
@@ -303,16 +301,17 @@ static int read_map(const char *root, st
return 1;
}
-int lookup_ghost(const char *root, int ghost, void *context)
+int lookup_ghost(const char *root, int ghost, time_t now, void *context)
{
struct lookup_context *ctxt = (struct lookup_context *) context;
struct mapent_cache *me;
int status = 1, rv = LDAP_SUCCESS;
char *mapname;
+ time_t age = now ? now : time(NULL);
chdir("/");
- if (!read_map(root, ctxt, NULL, 0, &rv))
+ if (!read_map(root, ctxt, NULL, 0, age, &rv))
switch (rv) {
case LDAP_SIZELIMIT_EXCEEDED:
case LDAP_UNWILLING_TO_PERFORM:
--- autofs-4.1.3/modules/lookup_multi.c.map-entry-order 2004-11-21
12:55:38.000000000 +0800
+++ autofs-4.1.3/modules/lookup_multi.c 2004-11-21 12:55:39.000000000 +0800
@@ -111,13 +111,17 @@ int lookup_init(const char *my_mapfmt, i
return 1;
}
-int lookup_ghost(const char *root, int ghost, void *context)
+int lookup_ghost(const char *root, int ghost, time_t now, void *context)
{
struct lookup_context *ctxt = (struct lookup_context *) context;
int i, ret, at_least_1 = 0;
- for (i = 0; i < ctxt->n; i++) {
- ret = ctxt->m[i].mod->lookup_ghost(root, ghost,
+ /*
+ * Read each map in reverse order to ensure that when we lookup a key
+ * in the cache we get what would be seen first.
+ */
+ for (i = ctxt->n - 1; i >= 0 ; i--) {
+ ret = ctxt->m[i].mod->lookup_ghost(root, ghost, now,
ctxt->m[i].mod->context);
if (ret & LKP_FAIL)
continue;
--- autofs-4.1.3/modules/lookup_nisplus.c.map-entry-order 2004-01-30
00:01:22.000000000 +0800
+++ autofs-4.1.3/modules/lookup_nisplus.c 2004-11-21 12:55:39.000000000
+0800
@@ -59,7 +59,7 @@ int lookup_init(const char *mapfmt, int
return !(ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv +
1));
}
-int lookup_ghost(const char *root, int ghost, void *context)
+int lookup_ghost(const char *root, int ghost, time_t now, void *context)
{
return LKP_NOTSUP;
}
--- autofs-4.1.3/modules/lookup_program.c.map-entry-order 2004-11-21
12:55:38.000000000 +0800
+++ autofs-4.1.3/modules/lookup_program.c 2004-11-21 12:55:39.000000000
+0800
@@ -76,7 +76,7 @@ int lookup_init(const char *mapfmt, int
return !(ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv +
1));
}
-int lookup_ghost(const char *root, int ghost, void *context)
+int lookup_ghost(const char *root, int ghost, time_t now, void *context)
{
return LKP_NOTSUP;
}
--- autofs-4.1.3/modules/lookup_userhome.c.map-entry-order 2004-01-30
00:01:22.000000000 +0800
+++ autofs-4.1.3/modules/lookup_userhome.c 2004-11-21 12:55:39.000000000
+0800
@@ -36,7 +36,7 @@ int lookup_init(const char *mapfmt, int
return 0; /* Nothing to do */
}
-int lookup_ghost(const char *root, int ghost, void *context)
+int lookup_ghost(const char *root, int ghost, time_t now, void *context)
{
return LKP_NOTSUP;
}
--- autofs-4.1.3/modules/lookup_yp.c.map-entry-order 2004-11-21
12:55:37.000000000 +0800
+++ autofs-4.1.3/modules/lookup_yp.c 2004-11-21 12:55:39.000000000 +0800
@@ -44,16 +44,8 @@ struct lookup_context {
};
struct callback_data {
- int status;
- int map;
const char *root;
- char direct_base[KEY_MAX_LEN + 1];
- const char *name;
- int name_len;
- unsigned long type;
- const char *mapname;
time_t age;
- struct lookup_context *context;
};
int lookup_version = AUTOFS_LOOKUP_VERSION; /* Required by protocol */
@@ -93,8 +85,9 @@ int lookup_init(const char *mapfmt, int
int yp_all_callback(int status, char *ypkey, int ypkeylen,
char *val, int vallen, char *ypcb_data)
{
- time_t age = time(NULL);
- char *root = ypcb_data;
+ struct callback_data *cbdata = (struct callback_data *) ypcb_data;
+ char *root = cbdata->root;
+ time_t age = cbdata->age;
char *key;
char *mapent;
@@ -114,15 +107,18 @@ int yp_all_callback(int status, char *yp
return 0;
}
-static int read_map(const char *root, struct lookup_context *context)
+static int read_map(const char *root, time_t age, struct lookup_context
*context)
{
struct lookup_context *ctxt = (struct lookup_context *) context;
struct ypall_callback ypcb;
- time_t age = time(NULL);
+ struct callback_data ypcb_data;
int err;
+ ypcb_data.root = root;
+ ypcb_data.age = age;
+
ypcb.foreach = yp_all_callback;
- ypcb.data = (char *) root;
+ ypcb.data = (char *) &ypcb_data;
err = yp_all((char *) ctxt->domainname, (char *) ctxt->mapname, &ypcb);
@@ -138,13 +134,14 @@ static int read_map(const char *root, st
return 1;
}
-int lookup_ghost(const char *root, int ghost, void *context)
+int lookup_ghost(const char *root, int ghost, time_t now, void *context)
{
struct lookup_context *ctxt = (struct lookup_context *) context;
+ time_t age = now ? now : time(NULL);
struct mapent_cache *me;
int status = 1;
- if (!read_map(root, ctxt))
+ if (!read_map(root, age, ctxt))
return LKP_FAIL;
status = cache_ghost(root, ghost, ctxt->mapname, "yp", ctxt->parse);
--- autofs-4.1.3/modules/lookup_yp.c.direct-lookup 2004-11-21
16:29:49.000000000 +0800
+++ autofs-4.1.3/modules/lookup_yp.c 2004-11-21 16:30:26.000000000 +0800
@@ -235,7 +235,7 @@ int lookup_mount(const char *root, const
return 1;
/* check map and if change is detected re-read map */
- ret = lookup_one(root, name, name_len, ctxt);
+ ret = lookup_one(root, key, key_len, ctxt);
debug("ret = %d", ret);
--- autofs-4.1.3/modules/lookup_file.c.map-expiry-fix 2004-11-21
21:35:52.000000000 +0800
+++ autofs-4.1.3/modules/lookup_file.c 2004-11-21 21:37:08.000000000 +0800
@@ -323,8 +323,10 @@ static int lookup_one(const char *root,
while(1) {
entry = read_one(f, mkey, mapent);
if (entry)
- if (strncmp(mkey, key, key_len) == 0)
+ if (strncmp(mkey, key, key_len) == 0) {
+ fclose(f);
return cache_update(root, key, mapent, age);
+ }
if (feof(f))
break;
_______________________________________________
autofs mailing list
[EMAIL PROTECTED]
http://linux.kernel.org/mailman/listinfo/autofs