- add upstream bug fix patches

- add command line option to override is running check.
- don't use proc fs for is running check.
- fix fail on included browse map not found.
- fix incorrect multi source messages.
- clear stale flag on map read.
- fix proximity other rpc ping timeout.
- refactor mount request vars code.
- make handle_mounts startup condition distinct.
- fix submount shutdown handling.
- try not to block on expire.
- add configuration paramter UMOUNT_WAIT.
- fix multi mount race.
- fix nfs4 colon escape handling.
- check replicated list after probe.
- add replicated server selection debug logging.
- update replicated server selection documentation.
- use /dev/urandom instead of /dev/random.
- check for mtab pointing to /proc/mounts.
- fix interface config buffer size.
- fix percent hack heap corruption.
This commit is contained in:
Ian Kent 2008-08-25 04:47:37 +00:00
parent 4fa4332422
commit 3685ec8873
22 changed files with 7885 additions and 1 deletions

View File

@ -0,0 +1,189 @@
autofs-5.0.3 - add replicated server selection debug logging
From: Ian Kent <raven@themaw.net>
Add some debug logging to the replicated server selection code.
---
CHANGELOG | 1 +
modules/replicated.c | 86 ++++++++++++++++++++++++++++++++++++++------------
2 files changed, 67 insertions(+), 20 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index a7b41ec..af3318a 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -30,6 +30,7 @@
- avoid stat of possibly dead mount points and limit time to wait for
umount during expire.
- make mount of multi-mounts wuth a root offset atomic.
+- add replicated server selection debug logging.
14/01/2008 autofs-5.0.3
-----------------------
diff --git a/modules/replicated.c b/modules/replicated.c
index 271907c..e41713e 100644
--- a/modules/replicated.c
+++ b/modules/replicated.c
@@ -404,6 +404,10 @@ static unsigned int get_nfs_info(unsigned logopt, struct host *host,
double taken = 0;
int status, count = 0;
+ debug(logopt,
+ "called for host %s proto %s version 0x%x",
+ host->name, proto, version);
+
memset(&parms, 0, sizeof(struct pmap));
parms.pm_prog = NFS_PROGRAM;
@@ -428,11 +432,17 @@ static unsigned int get_nfs_info(unsigned logopt, struct host *host,
status = rpc_ping_proto(rpc_info);
gettimeofday(&end, &tz);
if (status) {
- if (random_selection)
+ double reply;
+ if (random_selection) {
/* Random value between 0 and 1 */
- taken += ((float) random())/((float) RAND_MAX+1);
- else
- taken += elapsed(start, end);;
+ reply = ((float) random())/((float) RAND_MAX+1);
+ debug(logopt,
+ "nfs v4 random selection time: %f", reply);
+ } else {
+ reply = elapsed(start, end);
+ debug(logopt, "nfs v4 rpc ping time: %f", reply);
+ }
+ taken += reply;
count++;
supported = NFS4_SUPPORTED;
}
@@ -470,11 +480,17 @@ v3_ver:
status = rpc_ping_proto(rpc_info);
gettimeofday(&end, &tz);
if (status) {
- if (random_selection)
+ double reply;
+ if (random_selection) {
/* Random value between 0 and 1 */
- taken += ((float) random())/((float) RAND_MAX+1);
- else
- taken += elapsed(start, end);;
+ reply = ((float) random())/((float) RAND_MAX+1);
+ debug(logopt,
+ "nfs v3 random selection time: %f", reply);
+ } else {
+ reply = elapsed(start, end);
+ debug(logopt, "nfs v3 rpc ping time: %f", reply);
+ }
+ taken += reply;
count++;
supported |= NFS3_SUPPORTED;
}
@@ -504,11 +520,17 @@ v2_ver:
status = rpc_ping_proto(rpc_info);
gettimeofday(&end, &tz);
if (status) {
- if (random_selection)
+ double reply;
+ if (random_selection) {
/* Random value between 0 and 1 */
- taken += ((float) random())/((float) RAND_MAX+1);
- else
- taken += elapsed(start, end);;
+ reply = ((float) random())/((float) RAND_MAX+1);
+ debug(logopt,
+ "nfs v2 random selection time: %f", reply);
+ } else {
+ reply = elapsed(start, end);;
+ debug(logopt, "nfs v2 rpc ping time: %f", reply);
+ }
+ taken += reply;
count++;
supported |= NFS2_SUPPORTED;
}
@@ -533,6 +555,9 @@ done_ver:
/* Allow for user bias */
if (host->weight)
host->cost *= (host->weight + 1);
+
+ debug(logopt, "host %s cost %ld weight %d",
+ host->name, host->cost, host->weight);
}
return supported;
@@ -603,6 +628,9 @@ static int get_supported_ver_and_cost(unsigned logopt, struct host *host,
time_t timeout = RPC_TIMEOUT;
int status;
+ debug(logopt,
+ "called with host %s version 0x%x", host->name, version);
+
memset(&pm_info, 0, sizeof(struct conn_info));
memset(&rpc_info, 0, sizeof(struct conn_info));
memset(&parms, 0, sizeof(struct pmap));
@@ -681,11 +709,14 @@ static int get_supported_ver_and_cost(unsigned logopt, struct host *host,
status = rpc_ping_proto(&rpc_info);
gettimeofday(&end, &tz);
if (status) {
- if (random_selection)
+ if (random_selection) {
/* Random value between 0 and 1 */
taken = ((float) random())/((float) RAND_MAX+1);
- else
+ debug(logopt, "random selection time %f", taken);
+ } else {
taken = elapsed(start, end);
+ debug(logopt, "rpc ping time %f", taken);
+ }
}
}
done:
@@ -705,6 +736,8 @@ done:
if (host->weight)
host->cost *= (host->weight + 1);
+ debug(logopt, "cost %ld weight %d", host->cost, host->weight);
+
return 1;
}
@@ -811,18 +844,31 @@ int prune_host_list(unsigned logopt, struct host **list,
max_udp_count = mmax(v4_udp_count, v3_udp_count, v2_udp_count);
max_count = max(max_tcp_count, max_udp_count);
- if (max_count == v4_tcp_count)
+ if (max_count == v4_tcp_count) {
selected_version = NFS4_TCP_SUPPORTED;
- else if (max_count == v3_tcp_count)
+ debug(logopt,
+ "selected subset of hosts that support NFS4 over TCP");
+ } else if (max_count == v3_tcp_count) {
selected_version = NFS3_TCP_SUPPORTED;
- else if (max_count == v2_tcp_count)
+ debug(logopt,
+ "selected subset of hosts that support NFS3 over TCP");
+ } else if (max_count == v2_tcp_count) {
selected_version = NFS2_TCP_SUPPORTED;
- else if (max_count == v4_udp_count)
+ debug(logopt,
+ "selected subset of hosts that support NFS2 over TCP");
+ } else if (max_count == v4_udp_count) {
selected_version = NFS4_UDP_SUPPORTED;
- else if (max_count == v3_udp_count)
+ debug(logopt,
+ "selected subset of hosts that support NFS4 over UDP");
+ } else if (max_count == v3_udp_count) {
selected_version = NFS3_UDP_SUPPORTED;
- else if (max_count == v2_udp_count)
+ debug(logopt,
+ "selected subset of hosts that support NFS3 over UDP");
+ } else if (max_count == v2_udp_count) {
selected_version = NFS2_UDP_SUPPORTED;
+ debug(logopt,
+ "selected subset of hosts that support NFS2 over UDP");
+ }
/* Add local and hosts with selected version to new list */
this = *list;

View File

@ -0,0 +1,138 @@
autofs-5.0.3 - add configuration paramter UMOUNT_WAIT
From: Ian Kent <raven@themaw.net>
To try and prevent expire delays when trying to umount from a server
that is not available we limit the time that we wait for a response
from the spawned umount process before sending it a SIGTERM signal.
This patch adds a configuration parameter to allow this wait to be
changed if needed.
---
daemon/spawn.c | 2 +-
include/defaults.h | 2 ++
lib/defaults.c | 13 +++++++++++++
man/auto.master.5.in | 6 ++++++
redhat/autofs.sysconfig.in | 4 ++++
samples/autofs.conf.default.in | 4 ++++
6 files changed, 30 insertions(+), 1 deletions(-)
diff --git a/daemon/spawn.c b/daemon/spawn.c
index e3c355e..6b26c41 100644
--- a/daemon/spawn.c
+++ b/daemon/spawn.c
@@ -502,7 +502,7 @@ int spawn_umount(unsigned logopt, ...)
unsigned int options;
unsigned int retries = MTAB_LOCK_RETRIES;
int ret, printed = 0;
- unsigned int wait = 12;
+ unsigned int wait = defaults_get_umount_wait();
#ifdef ENABLE_MOUNT_LOCKING
options = SPAWN_OPT_LOCK;
diff --git a/include/defaults.h b/include/defaults.h
index 6e4f52a..12534ec 100644
--- a/include/defaults.h
+++ b/include/defaults.h
@@ -24,6 +24,7 @@
#define DEFAULT_TIMEOUT 600
#define DEFAULT_NEGATIVE_TIMEOUT 60
+#define DEFAULT_UMOUNT_WAIT 12
#define DEFAULT_BROWSE_MODE 1
#define DEFAULT_LOGGING 0
@@ -59,6 +60,7 @@ struct ldap_schema *defaults_get_schema(void);
struct ldap_searchdn *defaults_get_searchdns(void);
void defaults_free_searchdns(struct ldap_searchdn *);
unsigned int defaults_get_append_options(void);
+unsigned int defaults_get_umount_wait(void);
const char *defaults_get_auth_conf_file(void);
#endif
diff --git a/lib/defaults.c b/lib/defaults.c
index 8149549..21d76d2 100644
--- a/lib/defaults.c
+++ b/lib/defaults.c
@@ -45,6 +45,7 @@
#define ENV_NAME_VALUE_ATTR "VALUE_ATTRIBUTE"
#define ENV_APPEND_OPTIONS "APPEND_OPTIONS"
+#define ENV_UMOUNT_WAIT "UMOUNT_WAIT"
#define ENV_AUTH_CONF_FILE "AUTH_CONF_FILE"
static const char *default_master_map_name = DEFAULT_MASTER_MAP_NAME;
@@ -320,6 +321,7 @@ unsigned int defaults_read_config(unsigned int to_syslog)
check_set_config_value(key, ENV_NAME_ENTRY_ATTR, value, to_syslog) ||
check_set_config_value(key, ENV_NAME_VALUE_ATTR, value, to_syslog) ||
check_set_config_value(key, ENV_APPEND_OPTIONS, value, to_syslog) ||
+ check_set_config_value(key, ENV_UMOUNT_WAIT, value, to_syslog) ||
check_set_config_value(key, ENV_AUTH_CONF_FILE, value, to_syslog))
;
}
@@ -647,6 +649,17 @@ unsigned int defaults_get_append_options(void)
return res;
}
+unsigned int defaults_get_umount_wait(void)
+{
+ long wait;
+
+ wait = get_env_number(ENV_UMOUNT_WAIT);
+ if (wait < 0)
+ wait = DEFAULT_UMOUNT_WAIT;
+
+ return (unsigned int) wait;
+}
+
const char *defaults_get_auth_conf_file(void)
{
char *cf;
diff --git a/man/auto.master.5.in b/man/auto.master.5.in
index 49a711c..9cc5f02 100644
--- a/man/auto.master.5.in
+++ b/man/auto.master.5.in
@@ -174,6 +174,12 @@ Set the default timeout for caching failed key lookups (program default
60). If the equivalent command line option is given it will override this
setting.
.TP
+.B UMOUNT_WAIT
+Set the default time to wait for a response from a spawned umount(8)
+before sending it a SIGTERM. Note that we still need to wait for the
+RPC layer to timeout before the sub-process exits so this isn't ideal
+but it is the best we can do.
+.TP
.B BROWSE_MODE
Maps are browsable by default (program default "yes").
.TP
diff --git a/redhat/autofs.sysconfig.in b/redhat/autofs.sysconfig.in
index 636763a..ce64feb 100644
--- a/redhat/autofs.sysconfig.in
+++ b/redhat/autofs.sysconfig.in
@@ -14,6 +14,10 @@ TIMEOUT=300
#
#NEGATIVE_TIMEOUT=60
#
+# UMOUNT_WAIT - time to wait for a response from umount(8).
+#
+#UMOUNT_WAIT=12
+#
# BROWSE_MODE - maps are browsable by default.
#
BROWSE_MODE="no"
diff --git a/samples/autofs.conf.default.in b/samples/autofs.conf.default.in
index 086ba4f..0231e1d 100644
--- a/samples/autofs.conf.default.in
+++ b/samples/autofs.conf.default.in
@@ -14,6 +14,10 @@ TIMEOUT=300
#
#NEGATIVE_TIMEOUT=60
#
+# UMOUNT_WAIT - time to wait for a response from umount(8).
+#
+#UMOUNT_WAIT=12
+#
# BROWSE_MODE - maps are browsable by default.
#
BROWSE_MODE="no"

View File

@ -0,0 +1,33 @@
autofs-5.0.3 - check replicated list after probe
From: Ian Kent <raven@themaw.net>
When checking a list of servers for proximity and NFS version
the list may become empty after after the initial probe. This
case isn't handled and this patch adds it.
---
modules/replicated.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/modules/replicated.c b/modules/replicated.c
index 925f641..271907c 100644
--- a/modules/replicated.c
+++ b/modules/replicated.c
@@ -768,6 +768,15 @@ int prune_host_list(unsigned logopt, struct host **list,
this = next;
}
+ /*
+ * The list of hosts that aren't proximity local may now
+ * be empty if we haven't been able probe any so we need
+ * to check again for a list containing only proximity
+ * local hosts.
+ */
+ if (!first)
+ return 1;
+
last = this;
/* Select NFS version of highest number of closest servers */

View File

@ -0,0 +1,29 @@
autofs-5.0.3 - clear stale flag on map read
From: Ian Kent <raven@themaw.net>
We're not properly clearing the map stale flag after a map re-read
which causes a re-read after every lookup for master map entries
that have the "browse" option set. I removed the line that did
this at some point in the past and I must have had a reason to
do so. We'll have to wait and see what shows up after fixing
it.
---
daemon/lookup.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/daemon/lookup.c b/daemon/lookup.c
index d33aadc..2277623 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -298,6 +298,8 @@ static int do_read_map(struct autofs_point *ap, struct map_source *map, time_t a
status = lookup->lookup_read_map(ap, age, lookup->context);
+ map->stale = 0;
+
/*
* For maps that don't support enumeration return success
* and do whatever we must to have autofs function with an

View File

@ -0,0 +1,495 @@
autofs-5.0.3 - try not to block on expire
From: Ian Kent <raven@themaw.net>
When a server is not available umount and any stat statfs and related
function calls may block for a significant amount of time. This effects
expire timeouts a lot due to their synchronous nature. This patch limits
the time we wait on spawned umounts and elininates calls to functions
that would block. This allows us to retry the umount on the next expire
event and continue the expire of remaining mounts.
---
CHANGELOG | 2 ++
daemon/automount.c | 34 ++++++++++++++++++------------
daemon/direct.c | 29 +++++---------------------
daemon/indirect.c | 26 +++++++++--------------
daemon/spawn.c | 59 ++++++++++++++++++++++++++++++++++++++++++----------
include/master.h | 1 +
lib/master.c | 23 ++++++++++++++++++++
lib/mounts.c | 48 ++----------------------------------------
8 files changed, 112 insertions(+), 110 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index ff04985..ff44cc7 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -27,6 +27,8 @@
- don't use proc file system when checking if the daemon is running.
- make handle_mounts startup condition distinct.
- fix submount shutdown recovery handling.
+- avoid stat of possibly dead mount points and limit time to wait for
+ umount during expire.
14/01/2008 autofs-5.0.3
-----------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index 68bf1d3..5bd5f6d 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -247,9 +247,17 @@ static int walk_tree(const char *base, int (*fn) (unsigned logopt,
int, void *), int incl, unsigned logopt, void *arg)
{
char buf[PATH_MAX + 1];
- struct stat st;
+ struct stat st, *pst = &st;
+ int ret;
+
+ if (!is_mounted(_PATH_MOUNTED, base, MNTS_REAL))
+ ret = lstat(base, pst);
+ else {
+ pst = NULL;
+ ret = 0;
+ }
- if (lstat(base, &st) != -1 && (fn) (logopt, base, &st, 0, arg)) {
+ if (ret != -1 && (fn) (logopt, base, pst, 0, arg)) {
if (S_ISDIR(st.st_mode)) {
struct dirent **de;
int n;
@@ -283,7 +291,7 @@ static int walk_tree(const char *base, int (*fn) (unsigned logopt,
free(de);
}
if (incl)
- (fn) (logopt, base, &st, 1, arg);
+ (fn) (logopt, base, pst, 1, arg);
}
return 0;
}
@@ -294,6 +302,9 @@ static int rm_unwanted_fn(unsigned logopt, const char *file, const struct stat *
char buf[MAX_ERR_BUF];
struct stat newst;
+ if (!st)
+ return 0;
+
if (when == 0) {
if (st->st_dev != dev)
return 0;
@@ -344,8 +355,8 @@ static int counter_fn(unsigned logopt, const char *file, const struct stat *st,
{
struct counter_args *counter = (struct counter_args *) arg;
- if (S_ISLNK(st->st_mode) || (S_ISDIR(st->st_mode)
- && st->st_dev != counter->dev)) {
+ if (!st || (S_ISLNK(st->st_mode) || (S_ISDIR(st->st_mode)
+ && st->st_dev != counter->dev))) {
counter->count++;
return 0;
}
@@ -512,9 +523,8 @@ static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsi
int umount_multi(struct autofs_point *ap, const char *path, int incl)
{
struct mapent_cache *nc;
- struct statfs fs;
int is_autofs_fs;
- int ret, left;
+ int left;
debug(ap->logopt, "path %s incl %d", path, incl);
@@ -526,13 +536,9 @@ int umount_multi(struct autofs_point *ap, const char *path, int incl)
}
cache_unlock(nc);
- ret = statfs(path, &fs);
- if (ret == -1) {
- error(ap->logopt, "could not stat fs of %s", path);
- return 1;
- }
-
- is_autofs_fs = fs.f_type == (__SWORD_TYPE) AUTOFS_SUPER_MAGIC ? 1 : 0;
+ is_autofs_fs = 0;
+ if (master_find_submount(ap, path))
+ is_autofs_fs = 1;
left = 0;
diff --git a/daemon/direct.c b/daemon/direct.c
index 334a4b6..7fb78a3 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -152,7 +152,7 @@ int do_umount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, stru
retries = UMOUNT_RETRIES;
while ((rv = umount(me->key)) == -1 && retries--) {
- struct timespec tm = {0, 100000000};
+ struct timespec tm = {0, 200000000};
if (errno != EBUSY)
break;
nanosleep(&tm, NULL);
@@ -604,7 +604,7 @@ int umount_autofs_offset(struct autofs_point *ap, struct mapent *me)
retries = UMOUNT_RETRIES;
while ((rv = umount(me->key)) == -1 && retries--) {
- struct timespec tm = {0, 100000000};
+ struct timespec tm = {0, 200000000};
if (errno != EBUSY)
break;
nanosleep(&tm, NULL);
@@ -705,7 +705,7 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me)
* the kernel NFS client.
*/
if (me->multi != me &&
- is_mounted(_PROC_MOUNTS, me->key, MNTS_REAL))
+ is_mounted(_PATH_MOUNTED, me->key, MNTS_REAL))
return MOUNT_OFFSET_IGNORE;
/*
@@ -807,17 +807,7 @@ out_err:
static int expire_direct(int ioctlfd, const char *path, unsigned int when, unsigned int logopt)
{
- char buf[MAX_ERR_BUF];
- int ret, retries;
- struct stat st;
-
- if (fstat(ioctlfd, &st) == -1) {
- char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
- debug(logopt, "fstat failed: %s", estr);
- return 0;
- }
-
- retries = (count_mounts(logopt, path, st.st_dev) + 1) * EXPIRE_RETRIES;
+ int ret, retries = EXPIRE_RETRIES;
while (retries--) {
struct timespec tm = {0, 100000000};
@@ -911,7 +901,6 @@ void *expire_proc_direct(void *arg)
if (!strcmp(next->fs_type, "autofs")) {
struct stat st;
- struct statfs fs;
int ioctlfd;
cache_unlock(me->mc);
@@ -932,14 +921,8 @@ void *expire_proc_direct(void *arg)
continue;
}
- if (statfs(next->path, &fs) == -1) {
- pthread_setcancelstate(cur_state, NULL);
- warn(ap->logopt,
- "fstatfs failed for %s", next->path);
- continue;
- }
-
- if (fs.f_type != (__SWORD_TYPE) AUTOFS_SUPER_MAGIC) {
+ /* It's got a mount, deal with in the outer loop */
+ if (tree_is_mounted(mnts, me->key, MNTS_REAL)) {
pthread_setcancelstate(cur_state, NULL);
continue;
}
diff --git a/daemon/indirect.c b/daemon/indirect.c
index 17bed3e..e832cd4 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -285,7 +285,7 @@ int umount_autofs_indirect(struct autofs_point *ap)
retries = UMOUNT_RETRIES;
while ((rv = umount(ap->path)) == -1 && retries--) {
- struct timespec tm = {0, 100000000};
+ struct timespec tm = {0, 200000000};
if (errno != EBUSY)
break;
nanosleep(&tm, NULL);
@@ -368,17 +368,7 @@ force_umount:
static int expire_indirect(struct autofs_point *ap, int ioctlfd, const char *path, unsigned int when)
{
- char buf[MAX_ERR_BUF];
- int ret, retries;
- struct stat st;
-
- if (fstat(ioctlfd, &st) == -1) {
- char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
- debug(ap->logopt, "fstat failed: %s", estr);
- return 0;
- }
-
- retries = (count_mounts(ap->logopt, path, st.st_dev) + 1) * EXPIRE_RETRIES;
+ int ret, retries = EXPIRE_RETRIES;
while (retries--) {
struct timespec tm = {0, 100000000};
@@ -512,7 +502,6 @@ void *expire_proc_indirect(void *arg)
left++;
pthread_setcancelstate(cur_state, NULL);
}
- pthread_cleanup_pop(1);
/*
* If there are no more real mounts left we could still
@@ -520,12 +509,17 @@ void *expire_proc_indirect(void *arg)
* umount them here.
*/
if (mnts) {
+ int retries;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
- ret = expire_indirect(ap, ap->ioctlfd, ap->path, now);
- if (!ret)
- left++;
+ retries = (count_mounts(ap->logopt, ap->path, ap->dev) + 1);
+ while (retries--) {
+ ret = expire_indirect(ap, ap->ioctlfd, ap->path, now);
+ if (!ret)
+ left++;
+ }
pthread_setcancelstate(cur_state, NULL);
}
+ pthread_cleanup_pop(1);
count = offsets = submnts = 0;
mnts = get_mnt_list(_PROC_MOUNTS, ap->path, 0);
diff --git a/daemon/spawn.c b/daemon/spawn.c
index 78d69c6..e3c355e 100644
--- a/daemon/spawn.c
+++ b/daemon/spawn.c
@@ -89,13 +89,43 @@ void reset_signals(void)
#define ERRBUFSIZ 2047 /* Max length of error string excl \0 */
-static int do_spawn(unsigned logopt, unsigned int options, const char *prog, const char *const *argv)
+static int timed_read(int pipe, char *buf, size_t len, int time)
+{
+ struct timeval timeout = { 0, 0 };
+ struct timeval *tout = NULL;
+ fd_set wset, rset;
+ int ret;
+
+ FD_ZERO(&rset);
+ FD_SET(pipe, &rset);
+ wset = rset;
+
+ if (time != -1) {
+ timeout.tv_sec = time;
+ tout = &timeout;
+ }
+
+ ret = select(pipe + 1, &rset, &wset, NULL, tout);
+ if (ret <= 0) {
+ if (ret == 0)
+ ret = -ETIMEDOUT;
+ return ret;
+ }
+
+ while ((ret = read(pipe, buf, len)) == -1 && errno == EINTR);
+
+ return ret;
+}
+
+static int do_spawn(unsigned logopt, unsigned int wait,
+ unsigned int options, const char *prog,
+ const char *const *argv)
{
pid_t f;
int ret, status, pipefd[2];
char errbuf[ERRBUFSIZ + 1], *p, *sp;
int errp, errn;
- int cancel_state;
+ int flags, cancel_state;
unsigned int use_lock = options & SPAWN_OPT_LOCK;
unsigned int use_access = options & SPAWN_OPT_ACCESS;
sigset_t allsigs, tmpsig, oldsig;
@@ -183,12 +213,15 @@ static int do_spawn(unsigned logopt, unsigned int options, const char *prog, con
return -1;
}
+ if ((flags = fcntl(pipefd[0], F_GETFD, 0)) != -1) {
+ flags |= FD_CLOEXEC;
+ fcntl(pipefd[0], F_SETFD, flags);
+ }
+
errp = 0;
do {
- while ((errn =
- read(pipefd[0], errbuf + errp, ERRBUFSIZ - errp)) == -1
- && errno == EINTR);
-
+ errn = timed_read(pipefd[0],
+ errbuf + errp, ERRBUFSIZ - errp, wait);
if (errn > 0) {
errp += errn;
@@ -213,6 +246,9 @@ static int do_spawn(unsigned logopt, unsigned int options, const char *prog, con
}
} while (errn > 0);
+ if (errn == -ETIMEDOUT)
+ kill(f, SIGTERM);
+
close(pipefd[0]);
if (errp > 0) {
@@ -238,7 +274,7 @@ static int do_spawn(unsigned logopt, unsigned int options, const char *prog, con
int spawnv(unsigned logopt, const char *prog, const char *const *argv)
{
- return do_spawn(logopt, SPAWN_OPT_NONE, prog, argv);
+ return do_spawn(logopt, -1, SPAWN_OPT_NONE, prog, argv);
}
int spawnl(unsigned logopt, const char *prog, ...)
@@ -259,7 +295,7 @@ int spawnl(unsigned logopt, const char *prog, ...)
while ((*p++ = va_arg(arg, char *)));
va_end(arg);
- return do_spawn(logopt, SPAWN_OPT_NONE, prog, (const char **) argv);
+ return do_spawn(logopt, -1, SPAWN_OPT_NONE, prog, (const char **) argv);
}
int spawn_mount(unsigned logopt, ...)
@@ -307,7 +343,7 @@ int spawn_mount(unsigned logopt, ...)
va_end(arg);
while (retries--) {
- ret = do_spawn(logopt, options, prog, (const char **) argv);
+ ret = do_spawn(logopt, -1, options, prog, (const char **) argv);
if (ret & MTAB_NOTUPDATED) {
struct timespec tm = {3, 0};
@@ -406,7 +442,7 @@ int spawn_bind_mount(unsigned logopt, ...)
va_end(arg);
while (retries--) {
- ret = do_spawn(logopt, options, prog, (const char **) argv);
+ ret = do_spawn(logopt, -1, options, prog, (const char **) argv);
if (ret & MTAB_NOTUPDATED) {
struct timespec tm = {3, 0};
@@ -466,6 +502,7 @@ int spawn_umount(unsigned logopt, ...)
unsigned int options;
unsigned int retries = MTAB_LOCK_RETRIES;
int ret, printed = 0;
+ unsigned int wait = 12;
#ifdef ENABLE_MOUNT_LOCKING
options = SPAWN_OPT_LOCK;
@@ -488,7 +525,7 @@ int spawn_umount(unsigned logopt, ...)
va_end(arg);
while (retries--) {
- ret = do_spawn(logopt, options, prog, (const char **) argv);
+ ret = do_spawn(logopt, wait, options, prog, (const char **) argv);
if (ret & MTAB_NOTUPDATED) {
/*
* If the mount succeeded but the mtab was not
diff --git a/include/master.h b/include/master.h
index 86ae045..a397a75 100644
--- a/include/master.h
+++ b/include/master.h
@@ -91,6 +91,7 @@ void master_source_lock_cleanup(void *);
void master_source_current_wait(struct master_mapent *);
void master_source_current_signal(struct master_mapent *);
struct master_mapent *master_find_mapent(struct master *, const char *);
+struct autofs_point *master_find_submount(struct autofs_point *, const char *);
struct master_mapent *master_new_mapent(struct master *, const char *, time_t);
void master_add_mapent(struct master *, struct master_mapent *);
void master_remove_mapent(struct master_mapent *);
diff --git a/lib/master.c b/lib/master.c
index 522b919..71ba04a 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -602,6 +602,29 @@ struct master_mapent *master_find_mapent(struct master *master, const char *path
return NULL;
}
+struct autofs_point *master_find_submount(struct autofs_point *ap, const char *path)
+{
+ struct list_head *head, *p;
+
+ mounts_mutex_lock(ap);
+
+ head = &ap->submounts;
+ list_for_each(p, head) {
+ struct autofs_point *submount;
+
+ submount = list_entry(p, struct autofs_point, mounts);
+
+ if (!strcmp(submount->path, path)) {
+ mounts_mutex_unlock(ap);
+ return submount;
+ }
+ }
+
+ mounts_mutex_unlock(ap);
+
+ return NULL;
+}
+
struct master_mapent *master_new_mapent(struct master *master, const char *path, time_t age)
{
struct master_mapent *entry;
diff --git a/lib/mounts.c b/lib/mounts.c
index a4bf86c..d77a6b0 100644
--- a/lib/mounts.c
+++ b/lib/mounts.c
@@ -1073,55 +1073,11 @@ free_tsv:
int umount_ent(struct autofs_point *ap, const char *path)
{
- struct stat st;
- struct statfs fs;
- int sav_errno;
- int status, is_smbfs = 0;
- int ret, rv = 1;
-
- ret = statfs(path, &fs);
- if (ret == -1) {
- warn(ap->logopt, "could not stat fs of %s", path);
- is_smbfs = 0;
- } else {
- int cifsfs = fs.f_type == (__SWORD_TYPE) CIFS_MAGIC_NUMBER;
- int smbfs = fs.f_type == (__SWORD_TYPE) SMB_SUPER_MAGIC;
- is_smbfs = (cifsfs | smbfs) ? 1 : 0;
- }
-
- status = lstat(path, &st);
- sav_errno = errno;
-
- if (status < 0)
- warn(ap->logopt, "lstat of %s failed with %d", path, status);
-
- /*
- * lstat failed and we're an smbfs fs returning an error that is not
- * EIO or EBADSLT or the lstat failed so it's a bad path. Return
- * a fail.
- *
- * EIO appears to correspond to an smb mount that has gone away
- * and EBADSLT relates to CD changer not responding.
- */
- if (!status && (S_ISDIR(st.st_mode) && st.st_dev != ap->dev)) {
- rv = spawn_umount(ap->logopt, path, NULL);
- } else if (is_smbfs && (sav_errno == EIO || sav_errno == EBADSLT)) {
- rv = spawn_umount(ap->logopt, path, NULL);
- }
+ int rv;
+ rv = spawn_umount(ap->logopt, path, NULL);
/* We are doing a forced shutcwdown down so unlink busy mounts */
if (rv && (ap->state == ST_SHUTDOWN_FORCE || ap->state == ST_SHUTDOWN)) {
- ret = stat(path, &st);
- if (ret == -1 && errno == ENOENT) {
- warn(ap->logopt, "mount point does not exist");
- return 0;
- }
-
- if (ret == 0 && !S_ISDIR(st.st_mode)) {
- warn(ap->logopt, "mount point is not a directory");
- return 0;
- }
-
if (ap->state == ST_SHUTDOWN_FORCE) {
info(ap->logopt, "forcing umount of %s", path);
rv = spawn_umount(ap->logopt, "-l", path, NULL);

View File

@ -0,0 +1,619 @@
autofs-5.0.3 - don't use proc for is running check
From: Ian Kent <raven@themaw.net>
Using /proc/<pid>/cmdline to check if the daemon is running allows
any user to create a trivial program called "automount" and prevent
the system automounter from running simply by executing it and
leaving it running. This patch makes autofs use a flag file for this
check instead.
---
CHANGELOG | 1
Makefile.conf.in | 3 +
aclocal.m4 | 16 ++++
configure | 35 +++++++++
configure.in | 17 +++++
daemon/Makefile | 5 +
daemon/automount.c | 95 ++++++++------------------
daemon/flag.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 294 insertions(+), 70 deletions(-)
create mode 100644 daemon/flag.c
diff --git a/CHANGELOG b/CHANGELOG
index f40a941..3921552 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -24,6 +24,7 @@
- fix incorrect if check in get user info.
- fix couple of memory leaks.
- add command line option to override check for daemon already running.
+- don't use proc file system when checking if the daemon is running.
14/01/2008 autofs-5.0.3
-----------------------
diff --git a/Makefile.conf.in b/Makefile.conf.in
index 09c3129..d88f5ee 100644
--- a/Makefile.conf.in
+++ b/Makefile.conf.in
@@ -74,6 +74,9 @@ autofsmapdir = @mapdir@
# Location for autofs fifos
autofsfifodir = @fifodir@
+# Location for autofs flag file
+autofsflagdir = @flagdir@
+
# Where to install the automount program
sbindir = @sbindir@
diff --git a/aclocal.m4 b/aclocal.m4
index a1105ae..9ef4050 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -136,6 +136,22 @@ AC_DEFUN(AF_FIFO_D,
done
fi])
+dnl --------------------------------------------------------------------------
+dnl AF_FLAG_D
+dnl
+dnl Check the location of the autofs flag file directory
+dnl --------------------------------------------------------------------------
+AC_DEFUN(AF_FLAG_D,
+[if test -z "$flagdir"; then
+ for flag_d in /var/run /tmp; do
+ if test -z "$flagdir"; then
+ if test -d "$flag_d"; then
+ flagdir="$flag_d"
+ fi
+ fi
+ done
+fi])
+
dnl ----------------------------------- ## -*- Autoconf -*-
dnl Check if --with-dmalloc was given. ##
dnl From Franc,ois Pinard ##
diff --git a/configure b/configure
index 0d3268c..9278196 100755
--- a/configure
+++ b/configure
@@ -655,6 +655,7 @@ initdir
confdir
mapdir
fifodir
+flagdir
DMALLOCLIB
MOUNT
HAVE_MOUNT
@@ -1295,6 +1296,7 @@ Optional Packages:
--with-confdir=DIR use DIR for autofs configuration files
--with-mapdir=PATH look in PATH for mount maps used by the automounter
--with-fifodir=PATH use PATH as the directory for fifos used by the automounter
+ --with-flagdir=PATH use PATH as the directory for the flag file used by the automounter
--with-dmalloc use dmalloc, as in
http://www.dmalloc.com/dmalloc.tar.gz
--with-hesiod=DIR enable Hesiod support (libs and includes in DIR)
@@ -1876,6 +1878,36 @@ echo "${ECHO_T}$fifodir" >&6; }
#
+# The user can specify --with-flagdir=PATH to specify where autofs flag file goes
+#
+if test -z "$flagdir"; then
+ for flag_d in /var/run /tmp; do
+ if test -z "$flagdir"; then
+ if test -d "$flag_d"; then
+ flagdir="$flag_d"
+ fi
+ fi
+ done
+fi
+
+# Check whether --with-flagdir was given.
+if test "${with_flagdir+set}" = set; then
+ withval=$with_flagdir; if test -z "$withval" -o "$withval" = "yes" -o "$withval" = "no"
+ then
+ :
+ else
+ filagdir="${withval}"
+ fi
+
+fi
+
+{ echo "$as_me:$LINENO: checking for autofs flag file directory" >&5
+echo $ECHO_N "checking for autofs flag file directory... $ECHO_C" >&6; }
+{ echo "$as_me:$LINENO: result: $flagdir" >&5
+echo "${ECHO_T}$flagdir" >&6; }
+
+
+#
# Optional include dmalloc
#
{ echo "$as_me:$LINENO: checking if malloc debugging is wanted" >&5
@@ -6247,6 +6279,7 @@ initdir!$initdir$ac_delim
confdir!$confdir$ac_delim
mapdir!$mapdir$ac_delim
fifodir!$fifodir$ac_delim
+flagdir!$flagdir$ac_delim
DMALLOCLIB!$DMALLOCLIB$ac_delim
MOUNT!$MOUNT$ac_delim
HAVE_MOUNT!$HAVE_MOUNT$ac_delim
@@ -6297,7 +6330,7 @@ LIBOBJS!$LIBOBJS$ac_delim
LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 89; then
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 90; then
break
elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
diff --git a/configure.in b/configure.in
index 27b9bec..5ba3a49 100644
--- a/configure.in
+++ b/configure.in
@@ -96,6 +96,23 @@ AC_MSG_RESULT([$fifodir])
AC_SUBST(fifodir)
#
+# The user can specify --with-flagdir=PATH to specify where autofs flag file goes
+#
+AF_FLAG_D()
+AC_ARG_WITH(flagdir,
+[ --with-flagdir=PATH use PATH as the directory for the flag file used by the automounter],
+ if test -z "$withval" -o "$withval" = "yes" -o "$withval" = "no"
+ then
+ :
+ else
+ filagdir="${withval}"
+ fi
+)
+AC_MSG_CHECKING([for autofs flag file directory])
+AC_MSG_RESULT([$flagdir])
+AC_SUBST(flagdir)
+
+#
# Optional include dmalloc
#
AM_WITH_DMALLOC()
diff --git a/daemon/Makefile b/daemon/Makefile
index 528a684..9c2d858 100644
--- a/daemon/Makefile
+++ b/daemon/Makefile
@@ -6,9 +6,9 @@
include ../Makefile.rules
SRCS = automount.c indirect.c direct.c spawn.c module.c mount.c \
- lookup.c state.c
+ lookup.c state.c flag.c
OBJS = automount.o indirect.o direct.o spawn.o module.o mount.o \
- lookup.o state.o
+ lookup.o state.o flag.o
version := $(shell cat ../.version)
@@ -17,6 +17,7 @@ CFLAGS += -DAUTOFS_LIB_DIR=\"$(autofslibdir)\"
CFLAGS += -DAUTOFS_MAP_DIR=\"$(autofsmapdir)\"
CFLAGS += -DAUTOFS_CONF_DIR=\"$(autofsconfdir)\"
CFLAGS += -DAUTOFS_FIFO_DIR=\"$(autofsfifodir)\"
+CFLAGS += -DAUTOFS_FLAG_DIR=\"$(autofsflagdir)\"
CFLAGS += -DVERSION_STRING=\"$(version)\"
LDFLAGS += -rdynamic
LIBS = -ldl
diff --git a/daemon/automount.c b/daemon/automount.c
index 48ac30a..dbf267c 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -81,6 +81,8 @@ pthread_key_t key_thread_stdenv_vars;
#define MAX_OPEN_FILES 10240
+int aquire_flag_file(void);
+void release_flag_file(void);
static int umount_all(struct autofs_point *ap, int force);
extern pthread_mutex_t master_mutex;
@@ -1098,7 +1100,7 @@ static int handle_packet(struct autofs_point *ap)
return -1;
}
-static void become_daemon(unsigned foreground)
+static void become_daemon(unsigned foreground, unsigned daemon_check)
{
FILE *pidfp;
char buf[MAX_ERR_BUF];
@@ -1118,9 +1120,14 @@ static void become_daemon(unsigned foreground)
}
/* Detach from foreground process */
- if (foreground)
+ if (foreground) {
+ if (daemon_check && !aquire_flag_file()) {
+ fprintf(stderr, "%s: program is already running.\n",
+ program);
+ exit(1);
+ }
log_to_stderr();
- else {
+ } else {
pid = fork();
if (pid > 0) {
int r;
@@ -1136,6 +1143,13 @@ static void become_daemon(unsigned foreground)
}
close(start_pipefd[0]);
+ if (daemon_check && !aquire_flag_file()) {
+ fprintf(stderr, "%s: program is already running.\n",
+ program);
+ close(start_pipefd[1]);
+ exit(1);
+ }
+
/*
* Make our own process group for "magic" reason: processes that share
* our pgrp see the raw filesystem behind the magic.
@@ -1143,6 +1157,7 @@ static void become_daemon(unsigned foreground)
if (setsid() == -1) {
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
fprintf(stderr, "setsid: %s", estr);
+ close(start_pipefd[1]);
exit(1);
}
log_to_syslog();
@@ -1617,64 +1632,6 @@ static void key_thread_stdenv_vars_destroy(void *arg)
return;
}
-static int is_automount_running(void)
-{
- FILE *fp;
- DIR *dir;
- struct dirent entry;
- struct dirent *result;
- char path[PATH_MAX + 1], buf[PATH_MAX];
-
- if ((dir = opendir("/proc")) == NULL) {
- fprintf(stderr, "cannot opendir(/proc)\n");
- exit(1);
- }
-
- while (readdir_r(dir, &entry, &result) == 0) {
- int path_len, pid = 0;
-
- if (!result)
- break;
-
- if (*entry.d_name == '.')
- continue;
-
- if (!strcmp(entry.d_name, "self"))
- continue;
-
- if (!isdigit(*entry.d_name))
- continue;
-
- pid = atoi(entry.d_name);
- if (pid == getpid())
- continue;
-
- path_len = sprintf(path, "/proc/%s/cmdline", entry.d_name);
- if (path_len >= PATH_MAX) {
- fprintf(stderr,
- "buffer to small for /proc path\n");
- return -1;
- }
- path[path_len] = '\0';
-
- fp = fopen(path, "r");
- if (fp) {
- int c, len = 0;
-
- while (len < 127 && (c = fgetc(fp)) != EOF && c)
- buf[len++] = c;
- buf[len] = '\0';
-
- if (strstr(buf, "automount"))
- return pid;
- fclose(fp);
- }
- }
- closedir(dir);
-
- return 0;
-}
-
static void usage(void)
{
fprintf(stderr,
@@ -1973,11 +1930,6 @@ int main(int argc, char *argv[])
exit(exit_code);
}
- if (daemon_check && is_automount_running() > 0) {
- fprintf(stderr, "%s: program is already running.\n",
- program);
- exit(1);
- }
#if 0
if (!load_autofs4_module()) {
fprintf(stderr, "%s: can't load %s filesystem module.\n",
@@ -2009,7 +1961,7 @@ int main(int argc, char *argv[])
"can't increase core file limit - continuing");
#endif
- become_daemon(foreground);
+ become_daemon(foreground, daemon_check);
if (argc == 0)
master_list = master_new(NULL, timeout, ghost);
@@ -2020,6 +1972,7 @@ int main(int argc, char *argv[])
logerr("%s: can't create master map %s",
program, argv[0]);
close(start_pipefd[1]);
+ release_flag_file();
exit(1);
}
@@ -2027,6 +1980,7 @@ int main(int argc, char *argv[])
logerr("%s: failed to init thread attribute struct!",
program);
close(start_pipefd[1]);
+ release_flag_file();
exit(1);
}
@@ -2035,6 +1989,7 @@ int main(int argc, char *argv[])
logerr("%s: failed to set detached thread attribute!",
program);
close(start_pipefd[1]);
+ release_flag_file();
exit(1);
}
@@ -2044,6 +1999,7 @@ int main(int argc, char *argv[])
logerr("%s: failed to set stack size thread attribute!",
program);
close(start_pipefd[1]);
+ release_flag_file();
exit(1);
}
#endif
@@ -2060,6 +2016,7 @@ int main(int argc, char *argv[])
program);
master_kill(master_list);
close(start_pipefd[1]);
+ release_flag_file();
exit(1);
}
@@ -2067,6 +2024,7 @@ int main(int argc, char *argv[])
logerr("%s: failed to create alarm handler thread!", program);
master_kill(master_list);
close(start_pipefd[1]);
+ release_flag_file();
exit(1);
}
@@ -2074,6 +2032,7 @@ int main(int argc, char *argv[])
logerr("%s: failed to create FSM handler thread!", program);
master_kill(master_list);
close(start_pipefd[1]);
+ release_flag_file();
exit(1);
}
@@ -2086,6 +2045,7 @@ int main(int argc, char *argv[])
*pst_stat = 3;
res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
close(start_pipefd[1]);
+ release_flag_file();
exit(3);
}
@@ -2102,6 +2062,7 @@ int main(int argc, char *argv[])
pid_file = NULL;
}
closelog();
+ release_flag_file();
#ifdef LIBXML2_WORKAROUND
if (dh)
diff --git a/daemon/flag.c b/daemon/flag.c
new file mode 100644
index 0000000..d8ca61b
--- /dev/null
+++ b/daemon/flag.c
@@ -0,0 +1,192 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * flag.c - autofs flag file management
+ *
+ * Copyright 2008 Red Hat, Inc. All rights reserved.
+ * Copyright 2008 Ian Kent <raven@themaw.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+#include <string.h>
+#include <alloca.h>
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+
+#define MAX_PIDSIZE 20
+#define FLAG_FILE AUTOFS_FLAG_DIR "/autofs-running"
+
+/* Flag for already existing flag file. */
+static int we_created_flagfile = 0;
+
+/* file descriptor of flag file */
+static int fd = -1;
+
+static int flag_is_owned(int fd)
+{
+ int pid = 0, tries = 3;
+
+ while (tries--) {
+ char pidbuf[MAX_PIDSIZE + 1];
+ int got;
+
+ lseek(fd, 0, SEEK_SET);
+ got = read(fd, pidbuf, MAX_PIDSIZE);
+ /*
+ * We add a terminator to the pid to verify write complete.
+ * If the write isn't finished in 300 milliseconds then it's
+ * probably a stale lock file.
+ */
+ if (got > 0 && pidbuf[got - 1] == '\n') {
+ sscanf(pidbuf, "%d", &pid);
+ break;
+ } else {
+ struct timespec t = { 0, 100000000 };
+ struct timespec r;
+
+ while (nanosleep(&t, &r) == -1 && errno == EINTR)
+ memcpy(&t, &r, sizeof(struct timespec));
+
+ continue;
+ }
+
+ /* Stale flagfile */
+ if (!tries)
+ return 0;
+ }
+
+
+ if (pid) {
+ int ret;
+
+ ret = kill(pid, 0);
+ /*
+ * If lock file exists but is not owned by a process
+ * we return unowned status so we can get rid of it
+ * and continue.
+ */
+ if (ret == -1 && errno == ESRCH)
+ return 0;
+ } else {
+ /*
+ * Odd, no pid in file - so what should we do?
+ * Assume something bad happened to owner and
+ * return unowned status.
+ */
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Remove flag file. */
+void release_flag_file(void)
+{
+ if (fd > 0) {
+ close(fd);
+ fd = -1;
+ }
+
+ if (we_created_flagfile) {
+ unlink(FLAG_FILE);
+ we_created_flagfile = 0;
+ }
+}
+
+/* * Try to create flag file */
+int aquire_flag_file(void)
+{
+ char *linkf;
+ int len;
+
+ len = strlen(FLAG_FILE) + MAX_PIDSIZE;
+ linkf = alloca(len + 1);
+ snprintf(linkf, len, "%s.%d", FLAG_FILE, getpid());
+
+ /*
+ * Repeat until it was us who made the link or we find the
+ * flag file already exists. If an unexpected error occurs
+ * we return 0 claiming the flag file exists which may not
+ * really be the case.
+ */
+ while (!we_created_flagfile) {
+ int errsv, i, j;
+
+ i = open(linkf, O_WRONLY|O_CREAT, 0);
+ if (i < 0) {
+ release_flag_file();
+ return 0;
+ }
+ close(i);
+
+ j = link(linkf, FLAG_FILE);
+ errsv = errno;
+
+ (void) unlink(linkf);
+
+ if (j < 0 && errsv != EEXIST) {
+ release_flag_file();
+ return 0;
+ }
+
+ fd = open(FLAG_FILE, O_RDWR);
+ if (fd < 0) {
+ /* Maybe the file was just deleted? */
+ if (errno == ENOENT)
+ continue;
+ release_flag_file();
+ return 0;
+ }
+
+ if (j == 0) {
+ char pidbuf[MAX_PIDSIZE + 1];
+ int pidlen;
+
+ pidlen = sprintf(pidbuf, "%d\n", getpid());
+ if (write(fd, pidbuf, pidlen) != pidlen) {
+ release_flag_file();
+ return 0;
+ }
+
+ we_created_flagfile = 1;
+ } else {
+ /*
+ * Someone else made the link.
+ * If the flag file is not owned by anyone clean
+ * it up and try again, otherwise return fail.
+ */
+ if (!flag_is_owned(fd)) {
+ close(fd);
+ fd = -1;
+ unlink(FLAG_FILE);
+ continue;
+ }
+
+ release_flag_file();
+ return 0;
+ }
+
+ close(fd);
+ fd = -1;
+ }
+
+ return 1;
+}
+

View File

@ -0,0 +1,144 @@
autofs-5.0.3 - fix interface config buffer size
From: Ian Kent <raven@themaw.net>
When getting the interface configuration information autofs uses a
fixed size buffer for the interface information. If there are many
interfaces this causes the check to fail.
---
CHANGELOG | 1 +
modules/replicated.c | 51 ++++++++++++++++++++++++++++++++++++++++++--------
2 files changed, 44 insertions(+), 8 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index d2fe0a6..5b0f265 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -34,6 +34,7 @@
- update replicated server selection documentation.
- use /dev/urandom instead of /dev/random.
- check for mtab pointing to /proc/mounts.
+- dynamically allocate interface config buffer.
14/01/2008 autofs-5.0.3
-----------------------
diff --git a/modules/replicated.c b/modules/replicated.c
index 362ab1b..ad1ede2 100644
--- a/modules/replicated.c
+++ b/modules/replicated.c
@@ -95,6 +95,41 @@ void seed_random(void)
return;
}
+static int alloc_ifreq(struct ifconf *ifc, int sock)
+{
+ int ret, lastlen = 0, len = MAX_IFC_BUF;
+ char err_buf[MAX_ERR_BUF], *buf;
+
+ while (1) {
+ buf = malloc(len);
+ if (!buf) {
+ char *estr = strerror_r(errno, err_buf, MAX_ERR_BUF);
+ logerr("malloc: %s", estr);
+ return 0;
+ }
+
+ ifc->ifc_len = sizeof(buf);
+ ifc->ifc_req = (struct ifreq *) buf;
+
+ ret = ioctl(sock, SIOCGIFCONF, ifc);
+ if (ret == -1) {
+ char *estr = strerror_r(errno, err_buf, MAX_ERR_BUF);
+ logerr("ioctl: %s", estr);
+ free(buf);
+ return 0;
+ }
+
+ if (ifc->ifc_len == lastlen)
+ break;
+
+ lastlen = ifc->ifc_len;
+ len += MAX_IFC_BUF;
+ free(buf);
+ }
+
+ return 1;
+}
+
static unsigned int get_proximity(const char *host_addr, int addr_len)
{
struct sockaddr_in *msk_addr, *if_addr;
@@ -122,12 +157,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
fcntl(sock, F_SETFD, cl_flags);
}
- ifc.ifc_len = sizeof(buf);
- ifc.ifc_req = (struct ifreq *) buf;
- ret = ioctl(sock, SIOCGIFCONF, &ifc);
- if (ret == -1) {
- char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
- logerr("ioctl: %s", estr);
+ if (!alloc_ifreq(&ifc, sock)) {
close(sock);
return PROXIMITY_ERROR;
}
@@ -138,7 +168,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
i = 0;
ptr = (char *) &ifc.ifc_buf[0];
- while (ptr < buf + ifc.ifc_len) {
+ while (ptr < (char *) ifc.ifc_req + ifc.ifc_len) {
ifr = (struct ifreq *) ptr;
switch (ifr->ifr_addr.sa_family) {
@@ -147,6 +177,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
ret = memcmp(&if_addr->sin_addr, hst_addr, addr_len);
if (!ret) {
close(sock);
+ free(ifc.ifc_req);
return PROXIMITY_LOCAL;
}
break;
@@ -162,7 +193,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
i = 0;
ptr = (char *) &ifc.ifc_buf[0];
- while (ptr < buf + ifc.ifc_len) {
+ while (ptr < (char *) ifc.ifc_req + ifc.ifc_len) {
ifr = (struct ifreq *) ptr;
switch (ifr->ifr_addr.sa_family) {
@@ -178,6 +209,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
logerr("ioctl: %s", estr);
close(sock);
+ free(ifc.ifc_req);
return PROXIMITY_ERROR;
}
@@ -186,6 +218,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
if ((ia & mask) == (ha & mask)) {
close(sock);
+ free(ifc.ifc_req);
return PROXIMITY_SUBNET;
}
@@ -208,6 +241,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
if ((ia & mask) == (ha & mask)) {
close(sock);
+ free(ifc.ifc_req);
return PROXIMITY_NET;
}
break;
@@ -221,6 +255,7 @@ static unsigned int get_proximity(const char *host_addr, int addr_len)
}
close(sock);
+ free(ifc.ifc_req);
return PROXIMITY_OTHER;
}

View File

@ -0,0 +1,26 @@
autofs-5.0.3 - fix fail on included browse map not found
From: Ian Kent <raven@themaw.net>
When looking up nsswitch sources, if nsswitch action check tells us
to continue we need to set the returned result to success so we
don't return a false failure.
---
daemon/lookup.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/daemon/lookup.c b/daemon/lookup.c
index 29a1491..3c22a35 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -545,6 +545,8 @@ int lookup_nss_read_map(struct autofs_point *ap, struct map_source *source, time
map = NULL;
break;
}
+
+ result = NSS_STATUS_SUCCESS;
}
pthread_cleanup_pop(1);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,182 @@
autofs-5.0.3 - fix multi source messages
From: Ian Kent <raven@themaw.net>
There are incorrect "key not found" messages seen for master map
entries that have multiple sources (direct mounts).
For example, for the direct mount entries:
/- auto.one
/- auto.two
if a mount lookup is done and is not found in auto.one we see a
not found message even though it may be found in auto.two.
This patch moves the "key not found" reporting out to the higher
level lookup and reports status at the end of the lookup.
---
daemon/lookup.c | 3 +++
modules/lookup_file.c | 11 ++---------
modules/lookup_ldap.c | 10 ++--------
modules/lookup_nisplus.c | 12 +++---------
modules/lookup_program.c | 2 +-
modules/lookup_yp.c | 10 ++--------
6 files changed, 13 insertions(+), 35 deletions(-)
diff --git a/daemon/lookup.c b/daemon/lookup.c
index 3c22a35..d33aadc 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -903,6 +903,9 @@ int lookup_nss_mount(struct autofs_point *ap, struct map_source *source, const c
send_map_update_request(ap);
pthread_cleanup_pop(1);
+ if (result == NSS_STATUS_NOTFOUND)
+ error(ap->logopt, "key \"%s\" not found in map.", name);
+
return !result;
}
diff --git a/modules/lookup_file.c b/modules/lookup_file.c
index 894f6fd..807ceab 100644
--- a/modules/lookup_file.c
+++ b/modules/lookup_file.c
@@ -1074,7 +1074,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
me = cache_lookup_distinct(mc, key);
if (me && me->status >= time(NULL)) {
cache_unlock(mc);
- return NSS_STATUS_NOTFOUND;
+ return NSS_STATUS_UNAVAIL;
}
cache_unlock(mc);
@@ -1105,11 +1105,6 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
if (status) {
if (status == NSS_STATUS_COMPLETED)
return NSS_STATUS_SUCCESS;
-
- error(ap->logopt,
- MODPREFIX "key \"%s\" not found in map",
- name);
-
return NSS_STATUS_NOTFOUND;
}
}
@@ -1154,9 +1149,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
}
cache_unlock(mc);
}
- } else
- error(ap->logopt,
- MODPREFIX "key \"%s\" not found in map.", name);
+ }
if (ret)
return NSS_STATUS_TRYAGAIN;
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 5cc2148..7777e90 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -2586,12 +2586,8 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt);
free(lkp_key);
- if (status) {
- error(ap->logopt,
- MODPREFIX "key \"%s\" not found in map",
- name);
+ if (status)
return status;
- }
}
cache_readlock(mc);
@@ -2633,9 +2629,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
}
cache_unlock(mc);
}
- } else
- error(ap->logopt,
- MODPREFIX "key \"%s\" not found in map", name);
+ }
if (ret)
return NSS_STATUS_TRYAGAIN;
diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c
index 3c19fd3..4666161 100644
--- a/modules/lookup_nisplus.c
+++ b/modules/lookup_nisplus.c
@@ -520,12 +520,8 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
ap->entry->current = source;
status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt);
- if (status) {
- error(ap->logopt,
- MODPREFIX "key \"%s\" not found in map",
- name);
+ if (status)
return status;
- }
}
cache_readlock(mc);
@@ -566,12 +562,10 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
}
cache_unlock(mc);
}
- } else
- error(ap->logopt,
- MODPREFIX "key \"%s\" not found in map", name);
+ }
if (ret)
- return NSS_STATUS_NOTFOUND;
+ return NSS_STATUS_TRYAGAIN;
return NSS_STATUS_SUCCESS;
}
diff --git a/modules/lookup_program.c b/modules/lookup_program.c
index 7c266d6..daf874d 100644
--- a/modules/lookup_program.c
+++ b/modules/lookup_program.c
@@ -390,7 +390,7 @@ out_free:
me->status = now + ap->negative_timeout;
}
cache_unlock(mc);
- return NSS_STATUS_UNAVAIL;
+ return NSS_STATUS_TRYAGAIN;
}
return NSS_STATUS_SUCCESS;
diff --git a/modules/lookup_yp.c b/modules/lookup_yp.c
index 14f981c..ee06551 100644
--- a/modules/lookup_yp.c
+++ b/modules/lookup_yp.c
@@ -626,12 +626,8 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt);
free(lkp_key);
- if (status) {
- error(ap->logopt,
- MODPREFIX "key \"%s\" not found in map",
- name);
+ if (status)
return status;
- }
}
cache_readlock(mc);
@@ -672,9 +668,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
}
cache_unlock(mc);
}
- } else
- error(ap->logopt,
- MODPREFIX "key \"%s\" not found in map", name);
+ }
if (ret)
return NSS_STATUS_TRYAGAIN;

