Blame SOURCES/autofs-5.1.6-use-mnt_list-for-submounts.patch

49b67f
autofs-5.1.6 - use mnt_list for submounts
49b67f
49b67f
From: Ian Kent <raven@themaw.net>
49b67f
49b67f
Use struct mnt_list objects for submount list entries instead of
49b67f
struct autofs_point itself.
49b67f
49b67f
Signed-off-by: Ian Kent <raven@themaw.net>
49b67f
---
49b67f
 CHANGELOG              |    1 
49b67f
 daemon/automount.c     |   11 ++++-
49b67f
 daemon/direct.c        |    7 ++-
49b67f
 daemon/indirect.c      |    5 ++
49b67f
 include/automount.h    |    2 -
49b67f
 include/master.h       |    2 -
49b67f
 include/mounts.h       |   10 +++++
49b67f
 lib/master.c           |   93 +++++++++++++++----------------------------------
49b67f
 lib/mounts.c           |   81 ++++++++++++++++++++++++++++++++++++++++++
49b67f
 modules/mount_autofs.c |   17 ++++++++
49b67f
 10 files changed, 157 insertions(+), 72 deletions(-)
49b67f
49b67f
--- autofs-5.1.4.orig/CHANGELOG
49b67f
+++ autofs-5.1.4/CHANGELOG
49b67f
@@ -122,6 +122,7 @@ xx/xx/2018 autofs-5.1.5
49b67f
 - make external mounts independent of amd_entry.
49b67f
 - make external mounts use simpler hashtable.
49b67f
 - add a hash index to mnt_list.
49b67f
+- use mnt_list for submounts.
49b67f
 
49b67f
 19/12/2017 autofs-5.1.4
49b67f
 - fix spec file url.
49b67f
--- autofs-5.1.4.orig/daemon/automount.c
49b67f
+++ autofs-5.1.4/daemon/automount.c
49b67f
@@ -624,6 +624,7 @@ done:
49b67f
    it also tries to umount path itself */
49b67f
 int umount_multi(struct autofs_point *ap, const char *path, int incl)
