- 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. - device node and active restart fixes. - update is_mounted to use device node ioctl, if available.
2255 lines
60 KiB
Diff
2255 lines
60 KiB
Diff
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
|
|
-----------------------
|