Author: trasz
Date: Wed Oct 15 09:28:45 2014
New Revision: 273127
URL: https://svnweb.freebsd.org/changeset/base/273127

Log:
  Make automountd(8) inform autofs(4) whether directory being handled can
  have wildcards.  This makes it possible for autofs(4) to avoid requesting
  automountd(8) action on access to nonexistent nodes - unless wildcards
  are actually used.
  
  Note that this change breaks ABI for automountd(8).
  
  Tested by:    dhw@
  MFC after:    1 month
  Sponsored by: The FreeBSD Foundation

Modified:
  head/sys/fs/autofs/autofs.c
  head/sys/fs/autofs/autofs.h
  head/sys/fs/autofs/autofs_ioctl.h
  head/usr.sbin/autofs/automountd.c
  head/usr.sbin/autofs/common.c
  head/usr.sbin/autofs/common.h

Modified: head/sys/fs/autofs/autofs.c
==============================================================================
--- head/sys/fs/autofs/autofs.c Wed Oct 15 08:04:43 2014        (r273126)
+++ head/sys/fs/autofs/autofs.c Wed Oct 15 09:28:45 2014        (r273127)
@@ -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, c
        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 *a
        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 *a
                    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 *a
         */
        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_d
        }
 
        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);

Modified: head/sys/fs/autofs/autofs.h
==============================================================================
--- head/sys/fs/autofs/autofs.h Wed Oct 15 08:04:43 2014        (r273126)
+++ head/sys/fs/autofs/autofs.h Wed Oct 15 09:28:45 2014        (r273127)
@@ -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];

Modified: head/sys/fs/autofs/autofs_ioctl.h
==============================================================================
--- head/sys/fs/autofs/autofs_ioctl.h   Wed Oct 15 08:04:43 2014        
(r273126)
+++ head/sys/fs/autofs/autofs_ioctl.h   Wed Oct 15 09:28:45 2014        
(r273127)
@@ -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;

Modified: head/usr.sbin/autofs/automountd.c
==============================================================================
--- head/usr.sbin/autofs/automountd.c   Wed Oct 15 08:04:43 2014        
(r273126)
+++ head/usr.sbin/autofs/automountd.c   Wed Oct 15 09:28:45 2014        
(r273127)
@@ -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_daemo
        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_daemo
                    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_daemo
                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_daemo
                }
 
                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_daemo
                log_errx(1, "mount failed");
 
        log_debugx("mount done; exiting");
-       done(0);
+       done(0, wildcards);
 
        /*
         * Exit without calling exit_callback().

Modified: head/usr.sbin/autofs/common.c
==============================================================================
--- head/usr.sbin/autofs/common.c       Wed Oct 15 08:04:43 2014        
(r273126)
+++ head/usr.sbin/autofs/common.c       Wed Oct 15 09:28:45 2014        
(r273127)
@@ -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 in
                        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, 
 }
 
 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 cha
 
        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 cha
        if (executable) {
                log_debugx("map \"%s\" is executable", map);
 
+               if (wildcards != NULL)
+                       *wildcards = true;
+
                if (key != NULL) {
                        yyin = auto_popen(path, key, NULL);
                } else {

Modified: head/usr.sbin/autofs/common.h
==============================================================================
--- head/usr.sbin/autofs/common.h       Wed Oct 15 08:04:43 2014        
(r273126)
+++ head/usr.sbin/autofs/common.h       Wed Oct 15 09:28:45 2014        
(r273127)
@@ -80,6 +80,7 @@ struct node   *node_new_map(struct node *p
                    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 *roo
 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);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to