49b67f
 {
49b67f
+	struct mnt_list *sbmnt;
49b67f
 	int is_autofs_fs;
49b67f
 	struct stat st;
49b67f
 	int left;
49b67f
@@ -685,8 +686,11 @@ int umount_multi(struct autofs_point *ap
49b67f
 	}
49b67f
 
49b67f
 	is_autofs_fs = 0;
49b67f
-	if (master_find_submount(ap, path))
49b67f
+	sbmnt = mnts_find_submount(path);
49b67f
+	if (sbmnt) {
49b67f
 		is_autofs_fs = 1;
49b67f
+		mnts_put_mount(sbmnt);
49b67f
+	}
49b67f
 
49b67f
 	left = 0;
49b67f
 
49b67f
@@ -1717,9 +1721,12 @@ static void handle_mounts_cleanup(void *
49b67f
 
49b67f
 	if (submount) {
49b67f
 		struct amd_entry *am;
49b67f
+
49b67f
 		/* We are finishing up */
49b67f
 		ap->parent->submnt_count--;
49b67f
-		list_del_init(&ap->mounts);
49b67f
+
49b67f
+		/* Submount at ap->path belongs to parent submount list. */
49b67f
+		mnts_remove_submount(ap->path);
49b67f
 		am = __master_find_amdmount(ap->parent, ap->path);
49b67f
 		if (am) {
49b67f
 			list_del_init(&am->entries);
49b67f
--- autofs-5.1.4.orig/daemon/direct.c
49b67f
+++ autofs-5.1.4/daemon/direct.c
49b67f
@@ -1211,14 +1211,17 @@ static void *do_mount_direct(void *arg)
49b67f
 	 */
49b67f
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
49b67f
 	if (status) {
49b67f
+		struct mnt_list *sbmnt;
49b67f
 		struct mapent *me;
49b67f
 		struct statfs fs;
49b67f
 		unsigned int close_fd = 0;
49b67f
 
49b67f
+		sbmnt = mnts_find_submount(mt.name);
49b67f
 		if (statfs(mt.name, &fs) == -1 ||
49b67f
-		   (fs.f_type == AUTOFS_SUPER_MAGIC &&
49b67f
-		    !master_find_submount(ap, mt.name)))
49b67f
+		   (fs.f_type == AUTOFS_SUPER_MAGIC && !sbmnt))
49b67f
 			close_fd = 1;
49b67f
+		if (sbmnt)
49b67f
+			mnts_put_mount(sbmnt);
49b67f
 		cache_writelock(mt.mc);
49b67f
 		if ((me = cache_lookup_distinct(mt.mc, mt.name))) {
49b67f
 			/*
49b67f
--- autofs-5.1.4.orig/daemon/indirect.c
49b67f
+++ autofs-5.1.4/daemon/indirect.c
49b67f
@@ -401,6 +401,7 @@ void *expire_proc_indirect(void *arg)
49b67f
 			if (next->flags & MNTS_INDIRECT)
49b67f
 				master_notify_submount(ap, next->mp, ap->state);
49b67f
 			else if (next->flags & MNTS_OFFSET) {
49b67f
+				struct mnt_list *sbmnt;
49b67f
 				struct map_source *map;
49b67f
 				struct mapent_cache *mc = NULL;
49b67f
 				struct mapent *me = NULL;
49b67f
@@ -413,7 +414,9 @@ void *expire_proc_indirect(void *arg)
49b67f
 				}
49b67f
 
49b67f
 				/* Don't touch submounts */
49b67f
-				if (master_find_submount(ap, next->mp)) {
49b67f
+				sbmnt = mnts_find_submount(next->mp);
49b67f
+				if (sbmnt) {
49b67f
+					mnts_put_mount(sbmnt);
49b67f
 					pthread_setcancelstate(cur_state, NULL);
49b67f
 					continue;
49b67f
 				}
49b67f
--- autofs-5.1.4.orig/include/automount.h
49b67f
+++ autofs-5.1.4/include/automount.h
49b67f
@@ -570,9 +570,9 @@ struct autofs_point {
49b67f
 	struct list_head mounts;	/* List of autofs mounts at current level */
49b67f
 	struct list_head amdmounts;	/* List of non submount amd mounts */
49b67f
 	unsigned int submount;		/* Is this a submount */
49b67f
-	unsigned int shutdown;		/* Shutdown notification */
49b67f
 	unsigned int submnt_count;	/* Number of submounts */
49b67f
 	struct list_head submounts;	/* List of child submounts */
49b67f
+	unsigned int shutdown;		/* Shutdown notification */
49b67f
 };
49b67f
 
49b67f
 #define UNLINK_AND_CONT		0x01
49b67f
--- autofs-5.1.4.orig/include/master.h
49b67f
+++ autofs-5.1.4/include/master.h
49b67f
@@ -109,8 +109,6 @@ void master_source_current_wait(struct m
49b67f
 void master_source_current_signal(struct master_mapent *);
49b67f
 struct master_mapent *master_find_mapent(struct master *, const char *);
49b67f
 unsigned int master_partial_match_mapent(struct master *, const char *);
49b67f
-struct autofs_point *__master_find_submount(struct autofs_point *, const char *);
49b67f
-struct autofs_point *master_find_submount(struct autofs_point *, const char *);
49b67f
 struct amd_entry *__master_find_amdmount(struct autofs_point *, const char *);
49b67f
 struct amd_entry *master_find_amdmount(struct autofs_point *, const char *);
49b67f
 struct master_mapent *master_new_mapent(struct master *, const char *, time_t);
49b67f
--- autofs-5.1.4.orig/include/mounts.h
49b67f
+++ autofs-5.1.4/include/mounts.h
49b67f
@@ -59,6 +59,11 @@ struct mnt_list {
49b67f
 	struct hlist_node hash;
49b67f
 	unsigned int ref;
49b67f
 
49b67f
+	/* List of sub-mounts of an autofs_point */
49b67f
+	struct autofs_point *ap;
49b67f
+	struct list_head submount;
49b67f
+	struct list_head submount_work;
49b67f
+
49b67f
 	/*
49b67f
 	 * List operations ie. get_mnt_list.
49b67f
 	 */
49b67f
@@ -108,6 +113,11 @@ int ext_mount_remove(const char *);
49b67f
 int ext_mount_inuse(const char *);
49b67f
 struct mnt_list *mnts_lookup_mount(const char *mp);
49b67f
 void mnts_put_mount(struct mnt_list *mnt);
49b67f
+struct mnt_list *mnts_find_submount(const char *path);
49b67f
+struct mnt_list *mnts_add_submount(struct autofs_point *ap);
49b67f
+void mnts_remove_submount(const char *mp);
49b67f
+void mnts_get_submount_list(struct list_head *mnts, struct autofs_point *ap);
49b67f
+void mnts_put_submount_list(struct list_head *mnts);
49b67f
 struct mnt_list *get_mnt_list(const char *path, int include);
49b67f
 int unlink_mount_tree(struct autofs_point *ap, const char *mp);
49b67f
 void free_mnt_list(struct mnt_list *list);
49b67f
--- autofs-5.1.4.orig/lib/master.c
49b67f
+++ autofs-5.1.4/lib/master.c
49b67f
@@ -761,34 +761,6 @@ unsigned int master_partial_match_mapent
49b67f
 	return ret;
49b67f
 }
49b67f
 
49b67f
-struct autofs_point *__master_find_submount(struct autofs_point *ap, const char *path)
49b67f
-{
49b67f
-	struct list_head *head, *p;
49b67f
-
49b67f
-	head = &ap->submounts;
49b67f
-	list_for_each(p, head) {
49b67f
-		struct autofs_point *submount;
49b67f
-
49b67f
-		submount = list_entry(p, struct autofs_point, mounts);
49b67f
-
49b67f
-		if (!strcmp(submount->path, path))
49b67f
-			return submount;
49b67f
-	}
49b67f
-
49b67f
-	return NULL;
49b67f
-}
49b67f
-
49b67f
-struct autofs_point *master_find_submount(struct autofs_point *ap, const char *path)
49b67f
-{
49b67f
-	struct autofs_point *submount;
49b67f
-
49b67f
-	mounts_mutex_lock(ap);
49b67f
-	submount = __master_find_submount(ap, path);
49b67f
-	mounts_mutex_unlock(ap);
49b67f
-
49b67f
-	return submount;
49b67f
-}
49b67f
-
49b67f
 struct amd_entry *__master_find_amdmount(struct autofs_point *ap, const char *path)
49b67f
 {
49b67f
 	struct list_head *head, *p;
49b67f
@@ -1190,85 +1162,80 @@ int master_submount_list_empty(struct au
49b67f
 
49b67f
 int master_notify_submount(struct autofs_point *ap, const char *path, enum states state)
49b67f
 {
49b67f
-	struct list_head *head, *p;
49b67f
-	struct autofs_point *this = NULL;
49b67f
+	struct mnt_list *this, *sbmnt;
49b67f
+	LIST_HEAD(sbmnts);
49b67f
 	int ret = 1;
49b67f
 
49b67f
-	mounts_mutex_lock(ap);
49b67f
-
49b67f
-	head = &ap->submounts;
49b67f
-	p = head->prev;
49b67f
-	while (p != head) {
49b67f
-		this = list_entry(p, struct autofs_point, mounts);
49b67f
-		p = p->prev;
49b67f
+	mnts_get_submount_list(&sbmnts, ap);
49b67f
+	if (list_empty(&sbmnts))
49b67f
+		return 1;
49b67f
+
49b67f
+	list_for_each_entry(this, &sbmnts, submount_work) {
49b67f
+		/* Not a submount */
49b67f
+		if (!(this->flags & MNTS_AUTOFS))
49b67f
+			continue;
49b67f
 
49b67f
 		/* path not the same */
49b67f
-		if (strcmp(this->path, path))
49b67f
+		if (strcmp(this->mp, path))
49b67f
 			continue;
49b67f
 
49b67f
-		if (!master_submount_list_empty(this)) {
49b67f
-			char *this_path = strdup(this->path);
49b67f
-			if (this_path) {
49b67f
-				mounts_mutex_unlock(ap);
49b67f
-				master_notify_submount(this, path, state);
49b67f
-				mounts_mutex_lock(ap);
49b67f
-				if (!__master_find_submount(ap, this_path)) {
49b67f
-					free(this_path);
49b67f
-					continue;
49b67f
-				}
49b67f
-				free(this_path);
49b67f
-			}
49b67f
+		if (!master_submount_list_empty(this->ap)) {
49b67f
+			struct mnt_list *sm;
49b67f
+
49b67f
+			master_notify_submount(this->ap, path, state);
49b67f
+			sm = mnts_find_submount(path);
49b67f
+			if (!sm)
49b67f
+				continue;
49b67f
+			mnts_put_mount(sm);
49b67f
 		}
49b67f
 
49b67f
 		/* Now we have found the submount we want to expire */
49b67f
 
49b67f
 		st_mutex_lock();
49b67f
 
49b67f
-		if (this->state == ST_SHUTDOWN) {
49b67f
+		if (this->ap->state == ST_SHUTDOWN) {
49b67f
 			this = NULL;
49b67f
 			st_mutex_unlock();
49b67f
 			break;
49b67f
 		}
49b67f
 
49b67f
-		this->shutdown = ap->shutdown;
49b67f
+		this->ap->shutdown = ap->shutdown;
49b67f
 
49b67f
-		__st_add_task(this, state);
49b67f
+		__st_add_task(this->ap, state);
49b67f
 
49b67f
 		st_mutex_unlock();
49b67f
-		mounts_mutex_unlock(ap);
49b67f
 
49b67f
-		st_wait_task(this, state, 0);
49b67f
+		st_wait_task(this->ap, state, 0);
49b67f
 
49b67f
 		/*
49b67f
 		 * If our submount gets to state ST_SHUTDOWN, ST_SHUTDOWN_PENDING or
49b67f
 		 * ST_SHUTDOWN_FORCE we need to wait until it goes away or changes
49b67f
 		 * to ST_READY.
49b67f
 		 */
49b67f
-		mounts_mutex_lock(ap);
49b67f
 		st_mutex_lock();
49b67f
-		while ((this = __master_find_submount(ap, path))) {
49b67f
+		while ((sbmnt = mnts_find_submount(path))) {
49b67f
 			struct timespec t = { 0, 300000000 };
49b67f
 			struct timespec r;
49b67f
 
49b67f
-			if (this->state != ST_SHUTDOWN &&
49b67f
-			    this->state != ST_SHUTDOWN_PENDING &&
49b67f
-			    this->state != ST_SHUTDOWN_FORCE) {
49b67f
+			if (sbmnt->ap->state != ST_SHUTDOWN &&
49b67f
+			    sbmnt->ap->state != ST_SHUTDOWN_PENDING &&
49b67f
+			    sbmnt->ap->state != ST_SHUTDOWN_FORCE) {
49b67f
 				ret = 0;
49b67f
+				mnts_put_mount(sbmnt);
49b67f
 				break;
49b67f
 			}
49b67f
+			mnts_put_mount(sbmnt);
49b67f
 
49b67f
 			st_mutex_unlock();
49b67f
-			mounts_mutex_unlock(ap);
49b67f
 			while (nanosleep(&t, &r) == -1 && errno == EINTR)
49b67f
 				memcpy(&t, &r, sizeof(struct timespec));
49b67f
-			mounts_mutex_lock(ap);
49b67f
 			st_mutex_lock();
49b67f
 		}
49b67f
 		st_mutex_unlock();
49b67f
 		break;
49b67f
 	}
49b67f
 
49b67f
-	mounts_mutex_unlock(ap);
49b67f
+	mnts_put_submount_list(&sbmnts);
49b67f
 
49b67f
 	return ret;
49b67f
 }
49b67f
--- autofs-5.1.4.orig/lib/mounts.c
49b67f
+++ autofs-5.1.4/lib/mounts.c
49b67f
@@ -885,6 +885,8 @@ static struct mnt_list *mnts_alloc_mount
49b67f
 
49b67f
 	this->ref = 1;
49b67f
 	INIT_HLIST_NODE(&this->hash);
49b67f
+	INIT_LIST_HEAD(&this->submount);
49b67f
+	INIT_LIST_HEAD(&this->submount_work);
49b67f
 done:
49b67f
 	return this;
49b67f
 }
49b67f
@@ -967,6 +969,85 @@ void mnts_put_mount(struct mnt_list *mnt
49b67f
 	mnts_hash_mutex_unlock();
49b67f
 }
49b67f
 
49b67f
+struct mnt_list *mnts_find_submount(const char *path)
49b67f
+{
49b67f
+	struct mnt_list *mnt;
49b67f
+
49b67f
+	mnt = mnts_lookup_mount(path);
49b67f
+	if (mnt && mnt->flags & MNTS_AUTOFS)
49b67f
+		return mnt;
49b67f
+	mnts_put_mount(mnt);
49b67f
+	return NULL;
49b67f
+}
49b67f
+
49b67f
+struct mnt_list *mnts_add_submount(struct autofs_point *ap)
49b67f
+{
49b67f
+	struct mnt_list *this;
49b67f
+
49b67f
+	mnts_hash_mutex_lock();
49b67f
+	this = mnts_get_mount(ap->path);
49b67f
+	if (this) {
49b67f
+		if (!this->ap)
49b67f
+			this->ap = ap;
49b67f
+		else if (this->ap != ap ||
49b67f
+			 this->ap->parent != ap->parent) {
49b67f
+			__mnts_put_mount(this);
49b67f
+			mnts_hash_mutex_unlock();
49b67f
+			error(ap->logopt,
49b67f
+			      "conflict with submount owner: %s", ap->path);
49b67f
+			goto fail;
49b67f
+		}
49b67f
+		this->flags |= MNTS_AUTOFS;
49b67f
+		if (list_empty(&this->submount))
49b67f
+			list_add_tail(&this->submount, &ap->parent->submounts);
49b67f
+	}
49b67f
+	mnts_hash_mutex_unlock();
49b67f
+fail:
49b67f
+	return this;
49b67f
+}
49b67f
+
49b67f
+void mnts_remove_submount(const char *mp)
49b67f
+{
49b67f
+	struct mnt_list *this;
49b67f
+
49b67f
+	mnts_hash_mutex_lock();
49b67f
+	this = mnts_lookup(mp);
49b67f
+	if (this && this->flags & MNTS_AUTOFS) {
49b67f
+		this->flags &= ~MNTS_AUTOFS;
49b67f
+		this->ap = NULL;
49b67f
+		list_del_init(&this->submount);
49b67f
+		__mnts_put_mount(this);
49b67f
+	}
49b67f
+	mnts_hash_mutex_unlock();
49b67f
+}
49b67f
+
49b67f
+void mnts_get_submount_list(struct list_head *mnts, struct autofs_point *ap)
49b67f
+{
49b67f
+	struct mnt_list *mnt;
49b67f
+
49b67f
+	mnts_hash_mutex_lock();
49b67f
+	if (list_empty(&ap->submounts))
49b67f
+		goto done;
49b67f
+	list_for_each_entry(mnt, &ap->submounts, submount) {
49b67f
+		__mnts_get_mount(mnt);
49b67f
+		list_add(&mnt->submount_work, mnts);
49b67f
+	}
49b67f
+done:
49b67f
+	mnts_hash_mutex_unlock();
49b67f
+}
49b67f
+
49b67f
+void mnts_put_submount_list(struct list_head *mnts)
49b67f
+{
49b67f
+	struct mnt_list *mnt, *tmp;
49b67f
+
49b67f
+	mnts_hash_mutex_lock();
49b67f
+	list_for_each_entry_safe(mnt, tmp, mnts, submount_work) {
49b67f
+		list_del_init(&mnt->submount_work);
49b67f
+		__mnts_put_mount(mnt);
49b67f
+	}
49b67f
+	mnts_hash_mutex_unlock();
49b67f
+}
49b67f
+
49b67f
 /* From glibc decode_name() */
49b67f
 /* Since the values in a line are separated by spaces, a name cannot
49b67f
  * contain a space.  Therefore some programs encode spaces in names
49b67f
--- autofs-5.1.4.orig/modules/mount_autofs.c
49b67f
+++ autofs-5.1.4/modules/mount_autofs.c
49b67f
@@ -65,6 +65,7 @@ int mount_mount(struct autofs_point *ap,
49b67f
 	struct master_mapent *entry;
49b67f
 	struct map_source *source;
49b67f
 	struct autofs_point *nap;
49b67f
+	struct mnt_list *mnt;
49b67f
 	char buf[MAX_ERR_BUF];
49b67f
 	char *options, *p;
49b67f
 	int len, ret;
49b67f
@@ -307,6 +308,18 @@ int mount_mount(struct autofs_point *ap,
49b67f
 		return 1;
49b67f
 	}
49b67f
 
49b67f
+	mnt = mnts_add_submount(nap);
49b67f
+	if (!mnt) {
49b67f
+		crit(ap->logopt,
49b67f
+		     MODPREFIX "failed to allocate mount %s", realpath);
49b67f
+		handle_mounts_startup_cond_destroy(&suc);
49b67f
+		mounts_mutex_unlock(ap);
49b67f
+		master_free_map_source(source, 1);
49b67f
+		master_free_mapent(entry);
49b67f
+		return 1;
49b67f
+	}
49b67f
+
49b67f
+
49b67f
 	suc.ap = nap;
49b67f
 	suc.root = mountpoint;
49b67f
 	suc.done = 0;
49b67f
@@ -318,6 +331,7 @@ int mount_mount(struct autofs_point *ap,
49b67f
 		     "failed to create mount handler thread for %s",
49b67f
 		     realpath);
49b67f
 		handle_mounts_startup_cond_destroy(&suc);
49b67f
+		mnts_remove_submount(nap->path);
49b67f
 		mounts_mutex_unlock(ap);
49b67f
 		master_free_map_source(source, 1);
49b67f
 		master_free_mapent(entry);
49b67f
@@ -328,6 +342,7 @@ int mount_mount(struct autofs_point *ap,
49b67f
 		status = pthread_cond_wait(&suc.cond, &suc.mutex);
49b67f
 		if (status) {
49b67f
 			handle_mounts_startup_cond_destroy(&suc);
49b67f
+			mnts_remove_submount(nap->path);
49b67f
 			mounts_mutex_unlock(ap);
49b67f
 			master_free_map_source(source, 1);
49b67f
 			master_free_mapent(entry);
49b67f
@@ -339,6 +354,7 @@ int mount_mount(struct autofs_point *ap,
49b67f
 		crit(ap->logopt,
49b67f
 		     MODPREFIX "failed to create submount for %s", realpath);
49b67f
 		handle_mounts_startup_cond_destroy(&suc);
49b67f
+		mnts_remove_submount(nap->path);
49b67f
 		mounts_mutex_unlock(ap);
49b67f
 		master_free_map_source(source, 1);
49b67f
 		master_free_mapent(entry);
49b67f
@@ -347,7 +363,6 @@ int mount_mount(struct autofs_point *ap,
49b67f
 	nap->thid = thid;
49b67f
 
49b67f
 	ap->submnt_count++;
49b67f
-	list_add(&nap->mounts, &ap->submounts);
49b67f
 
49b67f
 	handle_mounts_startup_cond_destroy(&suc);
49b67f
 	mounts_mutex_unlock(ap);