Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 130701790bf2d95e902edf16031ff596 > files > 38

autofs-5.0.1-0.rc2.164.el5_8.src.rpm

autofs-5.0.1 - don't hold lock for simple mounts

From: Ian Kent <raven@themaw.net>

A map entry that depends on another map entry in the "same" map cannot
be allowed in all cases. In particular, multi-mount entries must not
change during mount operations so the internal map entry cache must
remain locked during the mount. This is because, during the mount, we
must consult the map and possibly update the internal cache entry to
ensure we are using the most up to date mount information.

This isn't the case for non multi-mount map entries but autofs didn't
allow for this, which is the issue this patch addresses.
---

 modules/parse_sun.c |   41 +++++++++++++++++------------------------
 1 file changed, 17 insertions(+), 24 deletions(-)


--- autofs-5.0.1.orig/modules/parse_sun.c
+++ autofs-5.0.1/modules/parse_sun.c
@@ -1145,19 +1145,6 @@ static int mount_subtree(struct autofs_p
 
 	rv = 0;
 
-	if (!me || !me->multi) {
-		int loclen = strlen(loc);
-		int namelen = strlen(name);
-		const char *root = ap->path;
-
-		if (!strcmp(ap->path, "/-"))
-			root = name;
-
-		rv = sun_mount(ap, root, name, namelen, loc, loclen, options, ctxt);
-
-		goto done;
-	}
-
 	mm = me->multi;
 	mm_key = mm->key;
 	move = MOUNT_MOVE_NONE;
@@ -1303,7 +1290,6 @@ static int mount_subtree(struct autofs_p
 	if (rv > 0)
 		return rv;
 
-done:
 	/*
 	 * Convert fail on nonstrict, non-empty multi-mount
 	 * to success
@@ -1632,17 +1618,25 @@ int parse_mount(struct autofs_point *ap,
 		 * it's already been parsed (above) and any option string
 		 * has already been stripped so just use the remainder.
 		 */
+		cache_readlock(mc);
 		if (*name == '/' &&
 		   (me = cache_lookup_distinct(mc, name)) && me->multi) {
 			loc = strdup(p);
 			if (!loc) {
 				free(options);
+				cache_unlock(mc);
 				warn(ap->logopt, MODPREFIX "out of memory");
 				return 1;
 			}
-			loclen = strlen(p);
-			goto mount_it;
+			cache_multi_writelock(me);
+			rv = mount_subtree(ap, me, name, loc, options, ctxt);
+			cache_multi_unlock(me);
+			cache_unlock(mc);
+			free(loc);
+			free(options);
+			return rv;
 		}
+		cache_unlock(mc);
 
 		l = chunklen(p, check_colon(p));
 		loc = dequote(p, l, ap->logopt);
@@ -1725,21 +1719,20 @@ int parse_mount(struct autofs_point *ap,
 			      MODPREFIX "entry %s is empty!", name);
 			return 1;
 		}
-mount_it:
+
 		debug(ap->logopt,
 		      MODPREFIX "core of entry: options=%s, loc=%.*s",
 		      options, loclen, loc);
 
-		cache_readlock(mc);
-		cache_multi_writelock(me);
-
-		rv = mount_subtree(ap, me, name, loc, options, ctxt);
+		if (!strcmp(ap->path, "/-"))
+			rv = sun_mount(ap, name, name, name_len,
+				       loc, loclen, options, ctxt);
+		else
+			rv = sun_mount(ap, ap->path, name, name_len,
+				       loc, loclen, options, ctxt);
 
 		free(loc);
 		free(options);
-
-		cache_multi_unlock(me);
-		cache_unlock(mc);
 		pthread_setcancelstate(cur_state, NULL);
 	}
 	return rv;