aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/fs/autofs/autofs.c17
-rw-r--r--sys/fs/autofs/autofs.h2
-rw-r--r--sys/fs/autofs/autofs_ioctl.h6
-rw-r--r--usr.sbin/autofs/automountd.c31
-rw-r--r--usr.sbin/autofs/common.c29
-rw-r--r--usr.sbin/autofs/common.h4
6 files changed, 74 insertions, 15 deletions
diff --git a/sys/fs/autofs/autofs.c b/sys/fs/autofs/autofs.c
index a2aa6c19ba23..029d2548f519 100644
--- a/sys/fs/autofs/autofs.c
+++ b/sys/fs/autofs/autofs.c
@@ -274,6 +274,7 @@ autofs_task(void *context, int pending)
* XXX: EIO perhaps?
*/
ar->ar_error = ETIMEDOUT;
+ ar->ar_wildcards = true;
ar->ar_done = true;
ar->ar_in_progress = false;
cv_broadcast(&autofs_softc->sc_cv);
@@ -291,12 +292,13 @@ autofs_cached(struct autofs_node *anp, const char *component, int componentlen)
AUTOFS_ASSERT_UNLOCKED(amp);
/*
- * For top-level nodes we need to request automountd(8)
- * assistance even if the node is marked as cached,
- * but the requested subdirectory does not exist. This
- * is necessary for wildcard indirect map keys to work.
+ * For root node we need to request automountd(8) assistance even
+ * if the node is marked as cached, but the requested top-level
+ * directory does not exist. This is necessary for wildcard indirect
+ * map keys to work. We don't do this if we know that there are
+ * no wildcards.
*/
- if (anp->an_parent == NULL && componentlen != 0) {
+ if (anp->an_parent == NULL && componentlen != 0 && anp->an_wildcards) {
AUTOFS_SLOCK(amp);
error = autofs_node_find(anp, component, componentlen, NULL);
AUTOFS_SUNLOCK(amp);
@@ -366,6 +368,7 @@ autofs_trigger_one(struct autofs_node *anp,
struct autofs_request *ar;
char *key, *path;
int error = 0, request_error, last;
+ bool wildcards;
amp = anp->an_mount;
@@ -450,6 +453,8 @@ autofs_trigger_one(struct autofs_node *anp,
ar->ar_path, request_error);
}
+ wildcards = ar->ar_wildcards;
+
last = refcount_release(&ar->ar_refcount);
if (last) {
TAILQ_REMOVE(&autofs_softc->sc_requests, ar, ar_next);
@@ -470,6 +475,7 @@ autofs_trigger_one(struct autofs_node *anp,
*/
if (error == 0 && request_error == 0 && autofs_cache > 0) {
anp->an_cached = true;
+ anp->an_wildcards = wildcards;
callout_reset(&anp->an_callout, autofs_cache * hz,
autofs_cache_callout, anp);
}
@@ -584,6 +590,7 @@ autofs_ioctl_done(struct autofs_daemon_done *add)
}
ar->ar_error = add->add_error;
+ ar->ar_wildcards = add->add_wildcards;
ar->ar_done = true;
ar->ar_in_progress = false;
cv_broadcast(&autofs_softc->sc_cv);
diff --git a/sys/fs/autofs/autofs.h b/sys/fs/autofs/autofs.h
index dc33eeff54e6..6ea198c6c743 100644
--- a/sys/fs/autofs/autofs.h
+++ b/sys/fs/autofs/autofs.h
@@ -74,6 +74,7 @@ struct autofs_node {
struct vnode *an_vnode;
struct sx an_vnode_lock;
bool an_cached;
+ bool an_wildcards;
struct callout an_callout;
int an_retries;
struct timespec an_ctime;
@@ -97,6 +98,7 @@ struct autofs_request {
int ar_id;
bool ar_done;
int ar_error;
+ bool ar_wildcards;
bool ar_in_progress;
char ar_from[MAXPATHLEN];
char ar_path[MAXPATHLEN];
diff --git a/sys/fs/autofs/autofs_ioctl.h b/sys/fs/autofs/autofs_ioctl.h
index 8d03ef7480a2..328dd9ccd0cc 100644
--- a/sys/fs/autofs/autofs_ioctl.h
+++ b/sys/fs/autofs/autofs_ioctl.h
@@ -78,6 +78,12 @@ struct autofs_daemon_done {
int add_id;
/*
+ * Set to 1 if the map may contain wildcard entries;
+ * otherwise autofs will do negative caching.
+ */
+ int add_wildcards;
+
+ /*
* Error number, possibly returned to userland.
*/
int add_error;
diff --git a/usr.sbin/autofs/automountd.c b/usr.sbin/autofs/automountd.c
index 7c40b6bf80ac..0a648c5b37d5 100644
--- a/usr.sbin/autofs/automountd.c
+++ b/usr.sbin/autofs/automountd.c
@@ -68,13 +68,14 @@ static int autofs_fd;
static int request_id;
static void
-done(int request_error)
+done(int request_error, bool wildcards)
{
struct autofs_daemon_done add;
int error;
memset(&add, 0, sizeof(add));
add.add_id = request_id;
+ add.add_wildcards = wildcards;
add.add_error = request_error;
log_debugx("completing request %d with error %d",
@@ -172,7 +173,7 @@ static void
exit_callback(void)
{
- done(EIO);
+ done(EIO, true);
}
static void
@@ -184,6 +185,7 @@ handle_request(const struct autofs_daemon_request *adr, char *cmdline_options,
FILE *f;
char *options, *fstype, *nobrowse, *retrycnt, *tmp;
int error;
+ bool wildcards;
log_debugx("got request %d: from %s, path %s, prefix \"%s\", "
"key \"%s\", options \"%s\"", adr->adr_id, adr->adr_from,
@@ -209,9 +211,26 @@ handle_request(const struct autofs_daemon_request *adr, char *cmdline_options,
checked_strdup(adr->adr_options), checked_strdup(map),
checked_strdup("[kernel request]"), lineno);
}
- parse_map(parent, map, adr->adr_key[0] != '\0' ? adr->adr_key : NULL);
+
+ /*
+ * "Wildcards" here actually means "make autofs(4) request
+ * automountd(8) action if the node being looked up does not
+ * exist, even though the parent is marked as cached". This
+ * needs to be done for maps with wildcard entries, but also
+ * for special and executable maps.
+ */
+ parse_map(parent, map, adr->adr_key[0] != '\0' ? adr->adr_key : NULL,
+ &wildcards);
+ if (!wildcards)
+ wildcards = node_has_wildcards(parent);
+ if (wildcards)
+ log_debugx("map may contain wildcard entries");
+ else
+ log_debugx("map does not contain wildcard entries");
+
if (adr->adr_key[0] != '\0')
node_expand_wildcard(root, adr->adr_key);
+
node = node_find(root, adr->adr_path);
if (node == NULL) {
log_errx(1, "map %s does not contain key for \"%s\"; "
@@ -236,7 +255,7 @@ handle_request(const struct autofs_daemon_request *adr, char *cmdline_options,
if (nobrowse != NULL && adr->adr_key[0] == '\0') {
log_debugx("skipping map %s due to \"nobrowse\" "
"option; exiting", map);
- done(0);
+ done(0, true);
/*
* Exit without calling exit_callback().
@@ -263,7 +282,7 @@ handle_request(const struct autofs_daemon_request *adr, char *cmdline_options,
}
log_debugx("nothing to mount; exiting");
- done(0);
+ done(0, wildcards);
/*
* Exit without calling exit_callback().
@@ -337,7 +356,7 @@ handle_request(const struct autofs_daemon_request *adr, char *cmdline_options,
log_errx(1, "mount failed");
log_debugx("mount done; exiting");
- done(0);
+ done(0, wildcards);
/*
* Exit without calling exit_callback().
diff --git a/usr.sbin/autofs/common.c b/usr.sbin/autofs/common.c
index e6db682e5222..6fd8a05cf411 100644
--- a/usr.sbin/autofs/common.c
+++ b/usr.sbin/autofs/common.c
@@ -498,6 +498,19 @@ node_is_direct_map(const struct node *n)
return (true);
}
+bool
+node_has_wildcards(const struct node *n)
+{
+ const struct node *child;
+
+ TAILQ_FOREACH(child, &n->n_children, n_next) {
+ if (strcmp(child->n_key, "*") == 0)
+ return (true);
+ }
+
+ return (false);
+}
+
static void
node_expand_maps(struct node *n, bool indirect)
{
@@ -526,7 +539,7 @@ node_expand_maps(struct node *n, bool indirect)
log_debugx("map \"%s\" is a direct map, parsing",
child->n_map);
}
- parse_map(child, child->n_map, NULL);
+ parse_map(child, child->n_map, NULL, NULL);
}
}
@@ -996,7 +1009,8 @@ parse_included_map(struct node *parent, const char *map)
}
void
-parse_map(struct node *parent, const char *map, const char *key)
+parse_map(struct node *parent, const char *map, const char *key,
+ bool *wildcards)
{
char *path = NULL;
int error, ret;
@@ -1007,8 +1021,14 @@ parse_map(struct node *parent, const char *map, const char *key)
log_debugx("parsing map \"%s\"", map);
- if (map[0] == '-')
+ if (wildcards != NULL)
+ *wildcards = false;
+
+ if (map[0] == '-') {
+ if (wildcards != NULL)
+ *wildcards = true;
return (parse_special_map(parent, map, key));
+ }
if (map[0] == '/') {
path = checked_strdup(map);
@@ -1035,6 +1055,9 @@ parse_map(struct node *parent, const char *map, const char *key)
if (executable) {
log_debugx("map \"%s\" is executable", map);
+ if (wildcards != NULL)
+ *wildcards = true;
+
if (key != NULL) {
yyin = auto_popen(path, key, NULL);
} else {
diff --git a/usr.sbin/autofs/common.h b/usr.sbin/autofs/common.h
index bc0b6f6c6116..16a8d7395ae9 100644
--- a/usr.sbin/autofs/common.h
+++ b/usr.sbin/autofs/common.h
@@ -80,6 +80,7 @@ struct node *node_new_map(struct node *parent, char *key, char *options,
char *map, const char *config_file, int config_line);
struct node *node_find(struct node *root, const char *mountpoint);
bool node_is_direct_map(const struct node *n);
+bool node_has_wildcards(const struct node *n);
char *node_path(const struct node *n);
char *node_options(const struct node *n);
void node_expand_ampersand(struct node *root, const char *key);
@@ -88,7 +89,8 @@ int node_expand_defined(struct node *root);
void node_expand_indirect_maps(struct node *n);
void node_print(const struct node *n);
void parse_master(struct node *root, const char *path);
-void parse_map(struct node *parent, const char *map, const char *args);
+void parse_map(struct node *parent, const char *map, const char *args,
+ bool *wildcards);
char *defined_expand(const char *string);
void defined_init(void);
void defined_parse_and_add(char *def);