summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/fs/autofs/autofs.c12
-rw-r--r--sys/fs/autofs/autofs.h1
-rw-r--r--sys/fs/autofs/autofs_vfsops.c4
-rw-r--r--usr.sbin/autofs/automount.86
-rw-r--r--usr.sbin/autofs/automount.c65
5 files changed, 83 insertions, 5 deletions
diff --git a/sys/fs/autofs/autofs.c b/sys/fs/autofs/autofs.c
index 0393d13..235d09d 100644
--- a/sys/fs/autofs/autofs.c
+++ b/sys/fs/autofs/autofs.c
@@ -318,6 +318,18 @@ autofs_cache_callout(void *context)
anp->an_cached = false;
}
+void
+autofs_flush(struct autofs_mount *amp)
+{
+
+ /*
+ * XXX: This will do for now, but ideally we should iterate
+ * over all the nodes.
+ */
+ amp->am_root->an_cached = false;
+ AUTOFS_DEBUG("%s flushed", amp->am_mountpoint);
+}
+
/*
* The set/restore sigmask functions are used to (temporarily) overwrite
* the thread td_sigmask during triggering.
diff --git a/sys/fs/autofs/autofs.h b/sys/fs/autofs/autofs.h
index 6ea198c..4d16509 100644
--- a/sys/fs/autofs/autofs.h
+++ b/sys/fs/autofs/autofs.h
@@ -133,6 +133,7 @@ int autofs_trigger(struct autofs_node *anp, const char *component,
int componentlen);
bool autofs_cached(struct autofs_node *anp, const char *component,
int componentlen);
+void autofs_flush(struct autofs_mount *amp);
bool autofs_ignore_thread(const struct thread *td);
int autofs_node_new(struct autofs_node *parent, struct autofs_mount *amp,
const char *name, int namelen, struct autofs_node **anpp);
diff --git a/sys/fs/autofs/autofs_vfsops.c b/sys/fs/autofs/autofs_vfsops.c
index 13a5a89..e84f6b8 100644
--- a/sys/fs/autofs/autofs_vfsops.c
+++ b/sys/fs/autofs/autofs_vfsops.c
@@ -61,8 +61,10 @@ autofs_mount(struct mount *mp)
if (vfs_filteropt(mp->mnt_optnew, autofs_opts))
return (EINVAL);
- if (mp->mnt_flag & MNT_UPDATE)
+ if (mp->mnt_flag & MNT_UPDATE) {
+ autofs_flush(VFSTOAUTOFS(mp));
return (0);
+ }
if (vfs_getopt(mp->mnt_optnew, "from", (void **)&from, NULL))
return (EINVAL);
diff --git a/usr.sbin/autofs/automount.8 b/usr.sbin/autofs/automount.8
index 2988c68..c111a99 100644
--- a/usr.sbin/autofs/automount.8
+++ b/usr.sbin/autofs/automount.8
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 20, 2014
+.Dd November 22, 2014
.Dt AUTOMOUNT 8
.Os
.Sh NAME
@@ -37,6 +37,7 @@
.Nm
.Op Fl D Ar name=value
.Op Fl L
+.Op Fl c
.Op Fl f
.Op Fl o Ar options
.Op Fl v
@@ -64,6 +65,9 @@ and any direct maps, then print them to standard output.
When specified more than once, all the maps, including indirect ones,
will be parsed and shown.
This is useful when debugging configuration problems.
+.It Fl c
+Flush caches, discarding possibly stale information obtained from maps
+and directory services.
.It Fl f
Force unmount, to be used with
.Fl u .
diff --git a/usr.sbin/autofs/automount.c b/usr.sbin/autofs/automount.c
index a956b08..3c59704 100644
--- a/usr.sbin/autofs/automount.c
+++ b/usr.sbin/autofs/automount.c
@@ -230,6 +230,57 @@ mount_unmount(struct node *root)
}
static void
+flush_autofs(const char *fspath)
+{
+ struct iovec *iov = NULL;
+ char errmsg[255];
+ int error, iovlen = 0;
+
+ log_debugx("flushing %s", fspath);
+ memset(errmsg, 0, sizeof(errmsg));
+
+ build_iovec(&iov, &iovlen, "fstype",
+ __DECONST(void *, "autofs"), (size_t)-1);
+ build_iovec(&iov, &iovlen, "fspath",
+ __DECONST(void *, fspath), (size_t)-1);
+ build_iovec(&iov, &iovlen, "errmsg",
+ errmsg, sizeof(errmsg));
+
+ error = nmount(iov, iovlen, MNT_UPDATE);
+ if (error != 0) {
+ if (*errmsg != '\0') {
+ log_err(1, "cannot flush %s: %s",
+ fspath, errmsg);
+ } else {
+ log_err(1, "cannot flush %s", fspath);
+ }
+ }
+}
+
+static void
+flush_caches(void)
+{
+ struct statfs *mntbuf;
+ int i, nitems;
+
+ nitems = getmntinfo(&mntbuf, MNT_WAIT);
+ if (nitems <= 0)
+ log_err(1, "getmntinfo");
+
+ log_debugx("flushing autofs caches");
+
+ for (i = 0; i < nitems; i++) {
+ if (strcmp(mntbuf[i].f_fstypename, "autofs") != 0) {
+ log_debugx("skipping %s, filesystem type is not autofs",
+ mntbuf[i].f_mntonname);
+ continue;
+ }
+
+ flush_autofs(mntbuf[i].f_mntonname);
+ }
+}
+
+static void
unmount_automounted(bool force)
{
struct statfs *mntbuf;
@@ -262,7 +313,7 @@ static void
usage_automount(void)
{
- fprintf(stderr, "usage: automount [-D name=value][-o opts][-Lfuv]\n");
+ fprintf(stderr, "usage: automount [-D name=value][-o opts][-Lcfuv]\n");
exit(1);
}
@@ -272,7 +323,7 @@ main_automount(int argc, char **argv)
struct node *root;
int ch, debug = 0, show_maps = 0;
char *options = NULL;
- bool do_unmount = false, force_unmount = false;
+ bool do_unmount = false, force_unmount = false, flush = false;
/*
* Note that in automount(8), the only purpose of variable
@@ -280,7 +331,7 @@ main_automount(int argc, char **argv)
*/
defined_init();
- while ((ch = getopt(argc, argv, "D:Lfo:uv")) != -1) {
+ while ((ch = getopt(argc, argv, "D:Lfco:uv")) != -1) {
switch (ch) {
case 'D':
defined_parse_and_add(optarg);
@@ -288,6 +339,9 @@ main_automount(int argc, char **argv)
case 'L':
show_maps++;
break;
+ case 'c':
+ flush = true;
+ break;
case 'f':
force_unmount = true;
break;
@@ -319,6 +373,11 @@ main_automount(int argc, char **argv)
log_init(debug);
+ if (flush) {
+ flush_caches();
+ return (0);
+ }
+
if (do_unmount) {
unmount_automounted(force_unmount);
return (0);
OpenPOWER on IntegriCloud