diff -up autofs-5.0.3/daemon/indirect.c.active-restart autofs-5.0.3/daemon/indirect.c
--- autofs-5.0.3/daemon/indirect.c.active-restart 2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/daemon/indirect.c 2008-02-25 09:16:46.000000000 +0900
@@ -20,6 +20,7 @@
* ----------------------------------------------------------------------- */
#include <dirent.h>
+#include <libgen.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
@@ -32,9 +33,8 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/mount.h>
+#include <sys/vfs.h>
#include <sched.h>
-#include <pwd.h>
-#include <grp.h>
#include "automount.h"
@@ -43,8 +43,6 @@ extern pthread_attr_t thread_attr;
static pthread_mutex_t ma_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t ea_mutex = PTHREAD_MUTEX_INITIALIZER;
-static const unsigned int indirect = AUTOFS_TYPE_INDIRECT;
-
static int unlink_mount_tree(struct autofs_point *ap, struct mnt_list *mnts)
{
struct mnt_list *this;
@@ -90,6 +88,7 @@ static int unlink_mount_tree(struct auto
static int do_mount_autofs_indirect(struct autofs_point *ap)
{
+ const char *str_indirect = mount_type_str(indirect);
struct ioctl_ops *ops = get_ioctl_ops();
time_t timeout = ap->exp_timeout;
char *options = NULL;
@@ -98,8 +97,58 @@ static int do_mount_autofs_indirect(stru
struct mnt_list *mnts;
int ret;
- mnts = get_mnt_list(_PROC_MOUNTS, ap->path, 1);
- if (mnts) {
+ ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
+
+ if (ops->version) {
+ char device[AUTOFS_DEVID_LEN];
+ struct statfs fst;
+ int ioctlfd;
+ dev_t devid;
+ char *tmp;
+
+ if (!find_mnt_devid(_PROC_MOUNTS, ap->path, device, indirect))
+ goto cont;
+
+ devid = strtoul(device, NULL, 0);
+
+ ret = remount_active_mount(ap, NULL, ap->path, devid, indirect, &ioctlfd);
+
+ /*
+ * The directory must exist since we found a device
+ * number for the mount above but we can't know if we
+ * created it or not. However, if we're mounted on an
+ * autofs fs then we need to cleanup the path anyway.
+ */
+ ap->dir_created = 0;
+ tmp = strdup(ap->path);
+ if (tmp) {
+ if (statfs(dirname(tmp), &fst) != -1)
+ if (fst.f_type == AUTOFS_SUPER_MAGIC)
+ ap->dir_created = 1;
+ free(tmp);
+ }
+
+ /*
+ * Either we opened the mount or we're re-reading the map.
+ * If we opened the mount and ioctlfd is not -1 we have
+ * a descriptor for the indirect mount so we need to
+ * record that in the mount point struct. Otherwise we're
+ * re-reading the map.
+ */
+ if (ret == REMOUNT_SUCCESS || ret == REMOUNT_READ_MAP) {
+ if (ioctlfd != -1)
+ ap->ioctlfd = ioctlfd;
+ return 0;
+ }
+ /*
+ * Since we got the device number above a mount exists so
+ * any other failure warrants a failure return here.
+ */
+ return -1;
+ } else {
+ mnts = get_mnt_list(_PROC_MOUNTS, ap->path, 1);
+ if (!mnts)
+ goto cont;
ret = unlink_mount_tree(ap, mnts);
free_mnt_list(mnts);
if (!ret) {
@@ -109,7 +158,7 @@ static int do_mount_autofs_indirect(stru
goto out_err;
}
}
-
+cont:
options = make_options_string(ap->path, ap->kpipefd, NULL);
if (!options) {
error(ap->logopt, "options string error");
@@ -152,29 +201,21 @@ static int do_mount_autofs_indirect(stru
options = NULL;
- if (ops->open(ap->logopt, &ap->ioctlfd, -1, ap->path, indirect)) {
+ if (stat(ap->path, &st) == -1) {
+ error(ap->logopt,
+ "failed to stat mount %s", ap->path);
+ goto out_umount;
+ }
+ ap->dev = st.st_dev;
+
+ if (ops->open(ap->logopt, &ap->ioctlfd, ap->dev, ap->path, indirect)) {
crit(ap->logopt,
"failed to create ioctl fd for autofs path %s", ap->path);
goto out_umount;
}
- ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
-
ops->timeout(ap->logopt, ap->ioctlfd, &timeout);
-
- if (ap->exp_timeout)
- info(ap->logopt,
- "mounted indirect mount on %s "
- "with timeout %u, freq %u seconds", ap->path,
- (unsigned int) ap->exp_timeout,
- (unsigned int) ap->exp_runfreq);
- else
- info(ap->logopt,
- "mounted indirect mount on %s with timeouts disabled",
- ap->path);
-
- fstat(ap->ioctlfd, &st);
- ap->dev = st.st_dev; /* Device number for mount point checks */
+ notify_mount_result(ap, ap->path, str_indirect);
return 0;
@@ -636,15 +677,7 @@ static void *do_mount_indirect(void *arg
struct autofs_point *ap;
char buf[PATH_MAX + 1];
struct stat st;
- struct passwd pw;
- struct passwd *ppw = &pw;
- struct passwd **pppw = &ppw;
- struct group gr;
- struct group *pgr;
- struct group **ppgr;
- char *pw_tmp, *gr_tmp;
- struct thread_stdenv_vars *tsv;
- int len, tmplen, grplen, status, state;
+ int len, status, state;
mt = (struct pending_args *) arg;
@@ -687,125 +720,8 @@ static void *do_mount_indirect(void *arg
info(ap->logopt, "attempting to mount entry %s", buf);
- /*
- * Setup thread specific data values for macro
- * substution in map entries during the mount.
- * Best effort only as it must go ahead.
- */
+ set_tsd_user_vars(ap->logopt, mt->uid, mt->gid);
- tsv = malloc(sizeof(struct thread_stdenv_vars));
- if (!tsv)
- goto cont;
-
- tsv->uid = mt->uid;
- tsv->gid = mt->gid;
-
- /* Try to get passwd info */
-
- tmplen = sysconf(_SC_GETPW_R_SIZE_MAX);
- if (tmplen < 0) {
- error(ap->logopt, "failed to get buffer size for getpwuid_r");
- free(tsv);
- goto cont;
- }
-
- pw_tmp = malloc(tmplen + 1);
- if (!pw_tmp) {
- error(ap->logopt, "failed to malloc buffer for getpwuid_r");
- free(tsv);
- goto cont;
- }
-
- status = getpwuid_r(mt->uid, ppw, pw_tmp, tmplen, pppw);
- if (status || !ppw) {
- error(ap->logopt, "failed to get passwd info from getpwuid_r");
- free(tsv);
- free(pw_tmp);
- goto cont;
- }
-
- tsv->user = strdup(pw.pw_name);
- if (!tsv->user) {
- error(ap->logopt, "failed to malloc buffer for user");
- free(tsv);
- free(pw_tmp);
- goto cont;
- }
-
- tsv->home = strdup(pw.pw_dir);
- if (!tsv->user) {
- error(ap->logopt, "failed to malloc buffer for home");
- free(pw_tmp);
- free(tsv->user);
- free(tsv);
- goto cont;
- }
-
- free(pw_tmp);
-
- /* Try to get group info */
-
- grplen = sysconf(_SC_GETGR_R_SIZE_MAX);
- if (tmplen < 0) {
- error(ap->logopt, "failed to get buffer size for getgrgid_r");
- free(tsv->user);
- free(tsv->home);
- free(tsv);
- goto cont;
- }
-
- gr_tmp = NULL;
- tmplen = grplen;
- while (1) {
- char *tmp = realloc(gr_tmp, tmplen + 1);
- if (!tmp) {
- error(ap->logopt, "failed to malloc buffer for getgrgid_r");
- if (gr_tmp)
- free(gr_tmp);
- free(tsv->user);
- free(tsv->home);
- free(tsv);
- goto cont;
- }
- gr_tmp = tmp;
- pgr = &gr;
- ppgr = &pgr;
- status = getgrgid_r(mt->gid, pgr, gr_tmp, tmplen, ppgr);
- if (status != ERANGE)
- break;
- tmplen += grplen;
- }
-
- if (status || !pgr) {
- error(ap->logopt, "failed to get group info from getgrgid_r");
- free(tsv->user);
- free(tsv->home);
- free(tsv);
- free(gr_tmp);
- goto cont;
- }
-
- tsv->group = strdup(gr.gr_name);
- if (!tsv->group) {
- error(ap->logopt, "failed to malloc buffer for group");
- free(tsv->user);
- free(tsv->home);
- free(tsv);
- free(gr_tmp);
- goto cont;
- }
-
- free(gr_tmp);
-
- status = pthread_setspecific(key_thread_stdenv_vars, tsv);
- if (status) {
- error(ap->logopt, "failed to set stdenv thread var");
- free(tsv->group);
- free(tsv->user);
- free(tsv->home);
- free(tsv);
- }
-cont:
status = lookup_nss_mount(ap, NULL, mt->name, mt->len);
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
if (status) {
diff -up autofs-5.0.3/daemon/automount.c.active-restart autofs-5.0.3/daemon/automount.c
--- autofs-5.0.3/daemon/automount.c.active-restart 2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/daemon/automount.c 2008-02-25 09:16:46.000000000 +0900
@@ -466,7 +466,7 @@ static int umount_subtree_mounts(struct
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
/* Lock the closest parent nesting point for umount */
- cache_multi_lock(me->parent);
+ cache_multi_writelock(me->parent);
if (umount_multi_triggers(ap, root, me, base)) {
warn(ap->logopt,
"some offset mounts still present under %s", path);
@@ -1412,6 +1412,55 @@ static void mutex_operation_wait(pthread
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;
@@ -1463,17 +1512,20 @@ static void handle_mounts_cleanup(void *
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);
@@ -1481,7 +1533,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);
@@ -1491,7 +1543,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
@@ -1948,7 +2000,9 @@ int main(int argc, char *argv[])
if (!query_kproto_ver() || get_kver_major() < 5) {
fprintf(stderr,
- "%s: kernel protocol version 5.00 or above required.\n",
+ "%s: test mount forbidden or "
+ "incorrect kernel protocol version, "
+ "kernel protocol version 5.00 or above required.\n",
program);
exit(1);
}
diff -up autofs-5.0.3/daemon/direct.c.active-restart autofs-5.0.3/daemon/direct.c
--- autofs-5.0.3/daemon/direct.c.active-restart 2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/daemon/direct.c 2008-02-25 09:16:46.000000000 +0900
@@ -20,6 +20,7 @@
* ----------------------------------------------------------------------- */
#include <dirent.h>
+#include <libgen.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
@@ -35,16 +36,11 @@
#include <sys/mount.h>
#include <sys/vfs.h>
#include <sched.h>
-#include <pwd.h>
-#include <grp.h>
#include "automount.h"
extern pthread_attr_t thread_attr;
-static const unsigned int direct = AUTOFS_TYPE_DIRECT;
-static const unsigned int offset = AUTOFS_TYPE_OFFSET;
-
struct mnt_params {
char *options;
};
@@ -287,15 +283,11 @@ static int unlink_mount_tree(struct auto
return ret;
}
-int do_mount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me)
+static int unlink_active_mounts(struct autofs_point *ap,
+ struct mnt_list *mnts, struct mapent *me)
{
struct ioctl_ops *ops = get_ioctl_ops();
- struct mnt_params *mp;
- time_t timeout = ap->exp_timeout;
- struct stat st;
- int status, ret, ioctlfd;
struct list_head list;
- const char *map_name;
INIT_LIST_HEAD(&list);
@@ -313,7 +305,7 @@ int do_mount_autofs_direct(struct autofs
error(ap->logopt,
"failed to create ioctl fd for %s",
me->key);
- return 0;
+ return 1;
}
ops->timeout(ap->logopt, ioctlfd, &tout);
@@ -321,22 +313,99 @@ int do_mount_autofs_direct(struct autofs
if (save_ioctlfd == -1)
ops->close(ap->logopt, ioctlfd);
- return 0;
+ return 1;
}
if (!unlink_mount_tree(ap, &list)) {
debug(ap->logopt,
"already mounted as other than autofs "
"or failed to unlink entry in tree");
- return -1;
+ return 0;
}
}
+ return 1;
+}
- if (me->ioctlfd != -1) {
- error(ap->logopt, "active direct mount %s", me->key);
- return -1;
- }
+int do_mount_autofs_direct(struct autofs_point *ap, struct mnt_list *mnts, struct mapent *me)
+{
+ const char *str_direct = mount_type_str(direct);
+ struct ioctl_ops *ops = get_ioctl_ops();
+ struct mnt_params *mp;
+ time_t timeout = ap->exp_timeout;
+ struct stat st;
+ int status, ret, ioctlfd;
+ const char *map_name;
+
+ /* Calculate the timeouts */
+ ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
+
+ if (ops->version) {
+ char device[AUTOFS_DEVID_LEN];
+ struct statfs fst;
+ dev_t devid;
+ char *tmp;
+
+ /* Mount in mount table */
+ if (!tree_find_mnt_devid(mnts, me->key, device, direct))
+ goto cont;
+
+ devid = strtoul(device, NULL, 0);
+
+ ret = remount_active_mount(ap, me->mc,
+ me->key, devid, direct,
+ &ioctlfd);
+
+ /*
+ * The directory must exist since we found a device
+ * number for the mount above but we can't know if we
+ * created it or not. However, if we're mounted on an
+ * autofs fs then we need to cleanup the path anyway.
+ */
+ me->dir_created = 0;
+ tmp = strdup(me->key);
+ if (tmp) {
+ if (statfs(dirname(tmp), &fst) != -1)
+ if (fst.f_type == AUTOFS_SUPER_MAGIC)
+ me->dir_created = 1;
+ free(tmp);
+ }
+
+ /*
+ * Either we opened the mount or we're re-reading the map.
+ * If we opened the mount and ioctlfd is not -1 we have an
+ * active mount so we need to record the descriptor in the
+ * cache entry. Otherwise there is no active mount or we're
+ * re-reading the map.
+ */
+ if (ret == REMOUNT_SUCCESS || ret == REMOUNT_READ_MAP) {
+ if (ioctlfd != -1)
+ me->ioctlfd = ioctlfd;
+ return 0;
+ }
+
+ /*
+ * Since we got the device number above a mount exists so
+ * any other failure warrants a failure return here.
+ */
+ goto out_err;
+ } else {
+ /*
+ * A return of 1 indicates we're re-reading the map
+ * or we successfully unlinked the mount tree if it
+ * there was one. A return of zero inducates we
+ * failed to unlink the mount tree so we have to
+ * return a failure.
+ */
+ ret = unlink_active_mounts(ap, mnts, me);
+ if (ret == 0)
+ return -1;
+ if (me->ioctlfd != -1) {
+ error(ap->logopt, "active direct mount %s", me->key);
+ return -1;
+ }
+ }
+cont:
status = pthread_once(&key_mnt_params_once, key_mnt_params_init);
if (status)
fatal(status);
@@ -388,44 +457,27 @@ int do_mount_autofs_direct(struct autofs
goto out_err;
}
- ops->open(ap->logopt, &ioctlfd, -1, me->key, direct);
+ if (stat(me->key, &st) == -1) {
+ error(ap->logopt,
+ "failed to stat direct mount trigger %s", me->key);
+ goto out_umount;
+ }
+
+ ops->open(ap->logopt, &ioctlfd, st.st_dev, me->key, direct);
if (ioctlfd < 0) {
crit(ap->logopt, "failed to create ioctl fd for %s", me->key);
goto out_umount;
}
- /* Calculate the timeouts */
- ap->exp_runfreq = (timeout + CHECK_RATIO - 1) / CHECK_RATIO;
-
ops->timeout(ap->logopt, ioctlfd, &timeout);
-
- if (ap->exp_timeout)
- info(ap->logopt,
- "mounted direct mount on %s "
- "with timeout %u, freq %u seconds", me->key,
- (unsigned int) ap->exp_timeout,
- (unsigned int) ap->exp_runfreq);
- else
- info(ap->logopt,
- "mounted direct mount on %s with timeouts disabled",
- me->key);
-
- ret = fstat(ioctlfd, &st);
- if (ret == -1) {
- error(ap->logopt,
- "failed to stat direct mount trigger %s", me->key);
- goto out_close;
- }
+ notify_mount_result(ap, me->key, str_direct);
cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino);
-
ops->close(ap->logopt, ioctlfd);
debug(ap->logopt, "mounted trigger %s", me->key);
return 0;
-out_close:
- ops->close(ap->logopt, ioctlfd);
out_umount:
/* TODO: maybe force umount (-l) */
umount(me->key);
@@ -462,8 +514,6 @@ int mount_autofs_direct(struct autofs_po
pthread_cleanup_push(master_source_lock_cleanup, ap->entry);
master_source_readlock(ap->entry);
nc = ap->entry->master->nc;
- cache_readlock(nc);
- pthread_cleanup_push(cache_lock_cleanup, nc);
map = ap->entry->maps;
while (map) {
/*
@@ -476,8 +526,6 @@ int mount_autofs_direct(struct autofs_po
}
mc = map->mc;
- pthread_cleanup_push(cache_lock_cleanup, mc);
- cache_readlock(mc);
me = cache_enumerate(mc, NULL);
while (me) {
ne = cache_lookup_distinct(nc, me->key);
@@ -505,12 +553,10 @@ int mount_autofs_direct(struct autofs_po
me = cache_enumerate(mc, me);
}
- pthread_cleanup_pop(1);
map = map->next;
}
pthread_cleanup_pop(1);
pthread_cleanup_pop(1);
- pthread_cleanup_pop(1);
return 0;
}
@@ -627,6 +673,7 @@ force_umount:
int mount_autofs_offset(struct autofs_point *ap, struct mapent *me)
{
+ const char *str_offset = mount_type_str(offset);
struct ioctl_ops *ops = get_ioctl_ops();
char buf[MAX_ERR_BUF];
struct mnt_params *mp;
@@ -635,18 +682,68 @@ int mount_autofs_offset(struct autofs_po
int ioctlfd, status, ret;
const char *type, *map_name = NULL;
- if (is_mounted(_PROC_MOUNTS, me->key, MNTS_AUTOFS)) {
- if (ap->state != ST_READMAP)
- warn(ap->logopt,
- "trigger %s already mounted", me->key);
- return 0;
- }
+ if (ops->version) {
+ char device[AUTOFS_DEVID_LEN];
+ struct statfs fst;
+ dev_t devid;
+ char *tmp;
- if (me->ioctlfd != -1) {
- error(ap->logopt, "active offset mount %s", me->key);
- return -1;
- }
+ /* If we can find it it's mounted */
+ if (!find_mnt_devid(_PROC_MOUNTS, me->key, device, offset))
+ goto cont;
+
+ devid = strtoul(device, NULL, 0);
+
+ ret = remount_active_mount(ap, me->mc,
+ me->key, devid, offset,
+ &ioctlfd);
+
+ /*
+ * The directory must exist since we found a device
+ * number for the mount above but we can't know if we
+ * created it or not. However, if we're mounted on an
+ * autofs fs then we need to cleanup the path anyway.
+ */
+ me->dir_created = 0;
+ tmp = strdup(me->key);
+ if (tmp) {
+ if (statfs(dirname(tmp), &fst) != -1)
+ if (fst.f_type == AUTOFS_SUPER_MAGIC)
+ me->dir_created = 1;
+ free(tmp);
+ }
+
+ /*
+ * Either we opened the mount or we're re-reading the map.
+ * If we opened the mount and ioctlfd is not -1 we have an
+ * active mount so we need to record the descriptor in the
+ * cache entry. Otherwise there is no active mount or we're
+ * re-reading the map.
+ */
+ if (ret == REMOUNT_SUCCESS || ret == REMOUNT_READ_MAP) {
+ if (ioctlfd != -1)
+ me->ioctlfd = ioctlfd;
+ return 0;
+ }
+ /*
+ * Since we got the device number above a mount exists so
+ * any other failure warrants a failure return here.
+ */
+ goto out_err;
+ } else {
+ if (is_mounted(_PROC_MOUNTS, me->key, MNTS_AUTOFS)) {
+ if (ap->state != ST_READMAP)
+ warn(ap->logopt,
+ "trigger %s already mounted", me->key);
+ return 0;
+ }
+ if (me->ioctlfd != -1) {
+ error(ap->logopt, "active offset mount %s", me->key);
+ return -1;
+ }
+ }
+cont:
status = pthread_once(&key_mnt_params_once, key_mnt_params_init);
if (status)
fatal(status);
@@ -670,7 +767,7 @@ int mount_autofs_offset(struct autofs_po
}
if (!mp->options) {
- mp->options = make_options_string(ap->path, ap->kpipefd, "offset");
+ mp->options = make_options_string(ap->path, ap->kpipefd, str_offset);
if (!mp->options)
return 0;
}
@@ -724,34 +821,28 @@ int mount_autofs_offset(struct autofs_po
map_name = me->mc->map->argv[0];
ret = mount(map_name, me->key, "autofs", MS_MGC_VAL, mp->options);
- if (ret) {
- crit(ap->logopt, "failed to mount autofs path %s", me->key);
- goto out_err;
- }
-
if (ret != 0) {
crit(ap->logopt,
"failed to mount autofs offset trigger %s", me->key);
goto out_err;
}
- ops->open(ap->logopt, &ioctlfd, -1, me->key, offset);
- if (ioctlfd < 0) {
- crit(ap->logopt, "failed to create ioctl fd for %s", me->key);
- goto out_umount;
- }
-
- ops->timeout(ap->logopt, ioctlfd, &timeout);
-
- ret = fstat(ioctlfd, &st);
+ ret = stat(me->key, &st);
if (ret == -1) {
error(ap->logopt,
"failed to stat direct mount trigger %s", me->key);
goto out_close;
}
- cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino);
+ ops->open(ap->logopt, &ioctlfd, st.st_dev, me->key, offset);
+ if (ioctlfd < 0) {
+ crit(ap->logopt, "failed to create ioctl fd for %s", me->key);
+ goto out_umount;
+ }
+ ops->timeout(ap->logopt, ioctlfd, &timeout);
+ notify_mount_result(ap, me->key, str_offset);
+ cache_set_ino_index(me->mc, me->key, st.st_dev, st.st_ino);
ops->close(ap->logopt, ioctlfd);
debug(ap->logopt, "mounted trigger %s", me->key);
@@ -1072,7 +1163,6 @@ int handle_packet_expire_direct(struct a
return 1;
}
-
mt = malloc(sizeof(struct pending_args));
if (!mt) {
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
@@ -1155,15 +1245,6 @@ static void *do_mount_direct(void *arg)
struct ioctl_ops *ops = get_ioctl_ops();
struct pending_args *mt;
struct autofs_point *ap;
- struct passwd pw;
- struct passwd *ppw = &pw;
- struct passwd **pppw = &ppw;
- struct group gr;
- struct group *pgr;
- struct group **ppgr;
- char *pw_tmp, *gr_tmp;
- struct thread_stdenv_vars *tsv;
- int tmplen, grplen;
struct stat st;
int status, state;
@@ -1209,126 +1290,8 @@ static void *do_mount_direct(void *arg)
info(ap->logopt, "attempting to mount entry %s", mt->name);
- /*
- * Setup thread specific data values for macro
- * substution in map entries during the mount.
- * Best effort only as it must go ahead.
- */
+ set_tsd_user_vars(ap->logopt, mt->uid, mt->gid);
- tsv = malloc(sizeof(struct thread_stdenv_vars));
- if (!tsv)
- goto cont;
-
- tsv->uid = mt->uid;
- tsv->gid = mt->gid;
-
- /* Try to get passwd info */
-
- tmplen = sysconf(_SC_GETPW_R_SIZE_MAX);
- if (tmplen < 0) {
- error(ap->logopt, "failed to get buffer size for getpwuid_r");
- free(tsv);
- goto cont;
- }
-
- pw_tmp = malloc(tmplen + 1);
- if (!pw_tmp) {
- error(ap->logopt, "failed to malloc buffer for getpwuid_r");
- free(tsv);
- goto cont;
- }
-
- status = getpwuid_r(mt->uid, ppw, pw_tmp, tmplen, pppw);
- if (status || !ppw) {
- error(ap->logopt, "failed to get passwd info from getpwuid_r");
- free(tsv);
- free(pw_tmp);
- goto cont;
- }
-
- tsv->user = strdup(pw.pw_name);
- if (!tsv->user) {
- error(ap->logopt, "failed to malloc buffer for user");
- free(tsv);
- free(pw_tmp);
- goto cont;
- }
-
- tsv->home = strdup(pw.pw_dir);
- if (!tsv->user) {
- error(ap->logopt, "failed to malloc buffer for home");
- free(pw_tmp);
- free(tsv->user);
- free(tsv);
- goto cont;
- }
-
- free(pw_tmp);
-
- /* Try to get group info */
-
- grplen = sysconf(_SC_GETGR_R_SIZE_MAX);
- if (tmplen < 0) {
- error(ap->logopt, "failed to get buffer size for getgrgid_r");
- free(tsv->user);
- free(tsv->home);
- free(tsv);
- goto cont;
- }
-
- gr_tmp = NULL;
- tmplen = grplen;
- while (1) {
- char *tmp = realloc(gr_tmp, tmplen + 1);
- if (!tmp) {
- error(ap->logopt, "failed to malloc buffer for getgrgid_r");
- if (gr_tmp)
- free(gr_tmp);
- free(tsv->user);
- free(tsv->home);
- free(tsv);
- goto cont;
- }
- gr_tmp = tmp;
- pgr = &gr;
- ppgr = &pgr;
- status = getgrgid_r(mt->gid, pgr, gr_tmp, tmplen, ppgr);
- if (status != ERANGE)
- break;
- tmplen += grplen;
- }
-
- if (status || !pgr) {
- error(ap->logopt, "failed to get group info from getgrgid_r");
- free(tsv->user);
- free(tsv->home);
- free(tsv);
- free(gr_tmp);
- goto cont;
- }
-
- tsv->group = strdup(gr.gr_name);
- if (!tsv->group) {
- error(ap->logopt, "failed to malloc buffer for group");
- free(tsv->user);
- free(tsv->home);
- free(tsv);
- free(gr_tmp);
- goto cont;
- }
-
- free(gr_tmp);
-
- status = pthread_setspecific(key_thread_stdenv_vars, tsv);
- if (status) {
- error(ap->logopt, "failed to set stdenv thread var");
- free(tsv->group);
- free(tsv->user);
- free(tsv->home);
- free(tsv);
- }
-
-cont:
status = lookup_nss_mount(ap, NULL, mt->name, strlen(mt->name));
/*
* Direct mounts are always a single mount. If it fails there's
diff -up autofs-5.0.3/daemon/lookup.c.active-restart autofs-5.0.3/daemon/lookup.c
--- autofs-5.0.3/daemon/lookup.c.active-restart 2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/daemon/lookup.c 2008-02-25 09:16:46.000000000 +0900
@@ -898,7 +898,8 @@ int lookup_nss_mount(struct autofs_point
map = map->next;
}
- send_map_update_request(ap);
+ if (ap->state != ST_INIT)
+ send_map_update_request(ap);
pthread_cleanup_pop(1);
return !result;
diff -up autofs-5.0.3/include/parse_subs.h.active-restart autofs-5.0.3/include/parse_subs.h
--- autofs-5.0.3/include/parse_subs.h.active-restart 2008-01-14 13:39:16.000000000 +0900
+++ autofs-5.0.3/include/parse_subs.h 2008-02-25 09:16:46.000000000 +0900
@@ -27,8 +27,5 @@ int strmcmp(const char *, const char *,
char *dequote(const char *, int, unsigned int);
int span_space(const char *, unsigned int);
char *sanitize_path(const char *, int, unsigned int, unsigned int);
-int umount_ent(struct autofs_point *, const char *);
-int mount_multi_triggers(struct autofs_point *, char *, struct mapent *, const char *);
-int umount_multi_triggers(struct autofs_point *, char *, struct mapent *, const char *);
#endif
diff -up autofs-5.0.3/include/automount.h.active-restart autofs-5.0.3/include/automount.h
--- autofs-5.0.3/include/automount.h.active-restart 2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/include/automount.h 2008-02-25 09:16:46.000000000 +0900
@@ -29,6 +29,7 @@
#include "log.h"
#include "rpc_subs.h"
#include "parse_subs.h"
+#include "mounts.h"
#include "dev-ioctl-lib.h"
#ifdef WITH_DMALLOC
@@ -71,10 +72,6 @@ int load_autofs4_module(void);
#define SMB_SUPER_MAGIC 0x0000517BL
#define CIFS_MAGIC_NUMBER 0xFF534D42L
-#define AUTOFS_TYPE_INDIRECT 0x0001
-#define AUTOFS_TYPE_DIRECT 0x0002
-#define AUTOFS_TYPE_OFFSET 0x0004
-
/* This sould be enough for at least 20 host aliases */
#define HOST_ENT_BUF_SIZE 2048
@@ -146,7 +143,7 @@ struct mapent_cache {
struct mapent {
struct mapent *next;
struct list_head ino_index;
- pthread_mutex_t multi_mutex;
+ pthread_rwlock_t multi_rwlock;
struct list_head multi_list;
struct mapent_cache *mc;
struct map_source *source;
@@ -189,7 +186,8 @@ int cache_add_offset(struct mapent_cache
int cache_set_parents(struct mapent *mm);
int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key, const char *mapent, time_t age);
int cache_delete(struct mapent_cache *mc, const char *key);
-void cache_multi_lock(struct mapent *me);
+void cache_multi_readlock(struct mapent *me);
+void cache_multi_writelock(struct mapent *me);
void cache_multi_unlock(struct mapent *me);
int cache_delete_offset_list(struct mapent_cache *mc, const char *key);
void cache_release(struct map_source *map);
@@ -328,62 +326,6 @@ int cat_path(char *buf, size_t len, cons
int ncat_path(char *buf, size_t len,
const char *dir, const char *base, size_t blen);
-/* mount table utilities */
-
-#define MNTS_ALL 0x0001
-#define MNTS_REAL 0x0002
-#define MNTS_AUTOFS 0x0004
-
-struct mnt_list {
- char *path;
- char *fs_name;
- char *fs_type;
- char *opts;
- pid_t owner;
- /*
- * List operations ie. get_mnt_list.
- */
- struct mnt_list *next;
- /*
- * Tree operations ie. tree_make_tree,
- * tree_get_mnt_list etc.
- */
- struct mnt_list *left;
- struct mnt_list *right;
- struct list_head self;
- struct list_head list;
- struct list_head entries;
- struct list_head sublist;
- /*
- * Offset mount handling ie. add_ordered_list
- * and get_offset.
- */
- struct list_head ordered;
-};
-
-unsigned int query_kproto_ver(void);
-unsigned int get_kver_major(void);
-unsigned int get_kver_minor(void);
-char *make_options_string(char *path, int kernel_pipefd, char *extra);
-char *make_mnt_name_string(char *path);
-struct mnt_list *get_mnt_list(const char *table, const char *path, int include);
-struct mnt_list *reverse_mnt_list(struct mnt_list *list);
-void free_mnt_list(struct mnt_list *list);
-int contained_in_local_fs(const char *path);
-int is_mounted(const char *table, const char *path, unsigned int type);
-int has_fstab_option(const char *opt);
-int find_mnt_devid(const char *table, const char *path, char *devid, unsigned int type);
-char *get_offset(const char *prefix, char *offset,
- struct list_head *head, struct list_head **pos);
-void add_ordered_list(struct mnt_list *ent, struct list_head *head);
-void tree_free_mnt_tree(struct mnt_list *tree);
-struct mnt_list *tree_make_mnt_tree(const char *table, const char *path);
-int tree_get_mnt_list(struct mnt_list *mnts, struct list_head *list, const char *path, int include);
-int tree_get_mnt_sublist(struct mnt_list *mnts, struct list_head *list, const char *path, int include);
-int tree_find_mnt_ents(struct mnt_list *mnts, struct list_head *list, const char *path);
-int tree_is_mounted(struct mnt_list *mnts, const char *path, unsigned int type);
-int tree_find_mnt_devid(struct mnt_list *mnts, const char *path, char *devid, unsigned int type);
-
/* Core automount definitions */
#define MNT_DETACH 0x00000002 /* Just detach from the tree */
@@ -391,10 +333,14 @@ int tree_find_mnt_devid(struct mnt_list
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 -up autofs-5.0.3/modules/mount_ext2.c.active-restart autofs-5.0.3/modules/mount_ext2.c
--- autofs-5.0.3/modules/mount_ext2.c.active-restart 2008-01-14 13:39:16.000000000 +0900
+++ autofs-5.0.3/modules/mount_ext2.c 2008-02-25 09:16:46.000000000 +0900
@@ -84,8 +84,9 @@ int mount_mount(struct autofs_point *ap,
existed = 0;
if (is_mounted(_PATH_MOUNTED, fullpath, MNTS_REAL)) {
- error(ap->logopt,
- MODPREFIX "warning: %s is already mounted", fullpath);
+ info(ap->logopt, MODPREFIX
+ "%s is already mounted or is bieng re-mounted",
+ fullpath);
return 0;
}
diff -up autofs-5.0.3/modules/mount_generic.c.active-restart autofs-5.0.3/modules/mount_generic.c
--- autofs-5.0.3/modules/mount_generic.c.active-restart 2008-01-14 13:39:16.000000000 +0900
+++ autofs-5.0.3/modules/mount_generic.c 2008-02-25 09:16:46.000000000 +0900
@@ -83,8 +83,9 @@ int mount_mount(struct autofs_point *ap,
existed = 0;
if (is_mounted(_PATH_MOUNTED, fullpath, MNTS_REAL)) {
- error(ap->logopt,
- MODPREFIX "warning: %s is already mounted", fullpath);
+ info(ap->logopt, MODPREFIX
+ "%s is already mounted or is being re-mounted",
+ fullpath);
return 0;
}
diff -up autofs-5.0.3/modules/mount_autofs.c.active-restart autofs-5.0.3/modules/mount_autofs.c
--- autofs-5.0.3/modules/mount_autofs.c.active-restart 2008-01-14 13:39:16.000000000 +0900
+++ autofs-5.0.3/modules/mount_autofs.c 2008-02-25 09:16:46.000000000 +0900
@@ -46,6 +46,7 @@ int mount_mount(struct autofs_point *ap,
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;
@@ -216,27 +217,26 @@ int mount_mount(struct autofs_point *ap,
mounts_mutex_lock(ap);
- status = pthread_mutex_lock(&suc.mutex);
- if (status) {
- crit(ap->logopt,
- MODPREFIX "failed to lock startup condition mutex!");
+ 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);
cache_release(source);
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, NULL, handle_mounts, &suc)) {
crit(ap->logopt,
MODPREFIX
"failed to create mount handler thread for %s",
fullpath);
mounts_mutex_unlock(ap);
- status = pthread_mutex_unlock(&suc.mutex);
- if (status)
- fatal(status);
+ handle_mounts_startup_cond_destroy(&suc);
cache_release(source);
master_free_mapent(entry);
return 1;
@@ -247,7 +247,7 @@ int mount_mount(struct autofs_point *ap,
status = pthread_cond_wait(&suc.cond, &suc.mutex);
if (status) {
mounts_mutex_unlock(ap);
- pthread_mutex_unlock(&suc.mutex);
+ handle_mounts_startup_cond_destroy(&suc);
fatal(status);
}
}
@@ -256,9 +256,7 @@ int mount_mount(struct autofs_point *ap,
crit(ap->logopt,
MODPREFIX "failed to create submount for %s", fullpath);
mounts_mutex_unlock(ap);
- status = pthread_mutex_unlock(&suc.mutex);
- if (status)
- fatal(status);
+ handle_mounts_startup_cond_destroy(&suc);
master_free_mapent(entry);
return 1;
}
@@ -266,12 +264,9 @@ int mount_mount(struct autofs_point *ap,
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;
}
diff -up autofs-5.0.3/modules/mount_nfs.c.active-restart autofs-5.0.3/modules/mount_nfs.c
--- autofs-5.0.3/modules/mount_nfs.c.active-restart 2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/modules/mount_nfs.c 2008-02-25 09:16:46.000000000 +0900
@@ -198,10 +198,10 @@ int mount_mount(struct autofs_point *ap,
char *loc, *port_opt = NULL;
if (is_mounted(_PATH_MOUNTED, fullpath, MNTS_REAL)) {
- error(ap->logopt,
- MODPREFIX
- "warning: %s is already mounted", fullpath);
- break;
+ info(ap->logopt, MODPREFIX
+ "%s is already mounted or is being re-mounted", fullpath);
+ free_host_list(&hosts);
+ return 0;
}
/*
diff -up autofs-5.0.3/modules/parse_sun.c.active-restart autofs-5.0.3/modules/parse_sun.c
--- autofs-5.0.3/modules/parse_sun.c.active-restart 2008-01-14 13:39:16.000000000 +0900
+++ autofs-5.0.3/modules/parse_sun.c 2008-02-25 09:16:46.000000000 +0900
@@ -968,8 +968,6 @@ static int mount_subtree_offsets(struct
if (!mm)
return 0;
- cache_multi_lock(me->parent);
-
m_key = mm->key;
if (*m_key == '/') {
@@ -999,8 +997,6 @@ static int mount_subtree_offsets(struct
return -1;
}
- cache_multi_unlock(me->parent);
-
return ret;
}
@@ -1197,7 +1193,7 @@ int parse_mount(struct autofs_point *ap,
* us to fail on the check for duplicate offsets in
* we don't know when submounts go away.
*/
- cache_multi_lock(me);
+ cache_multi_writelock(me);
cache_delete_offset_list(mc, name);
cache_multi_unlock(me);
}
@@ -1220,7 +1216,7 @@ int parse_mount(struct autofs_point *ap,
}
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
- cache_multi_lock(me);
+ cache_multi_writelock(me);
/* It's a multi-mount; deal with it */
do {
char *path, *myoptions, *loc;
@@ -1296,6 +1292,10 @@ int parse_mount(struct autofs_point *ap,
*/
cache_set_parents(me);
+ /* Added multi-mount cache entries, down grade lock */
+ cache_multi_unlock(me);
+ cache_multi_readlock(me);
+
/* Mount root offset if it exists */
ro = cache_lookup_offset("/", "/", strlen(m_root), &me->multi_list);
if (ro) {
@@ -1468,10 +1468,14 @@ mount_it:
cache_readlock(mc);
me = cache_lookup_distinct(mc, name);
if (me) {
- int ret = mount_subtree_offsets(ap, mc, me);
+ int ret;
+
+ cache_multi_readlock(me->parent);
+ ret = mount_subtree_offsets(ap, mc, me);
/* Convert fail on nonstrict, non-empty multi-mount to success */
if (rv < 0 && ret > 0)
rv = 0;
+ cache_multi_unlock(me->parent);
}
cache_unlock(mc);
pthread_setcancelstate(cur_state, NULL);
diff -up autofs-5.0.3/modules/mount_bind.c.active-restart autofs-5.0.3/modules/mount_bind.c
--- autofs-5.0.3/modules/mount_bind.c.active-restart 2008-01-14 13:39:16.000000000 +0900
+++ autofs-5.0.3/modules/mount_bind.c 2008-02-25 09:16:46.000000000 +0900
@@ -126,8 +126,8 @@ int mount_mount(struct autofs_point *ap,
existed = 0;
if (is_mounted(_PATH_MOUNTED, fullpath, MNTS_REAL)) {
- error(ap->logopt,
- MODPREFIX "warning: %s is already mounted",
+ info(ap->logopt, MODPREFIX
+ "%s is already mounted or is being re-mounted",
fullpath);
return 0;
}
diff -up autofs-5.0.3/lib/parse_subs.c.active-restart autofs-5.0.3/lib/parse_subs.c
--- autofs-5.0.3/lib/parse_subs.c.active-restart 2008-01-14 13:39:16.000000000 +0900
+++ autofs-5.0.3/lib/parse_subs.c 2008-02-25 09:16:46.000000000 +0900
@@ -18,10 +18,7 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
#include <unistd.h>
-#include <sys/vfs.h>
#include "automount.h"
/*
@@ -304,220 +301,3 @@ char *sanitize_path(const char *path, in
return s_path;
}
-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);
- }
-
- /* 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);
- }
-
- /*
- * Verify that we actually unmounted the thing. This is a
- * belt and suspenders approach to not eating user data.
- * We have seen cases where umount succeeds, but there is
- * still a file system mounted on the mount point. How
- * this happens has not yet been determined, but we want to
- * make sure to return failure here, if that is the case,
- * so that we do not try to call rmdir_path on the
- * directory.
- */
- if (!rv && is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) {
- crit(ap->logopt,
- "the umount binary reported that %s was "
- "unmounted, but there is still something "
- "mounted on this path.", path);
- rv = -1;
- }
- }
-
- return rv;
-}
-
-int mount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, const char *base)
-{
- char path[PATH_MAX + 1];
- char *offset = path;
- struct mapent *oe;
- struct list_head *pos = NULL;
- unsigned int fs_path_len;
- unsigned int mounted;
- int start;
-
- fs_path_len = strlen(root) + strlen(base);
- if (fs_path_len > PATH_MAX)
- return -1;
-
- strcpy(path, root);
- strcat(path, base);
-
- mounted = 0;
- start = strlen(root);
- offset = cache_get_offset(base, offset, start, &me->multi_list, &pos);
- while (offset) {
- int plen = fs_path_len + strlen(offset);
-
- if (plen > PATH_MAX) {
- warn(ap->logopt, "path loo long");
- goto cont;
- }
-
- oe = cache_lookup_offset(base, offset, start, &me->multi_list);
- if (!oe)
- goto cont;
-
- debug(ap->logopt, "mount offset %s", oe->key);
-
- if (mount_autofs_offset(ap, oe) < 0)
- warn(ap->logopt, "failed to mount offset");
- else
- mounted++;
-cont:
- offset = cache_get_offset(base,
- offset, start, &me->multi_list, &pos);
- }
-
- return mounted;
-}
-
-int umount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, const char *base)
-{
- char path[PATH_MAX + 1];
- char *offset;
- struct mapent *oe;
- struct list_head *mm_root, *pos;
- const char o_root[] = "/";
- const char *mm_base;
- int left, start;
-
- left = 0;
- start = strlen(root);
-
- mm_root = &me->multi->multi_list;
-
- if (!base)
- mm_base = o_root;
- else
- mm_base = base;
-
- pos = NULL;
- offset = path;
-
- /* Make sure "none" of the offsets have an active mount. */
- while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
- char *oe_base;
-
- oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
- /* root offset is a special case */
- if (!oe || (strlen(oe->key) - start) == 1)
- continue;
-
- /*
- * Check for and umount subtree offsets resulting from
- * nonstrict mount fail.
- */
- oe_base = oe->key + strlen(root);
- left += umount_multi_triggers(ap, root, oe, oe_base);
-
- if (oe->ioctlfd != -1)
- left++;
- }
-
- if (left)
- return left;
-
- pos = NULL;
- offset = path;
-
- /* Make sure "none" of the offsets have an active mount. */
- while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
- oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
- /* root offset is a special case */
- if (!oe || (strlen(oe->key) - start) == 1)
- continue;
-
- debug(ap->logopt, "umount offset %s", oe->key);
-
- if (umount_autofs_offset(ap, oe)) {
- warn(ap->logopt, "failed to umount offset");
- left++;
- }
- }
-
- if (!left && me->multi == me) {
- struct mapent_cache *mc = me->mc;
- int status;
-
- /*
- * Special case.
- * If we can't umount the root container then we can't
- * delete the offsets from the cache and we need to put
- * the offset triggers back.
- */
- if (is_mounted(_PATH_MOUNTED, root, MNTS_REAL)) {
- info(ap->logopt, "unmounting dir = %s", root);
- if (umount_ent(ap, root)) {
- if (!mount_multi_triggers(ap, root, me, "/"))
- warn(ap->logopt,
- "failed to remount offset triggers");
- return left++;
- }
- }
-
- /* We're done - clean out the offsets */
- status = cache_delete_offset_list(mc, me->key);
- if (status != CHE_OK)
- warn(ap->logopt, "couldn't delete offset list");
- }
-
- return left;
-}
-
diff -up autofs-5.0.3/lib/mounts.c.active-restart autofs-5.0.3/lib/mounts.c
--- autofs-5.0.3/lib/mounts.c.active-restart 2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/lib/mounts.c 2008-02-25 09:16:46.000000000 +0900
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * mounts.c - module for Linux automount mount table lookup functions
+ * mounts.c - module for mount utilities.
*
* Copyright 2002-2005 Ian Kent <raven@themaw.net> - All Rights Reserved
*
@@ -23,12 +23,21 @@
#include <fcntl.h>
#include <sys/mount.h>
#include <stdio.h>
+#include <dirent.h>
+#include <sys/vfs.h>
+#include <pwd.h>
+#include <grp.h>
#include "automount.h"
#define MAX_OPTIONS_LEN 80
#define MAX_MNT_NAME_LEN 30
+const unsigned int indirect = AUTOFS_TYPE_INDIRECT;
+const unsigned int direct = AUTOFS_TYPE_DIRECT;
+const unsigned int offset = AUTOFS_TYPE_OFFSET;
+const unsigned int type_count = 3;
+
static const char options_template[] = "fd=%d,pgrp=%u,minproto=5,maxproto=%d";
static const char options_template_extra[] = "fd=%d,pgrp=%u,minproto=5,maxproto=%d,%s";
static const char mnt_name_template[] = "automount(pid%u)";
@@ -466,7 +475,7 @@ int has_fstab_option(const char *opt)
* super block when searching for the mount.
*/
int find_mnt_devid(const char *table,
- const char *path, char *devid, unsigned int type)
+ const char *path, char *devid, const unsigned int type)
{
struct mntent *mnt;
struct mntent mnt_wrk;
@@ -1070,3 +1079,528 @@ int tree_find_mnt_devid(struct mnt_list
return 1;
}
+void set_tsd_user_vars(unsigned int logopt, uid_t uid, gid_t gid)
+{
+ struct thread_stdenv_vars *tsv;
+ struct passwd pw;
+ struct passwd *ppw = &pw;
+ struct passwd **pppw = &ppw;
+ struct group gr;
+ struct group *pgr;
+ struct group **ppgr;
+ char *pw_tmp, *gr_tmp;
+ int status, tmplen, grplen;
+
+ /*
+ * Setup thread specific data values for macro
+ * substution in map entries during the mount.
+ * Best effort only as it must go ahead.
+ */
+
+ tsv = malloc(sizeof(struct thread_stdenv_vars));
+ if (!tsv) {
+ error(logopt, "failed alloc tsv storage");
+ return;
+ }
+
+ tsv->uid = uid;
+ tsv->gid = gid;
+
+ /* Try to get passwd info */
+
+ tmplen = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (tmplen < 0) {
+ error(logopt, "failed to get buffer size for getpwuid_r");
+ goto free_tsv;
+ }
+
+ pw_tmp = malloc(tmplen + 1);
+ if (!pw_tmp) {
+ error(logopt, "failed to malloc buffer for getpwuid_r");
+ goto free_tsv;
+ }
+
+ status = getpwuid_r(uid, ppw, pw_tmp, tmplen, pppw);
+ if (status || !ppw) {
+ error(logopt, "failed to get passwd info from getpwuid_r");
+ free(pw_tmp);
+ goto free_tsv;
+ }
+
+ tsv->user = strdup(pw.pw_name);
+ if (!tsv->user) {
+ error(logopt, "failed to malloc buffer for user");
+ free(pw_tmp);
+ goto free_tsv;
+ }
+
+ tsv->home = strdup(pw.pw_dir);
+ if (!tsv->user) {
+ error(logopt, "failed to malloc buffer for home");
+ free(pw_tmp);
+ goto free_tsv_user;
+ }
+
+ free(pw_tmp);
+
+ /* Try to get group info */
+
+ grplen = sysconf(_SC_GETGR_R_SIZE_MAX);
+ if (tmplen < 0) {
+ error(logopt, "failed to get buffer size for getgrgid_r");
+ goto free_tsv_home;
+ }
+
+ gr_tmp = NULL;
+ tmplen = grplen;
+ while (1) {
+ char *tmp = realloc(gr_tmp, tmplen + 1);
+ if (!tmp) {
+ error(logopt, "failed to malloc buffer for getgrgid_r");
+ if (gr_tmp)
+ free(gr_tmp);
+ goto free_tsv_home;
+ }
+ gr_tmp = tmp;
+ pgr = &gr;
+ ppgr = &pgr;
+ status = getgrgid_r(gid, pgr, gr_tmp, tmplen, ppgr);
+ if (status != ERANGE)
+ break;
+ tmplen += grplen;
+ }
+
+ if (status || !pgr) {
+ error(logopt, "failed to get group info from getgrgid_r");
+ free(gr_tmp);
+ goto free_tsv_home;
+ }
+
+ tsv->group = strdup(gr.gr_name);
+ if (!tsv->group) {
+ error(logopt, "failed to malloc buffer for group");
+ free(gr_tmp);
+ goto free_tsv_home;
+ }
+
+ free(gr_tmp);
+
+ status = pthread_setspecific(key_thread_stdenv_vars, tsv);
+ if (status) {
+ error(logopt, "failed to set stdenv thread var");
+ goto free_tsv_group;
+ }
+
+ return;
+
+free_tsv_group:
+ free(tsv->group);
+free_tsv_home:
+ free(tsv->home);
+free_tsv_user:
+ free(tsv->user);
+free_tsv:
+ free(tsv);
+ return;
+}
+
+const char *mount_type_str(const unsigned int type)
+{
+ static const char *str_type[] = {
+ "direct",
+ "indirect",
+ "offset"
+ };
+ unsigned int pos, i;
+
+ for (pos = 0, i = type; pos < type_count; i >>= 1, pos++)
+ if (i & 0x1)
+ break;
+
+ return (pos == type_count ? NULL : str_type[pos]);
+}
+
+void notify_mount_result(struct autofs_point *ap,
+ const char *path, const char *type)
+{
+ if (ap->exp_timeout)
+ info(ap->logopt,
+ "mounted %s on %s with timeout %u, freq %u seconds",
+ type, path,
+ (unsigned int) ap->exp_timeout,
+ (unsigned int) ap->exp_runfreq);
+ else
+ info(ap->logopt,
+ "mounted %s on %s with timeouts disabled",
+ type, path);
+
+ return;
+}
+
+static int do_remount_direct(struct autofs_point *ap, int fd, const char *path)
+{
+ struct ioctl_ops *ops = get_ioctl_ops();
+ uid_t uid;
+ gid_t gid;
+ int ret;
+
+ ops->requestor(ap->logopt, fd, path, &uid, &gid);
+ if (uid != -1 && gid != -1)
+ set_tsd_user_vars(ap->logopt, uid, gid);
+
+ ret = lookup_nss_mount(ap, NULL, path, strlen(path));
+ if (ret)
+ info(ap->logopt, "re-mounted %s", path);
+ else
+ info(ap->logopt, "failed to re-mount %s", path);
+
+ return ret;
+}
+
+static int do_remount_indirect(struct autofs_point *ap, int fd, const char *path)
+{
+ struct ioctl_ops *ops = get_ioctl_ops();
+ struct dirent **de;
+ char buf[PATH_MAX + 1];
+ uid_t uid;
+ gid_t gid;
+ unsigned int mounted;
+ int n, size;
+
+ n = scandir(path, &de, 0, alphasort);
+ if (n < 0)
+ return -1;
+
+ size = sizeof(buf);
+
+ while (n--) {
+ int ret, len;
+
+ if (strcmp(de[n]->d_name, ".") == 0 ||
+ strcmp(de[n]->d_name, "..") == 0) {
+ free(de[n]);
+ continue;
+ }
+
+ ret = cat_path(buf, size, path, de[n]->d_name);
+ if (!ret) {
+ do {
+ free(de[n]);
+ } while (n--);
+ free(de);
+ return -1;
+ }
+
+ ops->ismountpoint(ap->logopt, fd, buf, &mounted);
+ if (!mounted) {
+ free(de[n]);
+ continue;
+ }
+
+ ops->requestor(ap->logopt, fd, buf, &uid, &gid);
+ if (uid != -1 && gid != -1)
+ set_tsd_user_vars(ap->logopt, uid, gid);
+
+ len = strlen(de[n]->d_name);
+
+ ret = lookup_nss_mount(ap, NULL, de[n]->d_name, len);
+ if (ret)
+ info(ap->logopt, "re-mounted %s", buf);
+ else
+ info(ap->logopt, "failed to re-mount %s", buf);
+
+ free(de[n]);
+ }
+ free(de);
+
+ return 0;
+}
+
+int remount_active_mount(struct autofs_point *ap, struct mapent_cache *mc,
+ const char *path, dev_t devid, const unsigned int type,
+ int *ioctlfd)
+{
+ struct ioctl_ops *ops = get_ioctl_ops();
+ time_t timeout = ap->exp_timeout;
+ const char *str_type = mount_type_str(type);
+ unsigned int mounted;
+ struct stat st;
+ int fd;
+
+ *ioctlfd = -1;
+
+ /* Open failed, no mount present */
+ ops->open(ap->logopt, &fd, devid, path, type);
+ if (fd == -1)
+ return REMOUNT_OPEN_FAIL;
+
+ /* Re-reading the map, set timeout and return */
+ if (ap->state == ST_READMAP) {
+ ops->timeout(ap->logopt, fd, &timeout);
+ ops->close(ap->logopt, fd);
+ return REMOUNT_READ_MAP;
+ }
+
+ /* Mounted so set pipefd and timeout etc. */
+ ops->catatonic(ap->logopt, fd);
+ ops->setpipefd(ap->logopt, fd, ap->kpipefd);
+ ops->timeout(ap->logopt, fd, &timeout);
+ if (fstat(fd, &st) == -1) {
+ error(ap->logopt,
+ "failed to stat %s mount %s", str_type, path);
+ ops->close(ap->logopt, fd);
+ return REMOUNT_STAT_FAIL;
+ }
+ ap->dev = st.st_dev;
+ if (mc)
+ cache_set_ino_index(mc, path, st.st_dev, st.st_ino);
+ notify_mount_result(ap, path, str_type);
+
+ debug(ap->logopt, "re-connected to mount %s", path);
+
+ *ioctlfd = fd;
+
+ /* Any mounts on or below? */
+ ops->ismountpoint(ap->logopt, fd, path, &mounted);
+ if (!mounted) {
+ /*
+ * If we're an indirect mount we pass back the fd.
+ * But if were a direct or offset mount with no active
+ * mount we don't retain an open file descriptor.
+ */
+ if (type == direct) {
+ ops->close(ap->logopt, fd);
+ *ioctlfd = -1;
+ }
+ } else {
+ /*
+ * What can I do if we can't remount the existing
+ * mount(s) (possibly a partial failure), everything
+ * following will be broken?
+ */
+ if (type == indirect)
+ do_remount_indirect(ap, fd, path);
+ else
+ do_remount_direct(ap, fd, path);
+ }
+
+ return REMOUNT_SUCCESS;
+}
+
+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);
+ }
+
+ /* 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);
+ }
+
+ /*
+ * Verify that we actually unmounted the thing. This is a
+ * belt and suspenders approach to not eating user data.
+ * We have seen cases where umount succeeds, but there is
+ * still a file system mounted on the mount point. How
+ * this happens has not yet been determined, but we want to
+ * make sure to return failure here, if that is the case,
+ * so that we do not try to call rmdir_path on the
+ * directory.
+ */
+ if (!rv && is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) {
+ crit(ap->logopt,
+ "the umount binary reported that %s was "
+ "unmounted, but there is still something "
+ "mounted on this path.", path);
+ rv = -1;
+ }
+ }
+
+ return rv;
+}
+
+int mount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, const char *base)
+{
+ char path[PATH_MAX + 1];
+ char *offset = path;
+ struct mapent *oe;
+ struct list_head *pos = NULL;
+ unsigned int fs_path_len;
+ unsigned int mounted;
+ int start;
+
+ fs_path_len = strlen(root) + strlen(base);
+ if (fs_path_len > PATH_MAX)
+ return -1;
+
+ strcpy(path, root);
+ strcat(path, base);
+
+ mounted = 0;
+ start = strlen(root);
+ offset = cache_get_offset(base, offset, start, &me->multi_list, &pos);
+ while (offset) {
+ int plen = fs_path_len + strlen(offset);
+
+ if (plen > PATH_MAX) {
+ warn(ap->logopt, "path loo long");
+ goto cont;
+ }
+
+ oe = cache_lookup_offset(base, offset, start, &me->multi_list);
+ if (!oe)
+ goto cont;
+
+ debug(ap->logopt, "mount offset %s", oe->key);
+
+ if (mount_autofs_offset(ap, oe) < 0)
+ warn(ap->logopt, "failed to mount offset");
+ else
+ mounted++;
+cont:
+ offset = cache_get_offset(base,
+ offset, start, &me->multi_list, &pos);
+ }
+
+ return mounted;
+}
+
+int umount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, const char *base)
+{
+ char path[PATH_MAX + 1];
+ char *offset;
+ struct mapent *oe;
+ struct list_head *mm_root, *pos;
+ const char o_root[] = "/";
+ const char *mm_base;
+ int left, start;
+
+ left = 0;
+ start = strlen(root);
+
+ mm_root = &me->multi->multi_list;
+
+ if (!base)
+ mm_base = o_root;
+ else
+ mm_base = base;
+
+ pos = NULL;
+ offset = path;
+
+ /* Make sure "none" of the offsets have an active mount. */
+ while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
+ char *oe_base;
+
+ oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
+ /* root offset is a special case */
+ if (!oe || (strlen(oe->key) - start) == 1)
+ continue;
+
+ /*
+ * Check for and umount subtree offsets resulting from
+ * nonstrict mount fail.
+ */
+ oe_base = oe->key + strlen(root);
+ left += umount_multi_triggers(ap, root, oe, oe_base);
+
+ if (oe->ioctlfd != -1)
+ left++;
+ }
+
+ if (left)
+ return left;
+
+ pos = NULL;
+ offset = path;
+
+ /* Make sure "none" of the offsets have an active mount. */
+ while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
+ oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
+ /* root offset is a special case */
+ if (!oe || (strlen(oe->key) - start) == 1)
+ continue;
+
+ debug(ap->logopt, "umount offset %s", oe->key);
+
+ if (umount_autofs_offset(ap, oe)) {
+ warn(ap->logopt, "failed to umount offset");
+ left++;
+ }
+ }
+
+ if (!left && me->multi == me) {
+ struct mapent_cache *mc = me->mc;
+ int status;
+
+ /*
+ * Special case.
+ * If we can't umount the root container then we can't
+ * delete the offsets from the cache and we need to put
+ * the offset triggers back.
+ */
+ if (is_mounted(_PATH_MOUNTED, root, MNTS_REAL)) {
+ info(ap->logopt, "unmounting dir = %s", root);
+ if (umount_ent(ap, root)) {
+ if (!mount_multi_triggers(ap, root, me, "/"))
+ warn(ap->logopt,
+ "failed to remount offset triggers");
+ return left++;
+ }
+ }
+
+ /* We're done - clean out the offsets */
+ status = cache_delete_offset_list(mc, me->key);
+ if (status != CHE_OK)
+ warn(ap->logopt, "couldn't delete offset list");
+ }
+
+ return left;
+}
+
diff -up autofs-5.0.3/lib/cache.c.active-restart autofs-5.0.3/lib/cache.c
--- autofs-5.0.3/lib/cache.c.active-restart 2008-01-14 13:39:16.000000000 +0900
+++ autofs-5.0.3/lib/cache.c 2008-02-25 09:16:46.000000000 +0900
@@ -111,14 +111,29 @@ void cache_lock_cleanup(void *arg)
return;
}
-void cache_multi_lock(struct mapent *me)
+void cache_multi_readlock(struct mapent *me)
{
int status;
if (!me)
return;
- status = pthread_mutex_lock(&me->multi_mutex);
+ status = pthread_rwlock_rdlock(&me->multi_rwlock);
+ if (status) {
+ logmsg("mapent cache multi mutex lock failed");
+ fatal(status);
+ }
+ return;
+}
+
+void cache_multi_writelock(struct mapent *me)
+{
+ int status;
+
+ if (!me)
+ return;
+
+ status = pthread_rwlock_wrlock(&me->multi_rwlock);
if (status) {
logmsg("mapent cache multi mutex lock failed");
fatal(status);
@@ -133,7 +148,7 @@ void cache_multi_unlock(struct mapent *m
if (!me)
return;
- status = pthread_mutex_unlock(&me->multi_mutex);
+ status = pthread_rwlock_unlock(&me->multi_rwlock);
if (status) {
logmsg("mapent cache multi mutex unlock failed");
fatal(status);
@@ -553,8 +568,9 @@ int cache_add(struct mapent_cache *mc, s
me->ioctlfd = -1;
me->dev = (dev_t) -1;
me->ino = (ino_t) -1;
+ me->dir_created = 0;
- status = pthread_mutex_init(&me->multi_mutex, NULL);
+ status = pthread_rwlock_init(&me->multi_rwlock, NULL);
if (status)
fatal(status);
@@ -760,7 +776,7 @@ int cache_delete(struct mapent_cache *mc
goto done;
}
pred->next = me->next;
- status = pthread_mutex_destroy(&me->multi_mutex);
+ status = pthread_rwlock_destroy(&me->multi_rwlock);
if (status)
fatal(status);
ino_index_lock(mc);
@@ -784,7 +800,7 @@ int cache_delete(struct mapent_cache *mc
goto done;
}
mc->hash[hashval] = me->next;
- status = pthread_mutex_destroy(&me->multi_mutex);
+ status = pthread_rwlock_destroy(&me->multi_rwlock);
if (status)
fatal(status);
ino_index_lock(mc);
diff -up autofs-5.0.3/lib/master.c.active-restart autofs-5.0.3/lib/master.c
--- autofs-5.0.3/lib/master.c.active-restart 2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/lib/master.c 2008-02-25 09:16:46.000000000 +0900
@@ -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
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 -up autofs-5.0.3/CHANGELOG.active-restart autofs-5.0.3/CHANGELOG
--- autofs-5.0.3/CHANGELOG.active-restart 2008-02-25 09:16:05.000000000 +0900
+++ autofs-5.0.3/CHANGELOG 2008-02-25 09:16:46.000000000 +0900
@@ -9,6 +9,7 @@
- fix expire working harder than needed.
- fix unlink of mount tree incorrectly causing autofs mount fail.
- add miscellaneous device node interface library.
+- use miscellaneous device node, if available, for active restart.
14/01/2008 autofs-5.0.3
-----------------------