|
Ian Kent |
cc4062 |
autofs-5.0.5 - fix null cache race
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
From: Ian Kent <raven@themaw.net>
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
The null map entry cache scope is across the entire master map but
|
|
Ian Kent |
cc4062 |
it is used by individual master map entries during master map re-read
|
|
Ian Kent |
cc4062 |
and subsequest updates resulting form it. The current null cache locking
|
|
Ian Kent |
cc4062 |
doesn't properly account for this.
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
To resolve this, when we re-read the master, map we need to block
|
|
Ian Kent |
cc4062 |
access to the null cache until the master map has been read and the
|
|
Ian Kent |
cc4062 |
null cache updated.
|
|
Ian Kent |
cc4062 |
---
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
CHANGELOG | 1 +
|
|
Ian Kent |
cc4062 |
daemon/automount.c | 4 +++-
|
|
Ian Kent |
cc4062 |
include/automount.h | 1 +
|
|
Ian Kent |
cc4062 |
lib/cache.c | 33 ++++++++++++++++++++++++++-------
|
|
Ian Kent |
cc4062 |
lib/master.c | 27 ++++++++++++++++++++-------
|
|
Ian Kent |
cc4062 |
lib/master_parse.y | 5 -----
|
|
Ian Kent |
cc4062 |
6 files changed, 51 insertions(+), 20 deletions(-)
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
--- autofs-5.0.5.orig/CHANGELOG
|
|
Ian Kent |
cc4062 |
+++ autofs-5.0.5/CHANGELOG
|
|
Ian Kent |
cc4062 |
@@ -37,6 +37,7 @@
|
|
Ian Kent |
cc4062 |
- fix wildcard map entry match.
|
|
Ian Kent |
cc4062 |
- fix parse_sun() module init.
|
|
Ian Kent |
cc4062 |
- dont check null cache on expire.
|
|
Ian Kent |
cc4062 |
+- fix null cache race.
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
03/09/2009 autofs-5.0.5
|
|
Ian Kent |
cc4062 |
-----------------------
|
|
Ian Kent |
cc4062 |
--- autofs-5.0.5.orig/daemon/automount.c
|
|
Ian Kent |
cc4062 |
+++ autofs-5.0.5/daemon/automount.c
|
|
Ian Kent |
cc4062 |
@@ -1273,14 +1273,16 @@ static int do_hup_signal(struct master *
|
|
Ian Kent |
cc4062 |
if (status)
|
|
Ian Kent |
cc4062 |
fatal(status);
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
+ master_mutex_lock();
|
|
Ian Kent |
cc4062 |
if (master->reading) {
|
|
Ian Kent |
cc4062 |
status = pthread_mutex_unlock(&mrc.mutex);
|
|
Ian Kent |
cc4062 |
if (status)
|
|
Ian Kent |
cc4062 |
fatal(status);
|
|
Ian Kent |
cc4062 |
+ master_mutex_unlock();
|
|
Ian Kent |
cc4062 |
return 1;
|
|
Ian Kent |
cc4062 |
}
|
|
Ian Kent |
cc4062 |
-
|
|
Ian Kent |
cc4062 |
master->reading = 1;
|
|
Ian Kent |
cc4062 |
+ master_mutex_unlock();
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
status = pthread_create(&thid, &th_attr_detached, do_read_master, NULL);
|
|
Ian Kent |
cc4062 |
if (status) {
|
|
Ian Kent |
cc4062 |
--- autofs-5.0.5.orig/include/automount.h
|
|
Ian Kent |
cc4062 |
+++ autofs-5.0.5/include/automount.h
|
|
Ian Kent |
cc4062 |
@@ -194,6 +194,7 @@ void cache_multi_writelock(struct mapent
|
|
Ian Kent |
cc4062 |
void cache_multi_unlock(struct mapent *me);
|
|
Ian Kent |
cc4062 |
int cache_delete_offset_list(struct mapent_cache *mc, const char *key);
|
|
Ian Kent |
cc4062 |
void cache_release(struct map_source *map);
|
|
Ian Kent |
cc4062 |
+void cache_clean_null_cache(struct mapent_cache *mc);
|
|
Ian Kent |
cc4062 |
void cache_release_null_cache(struct master *master);
|
|
Ian Kent |
cc4062 |
struct mapent *cache_enumerate(struct mapent_cache *mc, struct mapent *me);
|
|
Ian Kent |
cc4062 |
char *cache_get_offset(const char *prefix, char *offset, int start, struct list_head *head, struct list_head **pos);
|
|
Ian Kent |
cc4062 |
--- autofs-5.0.5.orig/lib/cache.c
|
|
Ian Kent |
cc4062 |
+++ autofs-5.0.5/lib/cache.c
|
|
Ian Kent |
cc4062 |
@@ -228,15 +228,38 @@ struct mapent_cache *cache_init(struct a
|
|
Ian Kent |
cc4062 |
return mc;
|
|
Ian Kent |
cc4062 |
}
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
+void cache_clean_null_cache(struct mapent_cache *mc)
|
|
Ian Kent |
cc4062 |
+{
|
|
Ian Kent |
cc4062 |
+ struct mapent *me, *next;
|
|
Ian Kent |
cc4062 |
+ int i;
|
|
Ian Kent |
cc4062 |
+
|
|
Ian Kent |
cc4062 |
+ for (i = 0; i < mc->size; i++) {
|
|
Ian Kent |
cc4062 |
+ me = mc->hash[i];
|
|
Ian Kent |
cc4062 |
+ if (me == NULL)
|
|
Ian Kent |
cc4062 |
+ continue;
|
|
Ian Kent |
cc4062 |
+ next = me->next;
|
|
Ian Kent |
cc4062 |
+ free(me->key);
|
|
Ian Kent |
cc4062 |
+ if (me->mapent)
|
|
Ian Kent |
cc4062 |
+ free(me->mapent);
|
|
Ian Kent |
cc4062 |
+ free(me);
|
|
Ian Kent |
cc4062 |
+
|
|
Ian Kent |
cc4062 |
+ while (next != NULL) {
|
|
Ian Kent |
cc4062 |
+ me = next;
|
|
Ian Kent |
cc4062 |
+ next = me->next;
|
|
Ian Kent |
cc4062 |
+ free(me->key);
|
|
Ian Kent |
cc4062 |
+ free(me);
|
|
Ian Kent |
cc4062 |
+ }
|
|
Ian Kent |
cc4062 |
+ }
|
|
Ian Kent |
cc4062 |
+
|
|
Ian Kent |
cc4062 |
+ return;
|
|
Ian Kent |
cc4062 |
+}
|
|
Ian Kent |
cc4062 |
+
|
|
Ian Kent |
cc4062 |
struct mapent_cache *cache_init_null_cache(struct master *master)
|
|
Ian Kent |
cc4062 |
{
|
|
Ian Kent |
cc4062 |
struct mapent_cache *mc;
|
|
Ian Kent |
cc4062 |
unsigned int i;
|
|
Ian Kent |
cc4062 |
int status;
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
- if (master->nc)
|
|
Ian Kent |
cc4062 |
- cache_release_null_cache(master);
|
|
Ian Kent |
cc4062 |
-
|
|
Ian Kent |
cc4062 |
mc = malloc(sizeof(struct mapent_cache));
|
|
Ian Kent |
cc4062 |
if (!mc)
|
|
Ian Kent |
cc4062 |
return NULL;
|
|
Ian Kent |
cc4062 |
@@ -264,8 +287,6 @@ struct mapent_cache *cache_init_null_cac
|
|
Ian Kent |
cc4062 |
if (status)
|
|
Ian Kent |
cc4062 |
fatal(status);
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
- cache_writelock(mc);
|
|
Ian Kent |
cc4062 |
-
|
|
Ian Kent |
cc4062 |
for (i = 0; i < mc->size; i++) {
|
|
Ian Kent |
cc4062 |
mc->hash[i] = NULL;
|
|
Ian Kent |
cc4062 |
INIT_LIST_HEAD(&mc->ino_index[i]);
|
|
Ian Kent |
cc4062 |
@@ -274,8 +295,6 @@ struct mapent_cache *cache_init_null_cac
|
|
Ian Kent |
cc4062 |
mc->ap = NULL;
|
|
Ian Kent |
cc4062 |
mc->map = NULL;
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
- cache_unlock(mc);
|
|
Ian Kent |
cc4062 |
-
|
|
Ian Kent |
cc4062 |
return mc;
|
|
Ian Kent |
cc4062 |
}
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
--- autofs-5.0.5.orig/lib/master.c
|
|
Ian Kent |
cc4062 |
+++ autofs-5.0.5/lib/master.c
|
|
Ian Kent |
cc4062 |
@@ -811,15 +811,28 @@ int master_read_master(struct master *ma
|
|
Ian Kent |
cc4062 |
unsigned int logopt = master->logopt;
|
|
Ian Kent |
cc4062 |
struct mapent_cache *nc;
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
- nc = cache_init_null_cache(master);
|
|
Ian Kent |
cc4062 |
- if (!nc) {
|
|
Ian Kent |
cc4062 |
- error(logopt,
|
|
Ian Kent |
cc4062 |
- "failed to init null map cache for %s", master->name);
|
|
Ian Kent |
cc4062 |
- return 0;
|
|
Ian Kent |
cc4062 |
+ /*
|
|
Ian Kent |
cc4062 |
+ * We need to clear and re-populate the null map entry cache
|
|
Ian Kent |
cc4062 |
+ * before alowing anyone else to use it.
|
|
Ian Kent |
cc4062 |
+ */
|
|
Ian Kent |
cc4062 |
+ if (master->nc) {
|
|
Ian Kent |
cc4062 |
+ cache_writelock(master->nc);
|
|
Ian Kent |
cc4062 |
+ nc = master->nc;
|
|
Ian Kent |
cc4062 |
+ cache_clean_null_cache(nc);
|
|
Ian Kent |
cc4062 |
+ } else {
|
|
Ian Kent |
cc4062 |
+ nc = cache_init_null_cache(master);
|
|
Ian Kent |
cc4062 |
+ if (!nc) {
|
|
Ian Kent |
cc4062 |
+ error(logopt,
|
|
Ian Kent |
cc4062 |
+ "failed to init null map cache for %s",
|
|
Ian Kent |
cc4062 |
+ master->name);
|
|
Ian Kent |
cc4062 |
+ return 0;
|
|
Ian Kent |
cc4062 |
+ }
|
|
Ian Kent |
cc4062 |
+ cache_writelock(nc);
|
|
Ian Kent |
cc4062 |
+ master->nc = nc;
|
|
Ian Kent |
cc4062 |
}
|
|
Ian Kent |
cc4062 |
- master->nc = nc;
|
|
Ian Kent |
cc4062 |
-
|
|
Ian Kent |
cc4062 |
master_init_scan();
|
|
Ian Kent |
cc4062 |
+ lookup_nss_read_master(master, age);
|
|
Ian Kent |
cc4062 |
+ cache_unlock(nc);
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
lookup_nss_read_master(master, age);
|
|
Ian Kent |
cc4062 |
if (!master->read_fail)
|
|
Ian Kent |
cc4062 |
--- autofs-5.0.5.orig/lib/master_parse.y
|
|
Ian Kent |
cc4062 |
+++ autofs-5.0.5/lib/master_parse.y
|
|
Ian Kent |
cc4062 |
@@ -741,21 +741,16 @@ int master_parse_entry(const char *buffe
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
/* Add null map entries to the null map cache */
|
|
Ian Kent |
cc4062 |
if (type && !strcmp(type, "null")) {
|
|
Ian Kent |
cc4062 |
- cache_writelock(nc);
|
|
Ian Kent |
cc4062 |
cache_update(nc, NULL, path, NULL, lineno);
|
|
Ian Kent |
cc4062 |
- cache_unlock(nc);
|
|
Ian Kent |
cc4062 |
local_free_vars();
|
|
Ian Kent |
cc4062 |
return 1;
|
|
Ian Kent |
cc4062 |
}
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
/* Ignore all subsequent matching nulled entries */
|
|
Ian Kent |
cc4062 |
- cache_readlock(nc);
|
|
Ian Kent |
cc4062 |
if (cache_lookup_distinct(nc, path)) {
|
|
Ian Kent |
cc4062 |
- cache_unlock(nc);
|
|
Ian Kent |
cc4062 |
local_free_vars();
|
|
Ian Kent |
cc4062 |
return 1;
|
|
Ian Kent |
cc4062 |
}
|
|
Ian Kent |
cc4062 |
- cache_unlock(nc);
|
|
Ian Kent |
cc4062 |
|
|
Ian Kent |
cc4062 |
if (debug || verbose) {
|
|
Ian Kent |
cc4062 |
logopt = (debug ? LOGOPT_DEBUG : 0);
|