View File

@ -0,0 +1,28 @@
autofs-5.0.3 - fix nfs4 colon escape handling
From: Ian Kent <raven@themaw.net>
When fstype=nfs4 is given for a mount entry that should be bind
mounted because it has a ":" escaped location the colon can be
discarded before the mount module is called. This causes an
incorrect mount fail return since the replicated selection code
expects the colon to be present for parsing.
---
modules/parse_sun.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/modules/parse_sun.c b/modules/parse_sun.c
index b548520..333f8a5 100644
--- a/modules/parse_sun.c
+++ b/modules/parse_sun.c
@@ -638,7 +638,7 @@ static int sun_mount(struct autofs_point *ap, const char *root,
}
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
- if (!strcmp(fstype, "nfs")) {
+ if (!strcmp(fstype, "nfs") || !strcmp(fstype, "nfs4")) {
what = alloca(loclen + 1);
memcpy(what, loc, loclen);
what[loclen] = '\0';

View File

@ -0,0 +1,369 @@
From jmoyer@redhat.com Thu Jul 17 10:12:13 2008
From: Ian Kent <raven@themaw.net>
Hi, Ian,
As I mentioned, the encode and decode routines for the % hack were
corrupting heap space. I put together a patch to fix things as they
stand today. The comments document the assumptions I made.
I tested this code by compiling a program that only included
these functions and passing them arbitrary input and validating the
reuslts. I then compiled them into the automounter and verified that
no heap corruption occurred (by running automount -f on a fedora
system where such things are reported).
Now, I don't think that we should ever have to encode the percent
hack. Shouldn't we just need to decode it, walking through all of the
returned entries until we find an exact match for the key being looked
up?
Comments welcome.
IMK: You're right, but we'll keep it for the moment.
Cheers,
Jeff
---
modules/lookup_ldap.c | 267 +++++++++++++++++++++++++++++++++++--------------
1 files changed, 193 insertions(+), 74 deletions(-)
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 7777e90..3990f8c 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -1512,6 +1512,65 @@ next:
return NSS_STATUS_SUCCESS;
}
+static int get_percent_decoded_len(const char *name)
+{
+ int escapes = 0;
+ int escaped = 0;
+ char *tmp = name;
+ int look_for_close = 0;
+
+ while (*tmp) {
+ if (*tmp == '%') {
+ /* assume escapes aren't interpreted inside brackets */
+ if (look_for_close) {
+ tmp++;
+ continue;
+ }
+ /* check for escaped % */
+ if (escaped) {
+ tmp++;
+ escaped = 0;
+ continue;
+ }
+ escapes++;
+ tmp++;
+ if (*tmp == '[') {
+ escapes++;
+ tmp++;
+ look_for_close = 1;
+ } else
+ escaped = 1;
+ } else if (*tmp == ']' && look_for_close) {
+ escaped = 0;
+ escapes++;
+ tmp++;
+ look_for_close = 0;
+ } else {
+ tmp++;
+ escaped = 0;
+ }
+ }
+
+ assert(strlen(name) > escapes);
+ return strlen(name) - escapes;
+}
+
+/*
+ * Try to catch heap corruption if our logic happens to be incorrect.
+ */
+static void validate_string_len(const char *orig, char *start,
+ char *end, unsigned int len)
+{
+ debug(LOGOPT_NONE, MODPREFIX "string %s encoded as %s", orig, start);
+ /* make sure we didn't overflow the allocated space */
+ if (end - start > len + 1) {
+ crit(LOGOPT_ANY, MODPREFIX "orig %s, len %d", orig, len);
+ crit(LOGOPT_ANY, MODPREFIX "en/decoded %s, len %d", start,
+ end - start);
+ }
+ assert(end-start <= len + 1);
+}
+
/*
* Deal with encode and decode of % hack.
* Return
@@ -1519,131 +1578,191 @@ next:
* -1 => syntax error or alloc fail.
* 1 transofrmed value returned.
*/
+/*
+ * Assumptions: %'s must be escaped by %'s. %'s are not used to escape
+ * anything else except capital letters (so you can't escape a closing
+ * bracket, for example).
+ */
static int decode_percent_hack(const char *name, char **key)
{
const char *tmp;
char *ptr, *new;
+ unsigned int len;
+ int escaped = 0, look_for_close = 0;
if (!key)
return -1;
*key = NULL;
- tmp = name;
- while (*tmp && *tmp != '%' && *tmp != '[' && *tmp != ']')
- tmp++;
- if (!*tmp)
- return 0;
+ len = get_percent_decoded_len(name);
+ new = malloc(len + 1);
+ if (!new)
+ return -1;
+ ptr = new;
tmp = name;
while (*tmp) {
if (*tmp == '%') {
- tmp++;
- if (!*tmp)
- return -1;
- if (*tmp != '[')
+ if (escaped) {
+ *ptr++ = *tmp++;
+ if (!look_for_close)
+ escaped = 0;
continue;
+ }
tmp++;
- while (*tmp && *tmp != ']') {
- if (*tmp == '%')
- tmp++;
+ if (*tmp == '[') {
tmp++;
- }
- if (!tmp)
- return -1;
- }
- tmp++;
- }
-
- new = malloc(strlen(name) + 1);
- if (!new)
- return -1;
-
- ptr = new;
- tmp = name;
- while (*tmp) {
- if (*tmp == '%' || *tmp == '[' || *tmp == ']') {
+ look_for_close = 1;
+ escaped = 1;
+ } else
+ escaped = 1;
+ } else if (*tmp == ']' && look_for_close) {
tmp++;
- if (*tmp && *tmp != '%')
- continue;
+ look_for_close = 0;
+ } else {
+ escaped = 0;
+ *ptr++ = *tmp++;
}
- *ptr++ = *tmp++;
}
*ptr = '\0';
-
*key = new;
+ validate_string_len(name, new, ptr, len);
return strlen(new);
}
-static int encode_percent_hack(const char *name, char **key, unsigned int use_class)
+/*
+ * Calculate the length of a string replacing all capital letters with %letter.
+ * For example:
+ * Sale -> %Sale
+ * SALE -> %S%A%L%E
+ */
+static int get_encoded_len_escaping_every_cap(const char *name)
{
const char *tmp;
- unsigned int len = 0;
- char *ptr, *new;
+ unsigned int escapes = 0; /* number of % escape characters */
- if (!key)
- return -1;
+ tmp = name;
+ while (*tmp) {
+ /* We'll need to escape percents */
+ if (*tmp == '%' || isupper(*tmp))
+ escapes++;
+ tmp++;
+ }
- *key = NULL;
+ return strlen(name) + escapes;
+}
+
+/*
+ * Calculate the length of a string replacing sequences (1 or more) of capital
+ * letters with %[letters]. For example:
+ * FOO -> %[FOO]
+ * Work -> %[W]ork
+ * WorksForMe -> %[W]orks%[F]or%[M]e
+ * aaBBaa -> aa%[BB]aa
+ */
+static int get_encoded_len_escaping_sequences(const char *name)
+{
+ const char *tmp;
+ unsigned int escapes = 0;
tmp = name;
while (*tmp) {
+ /* escape percents */
if (*tmp == '%')
- len++;
+ escapes++;
else if (isupper(*tmp)) {
- tmp++;
- len++;
- if (!use_class)
- len++;
- else {
- if (*tmp && isupper(*tmp))
- len += 2;
- else
- return 0;
- while (*tmp && isupper(*tmp)) {
- len++;
- tmp++;
- }
- }
+ /* start an escape block %[...] */
+ escapes += 3; /* %[] */
+ while (*tmp && isupper(*tmp))
+ tmp++;
continue;
}
- len++;
tmp++;
}
- if (len == strlen(name))
- return 0;
- new = malloc(len + 1);
- if (!new)
- return -1;
+ return strlen(name) + escapes;
+}
+
+static void encode_individual(const char *name, char *new, unsigned int len)
+{
+ const char *tmp;
+ char *ptr;
ptr = new;
tmp = name;
while (*tmp) {
- if (*tmp == '%')
+ if (*tmp == '%' || isupper(*tmp))
*ptr++ = '%';
- else if (isupper(*tmp)) {
- char next = *tmp++;
+ *ptr++ = *tmp++;
+ }
+ *ptr = '\0';
+ validate_string_len(name, new, ptr, len);
+}
+
+static void encode_sequence(const char *name, char *new, unsigned int len)
+{
+ const char *tmp;
+ char *ptr;
+
+ ptr = new;
+ tmp = name;
+ while (*tmp) {
+ if (*tmp == '%') {
*ptr++ = '%';
- if (*tmp && (!isupper(*tmp) || !use_class))
- *ptr++ = next;
- else {
- *ptr++ = '[';
- *ptr++ = next;
- while (*tmp && isupper(*tmp))
- *ptr++ = *tmp++;
- *ptr++ = ']';
+ *ptr++ = *tmp++;
+ } else if (isupper(*tmp)) {
+ *ptr++ = '%';
+ *ptr++ = '[';
+ *ptr++ = *tmp++;
+
+ while (*tmp && isupper(*tmp)) {
+ *ptr++ = *tmp;
+ tmp++;
}
- continue;
- }
- *ptr++ = *tmp++;
+ *ptr++ = ']';
+ } else
+ *ptr++ = *tmp++;
}
*ptr = '\0';
+ validate_string_len(name, new, ptr, len);
+}
- *key = new;
+/*
+ * use_class: 1 means encode string as %[CAPITALS], 0 means encode as
+ * %C%A%P%I%T%A%L%S
+ */
+static int encode_percent_hack(const char *name, char **key, unsigned int use_class)
+{
+ unsigned int len = 0;
- return strlen(new);
+ if (!key)
+ return -1;
+
+ if (use_class)
+ len = get_encoded_len_escaping_sequences(name);
+ else
+ len = get_encoded_len_escaping_every_cap(name);
+
+ /* If there is no escaping to be done, return 0 */
+ if (len == strlen(name))
+ return 0;
+
+ *key = malloc(len + 1);
+ if (!*key)
+ return -1;
+
+ if (use_class)
+ encode_sequence(name, *key, len);
+ else
+ encode_individual(name, *key, len);
+
+ if (strlen(*key) != len)
+ crit(LOGOPT_ANY, MODPREFIX "encoded key length mismatch: key "
+ "%s len %d strlen %d", *key, len, strlen(*key));
+
+ return strlen(*key);
}
static int do_paged_query(struct ldap_search_params *sp, struct lookup_context *ctxt)

View File

@ -0,0 +1,36 @@
autofs-5.0.3 - fix proximity other rpc ping timeout
From: Ian Kent <raven@themaw.net>
The timeout for the RCP ping for hosts that are on a network other
than the local subnet or network is mistakenly set quite short. This
can lead to unexplained intermittent failures for hosts on remote
networks.
---
modules/replicated.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/modules/replicated.c b/modules/replicated.c
index efbe6b4..925f641 100644
--- a/modules/replicated.c
+++ b/modules/replicated.c
@@ -552,7 +552,7 @@ static int get_vers_and_cost(unsigned logopt, struct host *host,
if (host->proximity == PROXIMITY_NET)
timeout = RPC_TIMEOUT * 2;
- else if (host->proximity == PROXIMITY_NET)
+ else if (host->proximity == PROXIMITY_OTHER)
timeout = RPC_TIMEOUT * 8;
rpc_info.host = host->name;
@@ -609,7 +609,7 @@ static int get_supported_ver_and_cost(unsigned logopt, struct host *host,
if (host->proximity == PROXIMITY_NET)
timeout = RPC_TIMEOUT * 2;
- else if (host->proximity == PROXIMITY_NET)
+ else if (host->proximity == PROXIMITY_OTHER)
timeout = RPC_TIMEOUT * 8;
rpc_info.host = host->name;

View File

@ -0,0 +1,309 @@
autofs-5.0.3 - make handle_mounts startup condition distinct
From: Ian Kent <raven@themaw.net>
When starting a number of mounts we can get contention for the startup
condition used to synchronize the handle_mounts thread completion. This
patch makes the condition used distinct for each thread creation.
---
CHANGELOG | 1 +
daemon/automount.c | 62 ++++++++++++++++++++++++++++++++++++++++++++----
include/automount.h | 4 +++
lib/master.c | 29 +++++++++++-----------
modules/mount_autofs.c | 35 +++++++++++++--------------
5 files changed, 93 insertions(+), 38 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 3921552..9da7be3 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -25,6 +25,7 @@
- fix couple of memory leaks.
- add command line option to override check for daemon already running.
- don't use proc file system when checking if the daemon is running.
+- make handle_mounts startup condition distinct.
14/01/2008 autofs-5.0.3
-----------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index dbf267c..086affb 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -1461,6 +1461,55 @@ static void mutex_operation_wait(pthread_mutex_t *mutex)
return;
}
+int handle_mounts_startup_cond_init(struct startup_cond *suc)
+{
+ int status;
+
+ status = pthread_mutex_init(&suc->mutex, NULL);
+ if (status)
+ return status;
+
+ status = pthread_cond_init(&suc->cond, NULL);
+ if (status) {
+ status = pthread_mutex_destroy(&suc->mutex);
+ if (status)
+ fatal(status);
+ return status;
+ }
+
+ status = pthread_mutex_lock(&suc->mutex);
+ if (status) {
+ status = pthread_mutex_destroy(&suc->mutex);
+ if (status)
+ fatal(status);
+ status = pthread_cond_destroy(&suc->cond);
+ if (status)
+ fatal(status);
+ }
+
+ return 0;
+}
+
+void handle_mounts_startup_cond_destroy(void *arg)
+{
+ struct startup_cond *suc = (struct startup_cond *) arg;
+ int status;
+
+ status = pthread_mutex_unlock(&suc->mutex);
+ if (status)
+ fatal(status);
+
+ status = pthread_mutex_destroy(&suc->mutex);
+ if (status)
+ fatal(status);
+
+ status = pthread_cond_destroy(&suc->cond);
+ if (status)
+ fatal(status);
+
+ return;
+}
+
static void handle_mounts_cleanup(void *arg)
{
struct autofs_point *ap;
@@ -1512,17 +1561,20 @@ static void handle_mounts_cleanup(void *arg)
void *handle_mounts(void *arg)
{
+ struct startup_cond *suc;
struct autofs_point *ap;
int cancel_state, status = 0;
- ap = (struct autofs_point *) arg;
+ suc = (struct startup_cond *) arg;
+
+ ap = suc->ap;
- pthread_cleanup_push(return_start_status, &suc);
+ pthread_cleanup_push(return_start_status, suc);
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_state);
state_mutex_lock(ap);
- status = pthread_mutex_lock(&suc.mutex);
+ status = pthread_mutex_lock(&suc->mutex);
if (status) {
logerr("failed to lock startup condition mutex!");
fatal(status);
@@ -1530,7 +1582,7 @@ void *handle_mounts(void *arg)
if (mount_autofs(ap) < 0) {
crit(ap->logopt, "mount of %s failed!", ap->path);
- suc.status = 1;
+ suc->status = 1;
state_mutex_unlock(ap);
umount_autofs(ap, 1);
pthread_setcancelstate(cancel_state, NULL);
@@ -1540,7 +1592,7 @@ void *handle_mounts(void *arg)
if (ap->ghost && ap->type != LKP_DIRECT)
info(ap->logopt, "ghosting enabled");
- suc.status = 0;
+ suc->status = 0;
pthread_cleanup_pop(1);
/* We often start several automounters at the same time. Add some
diff --git a/include/automount.h b/include/automount.h
index da1bf8f..1a20cd9 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -331,10 +331,14 @@ int ncat_path(char *buf, size_t len,
struct startup_cond {
pthread_mutex_t mutex;
pthread_cond_t cond;
+ struct autofs_point *ap;
unsigned int done;
unsigned int status;
};
+int handle_mounts_startup_cond_init(struct startup_cond *suc);
+void handle_mounts_startup_cond_destroy(void *arg);
+
struct master_readmap_cond {
pthread_mutex_t mutex;
pthread_cond_t cond;
diff --git a/lib/master.c b/lib/master.c
index 4a34dd4..edd3bdc 100644
--- a/lib/master.c
+++ b/lib/master.c
@@ -997,28 +997,31 @@ next:
static int master_do_mount(struct master_mapent *entry)
{
+ struct startup_cond suc;
struct autofs_point *ap;
pthread_t thid;
int status;
- status = pthread_mutex_lock(&suc.mutex);
- if (status)
- fatal(status);
+ ap = entry->ap;
+
+ if (handle_mounts_startup_cond_init(&suc)) {
+ crit(ap->logopt,
+ "failed to init startup cond for mount %s", entry->path);
+ return 0;
+ }
+ suc.ap = ap;
suc.done = 0;
suc.status = 0;
- ap = entry->ap;
-
debug(ap->logopt, "mounting %s", entry->path);
- if (pthread_create(&thid, &thread_attr, handle_mounts, ap)) {
+ status = pthread_create(&thid, &thread_attr, handle_mounts, &suc);
+ if (status) {
crit(ap->logopt,
"failed to create mount handler thread for %s",
entry->path);
- status = pthread_mutex_unlock(&suc.mutex);
- if (status)
- fatal(status);
+ handle_mounts_startup_cond_destroy(&suc);
return 0;
}
entry->thid = thid;
@@ -1031,15 +1034,11 @@ static int master_do_mount(struct master_mapent *entry)
if (suc.status) {
error(ap->logopt, "failed to startup mount");
- status = pthread_mutex_unlock(&suc.mutex);
- if (status)
- fatal(status);
+ handle_mounts_startup_cond_destroy(&suc);
return 0;
}
- status = pthread_mutex_unlock(&suc.mutex);
- if (status)
- fatal(status);
+ handle_mounts_startup_cond_destroy(&suc);
return 1;
}
diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c
index 356fb14..6f66564 100644
--- a/modules/mount_autofs.c
+++ b/modules/mount_autofs.c
@@ -46,6 +46,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
int name_len, const char *what, const char *fstype,
const char *c_options, void *context)
{
+ struct startup_cond suc;
pthread_t thid;
char *fullpath;
const char **argv;
@@ -210,34 +211,34 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
source->mc = cache_init(entry->ap, source);
if (!source->mc) {
error(ap->logopt, MODPREFIX "failed to init source cache");
+ master_free_map_source(source, 0);
master_free_mapent(entry);
return 1;
}
mounts_mutex_lock(ap);
- status = pthread_mutex_lock(&suc.mutex);
- if (status) {
- crit(ap->logopt,
- MODPREFIX "failed to lock startup condition mutex!");
- cache_release(source);
+ if (handle_mounts_startup_cond_init(&suc)) {
+ crit(ap->logopt, MODPREFIX
+ "failed to init startup cond for mount %s", entry->path);
+ mounts_mutex_unlock(ap);
+ master_free_map_source(source, 1);
master_free_mapent(entry);
return 1;
}
+ suc.ap = nap;
suc.done = 0;
suc.status = 0;
- if (pthread_create(&thid, NULL, handle_mounts, nap)) {
+ if (pthread_create(&thid, &thread_attr, handle_mounts, &suc)) {
crit(ap->logopt,
MODPREFIX
"failed to create mount handler thread for %s",
fullpath);
+ handle_mounts_startup_cond_destroy(&suc);
mounts_mutex_unlock(ap);
- status = pthread_mutex_unlock(&suc.mutex);
- if (status)
- fatal(status);
- cache_release(source);
+ master_free_map_source(source, 1);
master_free_mapent(entry);
return 1;
}
@@ -246,8 +247,10 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
while (!suc.done) {
status = pthread_cond_wait(&suc.cond, &suc.mutex);
if (status) {
+ handle_mounts_startup_cond_destroy(&suc);
mounts_mutex_unlock(ap);
- pthread_mutex_unlock(&suc.mutex);
+ master_free_map_source(source, 1);
+ master_free_mapent(entry);
fatal(status);
}
}
@@ -255,10 +258,9 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
if (suc.status) {
crit(ap->logopt,
MODPREFIX "failed to create submount for %s", fullpath);
+ handle_mounts_startup_cond_destroy(&suc);
mounts_mutex_unlock(ap);
- status = pthread_mutex_unlock(&suc.mutex);
- if (status)
- fatal(status);
+ master_free_map_source(source, 1);
master_free_mapent(entry);
return 1;
}
@@ -266,12 +268,9 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
ap->submnt_count++;
list_add(&nap->mounts, &ap->submounts);
+ handle_mounts_startup_cond_destroy(&suc);
mounts_mutex_unlock(ap);
- status = pthread_mutex_unlock(&suc.mutex);
- if (status)
- fatal(status);
-
return 0;
}

View File

@ -0,0 +1,170 @@
autofs-5.0.3 - check for mtab pointing to /proc/mounts
From: Ian Kent <raven@themaw.net>
autofs has problems if /etc/mtab points to /proc/mounts.
This patchs adds a check to see if this is the case. If it is then
autofs uses the mount(8) "-n" option which disables the normal mtab
update error checking.
---
CHANGELOG | 1 +
daemon/spawn.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 61 insertions(+), 6 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 50c9a27..d2fe0a6 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -33,6 +33,7 @@
- add replicated server selection debug logging.
- update replicated server selection documentation.
- use /dev/urandom instead of /dev/random.
+- check for mtab pointing to /proc/mounts.
14/01/2008 autofs-5.0.3
-----------------------
diff --git a/daemon/spawn.c b/daemon/spawn.c
index 6b26c41..85cf9b8 100644
--- a/daemon/spawn.c
+++ b/daemon/spawn.c
@@ -305,11 +305,13 @@ int spawn_mount(unsigned logopt, ...)
char **argv, **p;
char prog[] = PATH_MOUNT;
char arg0[] = PATH_MOUNT;
+ char argn[] = "-n";
/* In case we need to use the fake option to mount */
char arg_fake[] = "-f";
unsigned int options;
unsigned int retries = MTAB_LOCK_RETRIES;
- int ret, printed = 0;
+ int update_mtab = 1, ret, printed = 0;
+ char buf[PATH_MAX];
/* If we use mount locking we can't validate the location */
#ifdef ENABLE_MOUNT_LOCKING
@@ -322,6 +324,17 @@ int spawn_mount(unsigned logopt, ...)
for (argc = 1; va_arg(arg, char *); argc++);
va_end(arg);
+ ret = readlink(_PATH_MOUNTED, buf, PATH_MAX);
+ if (ret != -1) {
+ buf[ret] = '\0';
+ if (!strcmp(buf, _PROC_MOUNTS)) {
+ debug(logopt,
+ "mtab link detected, passing -n to mount");
+ argc++;
+ update_mtab = 0;
+ }
+ }
+
/* Alloc 1 extra slot in case we need to use the "-f" option */
if (!(argv = alloca(sizeof(char *) * argc + 2)))
return -1;
@@ -329,7 +342,12 @@ int spawn_mount(unsigned logopt, ...)
argv[0] = arg0;
va_start(arg, logopt);
- p = argv + 1;
+ if (update_mtab)
+ p = argv + 1;
+ else {
+ argv[1] = argn;
+ p = argv + 2;
+ }
while ((*p = va_arg(arg, char *))) {
if (options == SPAWN_OPT_NONE && !strcmp(*p, "-o")) {
*(++p) = va_arg(arg, char *);
@@ -409,11 +427,13 @@ int spawn_bind_mount(unsigned logopt, ...)
char prog[] = PATH_MOUNT;
char arg0[] = PATH_MOUNT;
char bind[] = "--bind";
+ char argn[] = "-n";
/* In case we need to use the fake option to mount */
char arg_fake[] = "-f";
unsigned int options;
unsigned int retries = MTAB_LOCK_RETRIES;
- int ret, printed = 0;
+ int update_mtab = 0, ret, printed = 0;
+ char buf[PATH_MAX];
/* If we use mount locking we can't validate the location */
#ifdef ENABLE_MOUNT_LOCKING
@@ -430,6 +450,17 @@ int spawn_bind_mount(unsigned logopt, ...)
for (argc = 2; va_arg(arg, char *); argc++);
va_end(arg);
+ ret = readlink(_PATH_MOUNTED, buf, PATH_MAX);
+ if (ret != -1) {
+ buf[ret] = '\0';
+ if (!strcmp(buf, _PROC_MOUNTS)) {
+ debug(logopt,
+ "mtab link detected, passing -n to mount");
+ argc++;
+ update_mtab = 0;
+ }
+ }
+
if (!(argv = alloca(sizeof(char *) * argc + 2)))
return -1;
@@ -437,7 +468,12 @@ int spawn_bind_mount(unsigned logopt, ...)
argv[1] = bind;
va_start(arg, logopt);
- p = argv + 2;
+ if (update_mtab)
+ p = argv + 2;
+ else {
+ argv[2] = argn;
+ p = argv + 3;
+ }
while ((*p++ = va_arg(arg, char *)));
va_end(arg);
@@ -499,10 +535,12 @@ int spawn_umount(unsigned logopt, ...)
char **argv, **p;
char prog[] = PATH_UMOUNT;
char arg0[] = PATH_UMOUNT;
+ char argn[] = "-n";
unsigned int options;
unsigned int retries = MTAB_LOCK_RETRIES;
- int ret, printed = 0;
+ int update_mtab = 1, ret, printed = 0;
unsigned int wait = defaults_get_umount_wait();
+ char buf[PATH_MAX];
#ifdef ENABLE_MOUNT_LOCKING
options = SPAWN_OPT_LOCK;
@@ -514,13 +552,29 @@ int spawn_umount(unsigned logopt, ...)
for (argc = 1; va_arg(arg, char *); argc++);
va_end(arg);
+ ret = readlink(_PATH_MOUNTED, buf, PATH_MAX);
+ if (ret != -1) {
+ buf[ret] = '\0';
+ if (!strcmp(buf, _PROC_MOUNTS)) {
+ debug(logopt,
+ "mtab link detected, passing -n to mount");
+ argc++;
+ update_mtab = 0;
+ }
+ }
+
if (!(argv = alloca(sizeof(char *) * argc + 1)))
return -1;
argv[0] = arg0;
va_start(arg, logopt);
- p = argv + 1;
+ if (update_mtab)
+ p = argv + 1;
+ else {
+ argv[1] = argn;
+ p = argv + 2;
+ }
while ((*p++ = va_arg(arg, char *)));
va_end(arg);

View File

@ -0,0 +1,121 @@
autofs-5.0.3 - add command line option to override is running check
From: Ian Kent <raven@themaw.net>
autofs common usage is to have a single instance of the daemon running
and it checks for this and exits if another instance is found to be
running. But there are situations were people need to run multiple
instances and this patch adds a command line option to overrid the
check. Please note that this doesn't mean that autofs will function
properly and it is the users responsibility to check that the
configuration in use will function properly.
---
CHANGELOG | 1 +
daemon/automount.c | 14 +++++++++++---
man/automount.8 | 10 ++++++++++
3 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 5901c75..f40a941 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -23,6 +23,7 @@
- fix direct mount path length not being checked.
- fix incorrect if check in get user info.
- fix couple of memory leaks.
+- add command line option to override check for daemon already running.
14/01/2008 autofs-5.0.3
-----------------------
diff --git a/daemon/automount.c b/daemon/automount.c
index 7ce9828..48ac30a 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -1694,6 +1694,8 @@ static void usage(void)
" specify global mount options\n"
" -l --set-log-priority priority path [path,...]\n"
" set daemon log verbosity\n"
+ " -C --dont-check-daemon\n"
+ " don't check if daemon is already running\n"
" -V --version print version, build config and exit\n"
, program);
}
@@ -1814,7 +1816,7 @@ int main(int argc, char *argv[])
{
int res, opt, status;
int logpri = -1;
- unsigned ghost, logging;
+ unsigned ghost, logging, daemon_check;
unsigned foreground, have_global_options;
time_t timeout;
time_t age = time(NULL);
@@ -1833,6 +1835,7 @@ int main(int argc, char *argv[])
{"global-options", 1, 0, 'O'},
{"version", 0, 0, 'V'},
{"set-log-priority", 1, 0, 'l'},
+ {"dont-check-daemon", 0, 0, 'C'},
{0, 0, 0, 0}
};
@@ -1851,9 +1854,10 @@ int main(int argc, char *argv[])
global_options = NULL;
have_global_options = 0;
foreground = 0;
+ daemon_check = 1;
opterr = 0;
- while ((opt = getopt_long(argc, argv, "+hp:t:vdD:fVrO:l:n:", long_options, NULL)) != EOF) {
+ while ((opt = getopt_long(argc, argv, "+hp:t:vdD:fVrO:l:n:C", long_options, NULL)) != EOF) {
switch (opt) {
case 'h':
usage();
@@ -1922,6 +1926,10 @@ int main(int argc, char *argv[])
}
break;
+ case 'C':
+ daemon_check = 0;
+ break;
+
case '?':
case ':':
printf("%s: Ambiguous or unknown options\n", program);
@@ -1965,7 +1973,7 @@ int main(int argc, char *argv[])
exit(exit_code);
}
- if (is_automount_running() > 0) {
+ if (daemon_check && is_automount_running() > 0) {
fprintf(stderr, "%s: program is already running.\n",
program);
exit(1);
diff --git a/man/automount.8 b/man/automount.8
index 59ad50e..d9285bf 100644
--- a/man/automount.8
+++ b/man/automount.8
@@ -81,6 +81,9 @@ be disabled, returning the daemon to verbose logging.
.P
The \fIpath\fP argument corresponds to the automounted
path name as specified in the master map.
+.TP
+.I "\-C, \-\-dont-check-daemon"
+Don't check if the daemon is currently running (see NOTES).
.SH ARGUMENTS
\fBautomount\fP takes one optional argument, the name of the master map to
use.
@@ -122,6 +125,13 @@ until they are no longer in use by the processes that held them busy.
If automount managed filesystems are found mounted when autofs is
started they will be recoverd unless they are no longer present in
the map in which case they need to umounted manually.
+.P
+If the option to disable the check to see if the daemon is already
+running is used be aware that autofs currently may not function correctly
+for certain types of automount maps. The mounts of the seperate daemons
+might interfere with one another. The implications of running multiple
+daemon instances needs to be checked and tested before we can say this
+is supported.
.SH "SEE ALSO"
.BR autofs (5),
.BR autofs (8),

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,32 @@
autofs-5.0.3 - submount shutdown recovery fix
From: Ian Kent <raven@themaw.net>
I was sure I fixed this in the final patch but evidently
not.
---
daemon/direct.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/daemon/direct.c b/daemon/direct.c
index 34e882b..afb354e 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -1129,7 +1129,6 @@ int handle_packet_expire_direct(struct autofs_point *ap, autofs_packet_expire_di
*/
crit(ap->logopt, "can't find map entry for (%lu,%lu)",
(unsigned long) pkt->dev, (unsigned long) pkt->ino);
- cache_unlock(mc);
master_source_unlock(ap->entry);
pthread_setcancelstate(state, NULL);
return 1;
@@ -1374,7 +1373,6 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_
*/
logerr("can't find map entry for (%lu,%lu)",
(unsigned long) pkt->dev, (unsigned long) pkt->ino);
- cache_unlock(mc);
master_source_unlock(ap->entry);
pthread_setcancelstate(state, NULL);
return 1;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,103 @@
autofs-5.0.3 - update replicated server selection documentation
From: Ian Kent <raven@themaw.net>
Update the replicated server selection README documentation to
reflect the selection rules now used.
---
CHANGELOG | 1 +
README.replicated-server | 53 ++++++++++++++++++++++------------------------
2 files changed, 26 insertions(+), 28 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index af3318a..be39e33 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -31,6 +31,7 @@
umount during expire.
- make mount of multi-mounts wuth a root offset atomic.
- add replicated server selection debug logging.
+- update replicated server selection documentation.
14/01/2008 autofs-5.0.3
-----------------------
diff --git a/README.replicated-server b/README.replicated-server
index 333dea3..1d771d3 100644
--- a/README.replicated-server
+++ b/README.replicated-server
@@ -3,48 +3,45 @@ Supported forms for mount paths are:
Normal single-host (these are unchanged)
<path> host:/path/path
+Single host entries are not probed for a server response.
+
Multiple replicated hosts, same path:
<path> host1,host2,hostn:/path/path
-This will do an initial RPC call with a .1 second timeout to all hosts to
-find best match. If this fails, it will try a 10 second timeout, if this
-fails it takes the first host.
-
Multiple hosts, some with same path, some with another
<path> host1,host2:/blah host3:/some/other/path
-Works as expected
-
Multiple replicated hosts, different (potentially) paths:
<path> host1:/path/pathA host2:/path/pathB
-Same as above with RPC calls..
-
Mutliple weighted, replicated hosts same path:
-
<path> host1(5),host2(6),host3(1):/path/path
-Will pick lowest weighted host that responds to RPC call.
-RPC time is not counted, only whether the call got a reply
-at all. Initially does a .1 second timeout, if all hosts
-fail this, moves to 10 second timeout. If one of the hosts
-is localhost, the automounter will choose that regardless of
-its weight. (This has been done to remain compatible with
-Sun's automounter)
-
Multiple weighted, replicated hosts different (potentially)
paths:
<path> host1(3):/path/pathA host2(5):/path/pathB
-Same as above with RPC calls/weighting.
-
-Anything else is questionable and unsupported, but these
-variations will also work:
-<path> host1(3),host:/blah
-
-Unsupported and I don't know why you would use this, but will
-work. Weighted host always gets precedence if it responds to RPC
-
-Anything else, I ain't making no promises.
+For these formats a priority ordered list of hosts is created by using
+the following selection rules.
+
+1) Highest priority in selection is proximity.
+ Proximity, in order of precedence is:
+ - PROXIMITY_LOCAL, host corresponds to a local interface.
+ - PROXIMITY_SUBNET, host is located in a subnet reachable
+ through a local interface.
+ - PROXIMITY_NETWORK, host is located in a network reachable
+ through a local interface.
+ - PROXIMITY_OTHER, host is on a network not directlty
+ reachable through a local interface.
+
+2) NFS version and protocol is selected by caclculating the largest
+ number of hosts supporting an NFS version and protocol that
+ have the closest proximity. These hosts are added to the list
+ in response time order. Hosts may have a corresponding weight
+ which essentially increases response time and so influences the
+ host order.
+
+3) Hosts at further proximity that support the selected NFS version
+ and protocol are also added to the list in response time order as
+ in 2 above.
-Jason

View File

@ -0,0 +1,39 @@
autofs-5.0.3 - use /dev/urandom instead of /dev/random
From: Ian Kent <raven@themaw.net>
It has been reported that some headless systems hang when using
/dev/random. It's also been pointed out that /dev/urandom is
sufficient for the needs of autofs.
---
CHANGELOG | 1 +
modules/replicated.c | 2 +-
2 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index be39e33..50c9a27 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -32,6 +32,7 @@
- make mount of multi-mounts wuth a root offset atomic.
- add replicated server selection debug logging.
- update replicated server selection documentation.
+- use /dev/urandom instead of /dev/random.
14/01/2008 autofs-5.0.3
-----------------------
diff --git a/modules/replicated.c b/modules/replicated.c
index e41713e..362ab1b 100644
--- a/modules/replicated.c
+++ b/modules/replicated.c
@@ -79,7 +79,7 @@ void seed_random(void)
int fd;
unsigned int seed;
- fd = open("/dev/random", O_RDONLY);
+ fd = open("/dev/urandom", O_RDONLY);
if (fd < 0) {
srandom(time(NULL));
return;

View File

@ -4,7 +4,7 @@
Summary: A tool for automatically mounting and unmounting filesystems
Name: autofs
Version: 5.0.3
Release: 19
Release: 21
Epoch: 1
License: GPLv2+
Group: System Environment/Daemons
@ -32,6 +32,27 @@ Patch19: autofs-5.0.3-allow-dir-create-on-nfs-root.patch
Patch20: autofs-5.0.3-check-direct-path-len.patch
Patch21: autofs-5.0.3-fix-get-user-info-check.patch
Patch22: autofs-5.0.3-fix-couple-of-memory-leaks.patch
Patch23: autofs-5.0.3-override-is-running-check.patch
Patch24: autofs-5.0.3-dont-use-proc-for-is-running-check.patch
Patch25: autofs-5.0.3-fix-included-browse-map-not-found.patch
Patch26: autofs-5.0.3-fix-multi-source-messages.patch
Patch27: autofs-5.0.3-clear-stale-on-map-read.patch
Patch28: autofs-5.0.3-fix-proximity-other-timeout.patch
Patch29: autofs-5.0.3-refactor-mount-request-vars.patch
Patch30: autofs-5.0.3-make-handle_mounts-startup-cond-distinct.patch
Patch31: autofs-5.0.3-submount-shutdown-recovery-12.patch
Patch32: autofs-5.0.3-dont-block-on-expire.patch
Patch33: autofs-5.0.3-add-umount_wait-parameter.patch
Patch34: autofs-5.0.3-fix-multi-mount-race.patch
Patch35: autofs-5.0.3-submount-shutdown-recovery-12-fix.patch
Patch36: autofs-5.0.3-fix-nfs4-colon-escape.patch
Patch37: autofs-5.0.3-check-replicated-list-after-probe.patch
Patch38: autofs-5.0.3-add-replicated-debug-logging.patch
Patch39: autofs-5.0.3-update-replicated-doco.patch
Patch40: autofs-5.0.3-use-dev-urandom.patch
Patch41: autofs-5.0.3-mtab-as-proc-mounts.patch
Patch42: autofs-5.0.3-fix-ifc-buff-size.patch
Patch43: autofs-5.0.3-fix-percent-hack.patch
Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: autoconf, hesiod-devel, openldap-devel, bison, flex, libxml2-devel, cyrus-sasl-devel, openssl-devel module-init-tools util-linux nfs-utils e2fsprogs
Requires: kernel >= 2.6.17
@ -147,6 +168,29 @@ fi
%{_libdir}/autofs/
%changelog
* Mon Aug 25 2008 Ian Kent <ikent@redhat.com> - 5.0.3-21
- add upstream bug fix patches
- add command line option to override is running check.
- don't use proc fs for is running check.
- fix fail on included browse map not found.
- fix incorrect multi source messages.
- clear stale flag on map read.
- fix proximity other rpc ping timeout.
- refactor mount request vars code.
- make handle_mounts startup condition distinct.
- fix submount shutdown handling.
- try not to block on expire.
- add configuration paramter UMOUNT_WAIT.
- fix multi mount race.
- fix nfs4 colon escape handling.
- check replicated list after probe.
- add replicated server selection debug logging.
- update replicated server selection documentation.
- use /dev/urandom instead of /dev/random.
- check for mtab pointing to /proc/mounts.
- fix interface config buffer size.
- fix percent hack heap corruption.
* Mon Jul 14 2008 Tom "spot" Callaway <tcallawa@redhat.com> - 5.0.3-19
- change conflicts to requires
- fix license tag