Blame SOURCES/autofs-5.1.6-use-struct-mnt_list-mounted-list-for-expire.patch

49b67f
autofs-5.1.6 - use struct mnt_list mounted list for expire
49b67f
49b67f
From: Ian Kent <raven@themaw.net>
49b67f
49b67f
Now we are keeping track of mounted mounts using the mnt_list struct
49b67f
use it to drive the expire instead of using the system mount table.
49b67f
49b67f
Signed-off-by: Ian Kent <raven@themaw.net>
49b67f
---
49b67f
 CHANGELOG         |    1 
49b67f
 daemon/direct.c   |   61 +++++++----------
49b67f
 daemon/indirect.c |   66 +++++++++----------
49b67f
 include/mounts.h  |    5 -
49b67f
 lib/master.c      |   36 +---------
49b67f
 lib/mounts.c      |  185 ++++++++++++++++++++++++++++++++++++++++++++++--------
49b67f
 6 files changed, 223 insertions(+), 131 deletions(-)
49b67f
49b67f
--- autofs-5.1.4.orig/CHANGELOG
49b67f
+++ autofs-5.1.4/CHANGELOG
49b67f
@@ -129,6 +129,7 @@ xx/xx/2018 autofs-5.1.5
49b67f
 - fix remount expire.
49b67f
 - fix stale offset directories disable mount.
49b67f
 - use struct mnt_list to track mounted mounts.
49b67f
+- use struct mnt_list mounted list for expire.
49b67f
 
49b67f
 19/12/2017 autofs-5.1.4
49b67f
 - fix spec file url.
49b67f
--- autofs-5.1.4.orig/daemon/direct.c
49b67f
+++ autofs-5.1.4/daemon/direct.c
49b67f
@@ -77,9 +77,8 @@ static void key_mnt_params_init(void)
49b67f
 
49b67f
 static void mnts_cleanup(void *arg)
49b67f
 {
49b67f
-	struct mnt_list *mnts = (struct mnt_list *) arg;
49b67f
-	tree_free_mnt_tree(mnts);
49b67f
-	return;
49b67f
+	struct list_head *mnts = (struct list_head *) arg;
49b67f
+	mnts_put_expire_list(mnts);
49b67f
 }
49b67f
 
49b67f
 int do_umount_autofs_direct(struct autofs_point *ap, struct mapent *me)
49b67f
@@ -788,8 +787,8 @@ out_err:
49b67f
 void *expire_proc_direct(void *arg)
49b67f
 {
49b67f
 	struct ioctl_ops *ops = get_ioctl_ops();
49b67f
-	struct mnt_list *mnts = NULL, *next;
49b67f
-	struct list_head list, *p;
49b67f
+	struct mnt_list *mnt;
49b67f
+	LIST_HEAD(mnts);
49b67f
 	struct expire_args *ea;
49b67f
 	struct expire_args ec;
49b67f
 	struct autofs_point *ap;
49b67f
@@ -821,31 +820,24 @@ void *expire_proc_direct(void *arg)
49b67f
 
49b67f
 	left = 0;
49b67f
 
49b67f
-	mnts = tree_make_mnt_tree("/");
49b67f
-	pthread_cleanup_push(mnts_cleanup, mnts);
49b67f
-
49b67f
-	/* Get a list of mounts select real ones and expire them if possible */
49b67f
-	INIT_LIST_HEAD(&list);
49b67f
-	if (!tree_get_mnt_list(mnts, &list, "/", 0)) {
49b67f
-		ec.status = 0;
49b67f
-		return NULL;
49b67f
-	}
49b67f
-
49b67f
-	list_for_each(p, &list) {
49b67f
-		next = list_entry(p, struct mnt_list, list);
49b67f
-
49b67f
+	/* Get the list of real mounts and expire them if possible */
49b67f
+	mnts_get_expire_list(&mnts, ap);
49b67f
+	if (list_empty(&mnts))
49b67f
+		goto done;
49b67f
+	pthread_cleanup_push(mnts_cleanup, &mnts);
49b67f
+	list_for_each_entry(mnt, &mnts, expire) {
49b67f
 		/*
49b67f
 		 * All direct mounts must be present in the map
49b67f
 		 * entry cache.
49b67f
 		 */
49b67f
 		pthread_cleanup_push(master_source_lock_cleanup, ap->entry);
49b67f
 		master_source_readlock(ap->entry);
49b67f
-		me = lookup_source_mapent(ap, next->mp, LKP_DISTINCT);
49b67f
+		me = lookup_source_mapent(ap, mnt->mp, LKP_DISTINCT);
49b67f
 		pthread_cleanup_pop(1);
49b67f
 		if (!me)
49b67f
 			continue;
49b67f
 
49b67f
-		if (next->flags & MNTS_AUTOFS) {
49b67f
+		if (mnt->flags & (MNTS_AUTOFS|MNTS_OFFSET)) {
49b67f
 			struct stat st;
49b67f
 			int ioctlfd;
49b67f
 
49b67f
@@ -856,22 +848,17 @@ void *expire_proc_direct(void *arg)
49b67f
 			 * one of them and pass on state change.
49b67f
 			 */
49b67f
 			pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
49b67f
-			if (next->flags & MNTS_INDIRECT) {
49b67f
-				master_notify_submount(ap, next->mp, ap->state);
49b67f
-				pthread_setcancelstate(cur_state, NULL);
49b67f
-				continue;
49b67f
-			}
49b67f
+			if (mnt->flags & MNTS_AUTOFS)
49b67f
+				master_notify_submount(ap, mnt->mp, ap->state);
49b67f
 
49b67f
 			if (me->ioctlfd == -1) {
49b67f
 				pthread_setcancelstate(cur_state, NULL);
49b67f
 				continue;
49b67f
 			}
49b67f
 
49b67f
-			/* It's got a mount, deal with in the outer loop */
49b67f
-			if (is_mounted(me->key, MNTS_REAL)) {
49b67f
-				pthread_setcancelstate(cur_state, NULL);
49b67f
-				continue;
49b67f
-			}
49b67f
+			/* It's got a mount, just send the expire. */
49b67f
+			if (is_mounted(me->key, MNTS_REAL))
49b67f
+				goto cont;
49b67f
 
49b67f
 			/*
49b67f
 			 * Maybe a manual umount, repair.
49b67f
@@ -888,19 +875,19 @@ void *expire_proc_direct(void *arg)
49b67f
 			cache_writelock(me->mc);
49b67f
 			if (me->ioctlfd != -1 && 
49b67f
 			    fstat(me->ioctlfd, &st) != -1 &&
49b67f
-			    !count_mounts(ap, next->mp, st.st_dev)) {
49b67f
+			    !count_mounts(ap, mnt->mp, st.st_dev)) {
49b67f
 				ops->close(ap->logopt, me->ioctlfd);
49b67f
 				me->ioctlfd = -1;
49b67f
 				cache_unlock(me->mc);
49b67f
-				mnts_remove_mount(next->mp, MNTS_MOUNTED);
49b67f
+				mnts_remove_mount(mnt->mp, MNTS_MOUNTED);
49b67f
 				pthread_setcancelstate(cur_state, NULL);
49b67f
 				continue;
49b67f
 			}
49b67f
 			cache_unlock(me->mc);
49b67f
-
49b67f
+cont:
49b67f
 			ioctlfd = me->ioctlfd;
49b67f
 
49b67f
-			ret = ops->expire(ap->logopt, ioctlfd, next->mp, how);
49b67f
+			ret = ops->expire(ap->logopt, ioctlfd, mnt->mp, how);
49b67f
 			if (ret) {
49b67f
 				left++;
49b67f
 				pthread_setcancelstate(cur_state, NULL);
49b67f
@@ -923,10 +910,10 @@ void *expire_proc_direct(void *arg)
49b67f
 		if (ap->state == ST_EXPIRE || ap->state == ST_PRUNE)
49b67f
 			pthread_testcancel();
49b67f
 
49b67f
-		debug(ap->logopt, "send expire to trigger %s", next->mp);
49b67f
+		debug(ap->logopt, "send expire to trigger %s", mnt->mp);
49b67f
 
49b67f
 		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
49b67f
-		ret = ops->expire(ap->logopt, ioctlfd, next->mp, how);
49b67f
+		ret = ops->expire(ap->logopt, ioctlfd, mnt->mp, how);
49b67f
 		if (ret)
49b67f
 			left++;
49b67f
 		pthread_setcancelstate(cur_state, NULL);
49b67f
@@ -935,7 +922,7 @@ void *expire_proc_direct(void *arg)
49b67f
 
49b67f
 	if (left)
49b67f
 		debug(ap->logopt, "%d remaining in %s", left, ap->path);
49b67f
-
49b67f
+done:
49b67f
 	ec.status = left;
49b67f
 
49b67f
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
49b67f
--- autofs-5.1.4.orig/daemon/indirect.c
49b67f
+++ autofs-5.1.4/daemon/indirect.c
49b67f
@@ -343,17 +343,17 @@ force_umount:
49b67f
 
49b67f
 static void mnts_cleanup(void *arg)
49b67f
 {
49b67f
-	struct mnt_list *mnts = (struct mnt_list *) arg;
49b67f
-	free_mnt_list(mnts);
49b67f
-	return;
49b67f
+	struct list_head *mnts = (struct list_head *) arg;
49b67f
+	mnts_put_expire_list(mnts);
49b67f
 }
49b67f
 
49b67f
 void *expire_proc_indirect(void *arg)
49b67f
 {
49b67f
 	struct ioctl_ops *ops = get_ioctl_ops();
49b67f
 	struct autofs_point *ap;
49b67f
-	struct mapent *me = NULL;
49b67f
-	struct mnt_list *mnts = NULL, *next;
49b67f
+	struct mnt_list *mnt;
49b67f
+	LIST_HEAD(mnts);
49b67f
+	struct mapent *me;
49b67f
 	struct expire_args *ea;
49b67f
 	struct expire_args ec;
49b67f
 	unsigned int how;
49b67f
@@ -385,36 +385,34 @@ void *expire_proc_indirect(void *arg)
49b67f
 
49b67f
 	left = 0;
49b67f
 
49b67f
-	/* Get a list of real mounts and expire them if possible */
49b67f
-	mnts = get_mnt_list(ap->path, 0);
49b67f
-	pthread_cleanup_push(mnts_cleanup, mnts);
49b67f
-	for (next = mnts; next; next = next->next) {
49b67f
+	/* Get the list of real mounts and expire them if possible */
49b67f
+	mnts_get_expire_list(&mnts, ap);
49b67f
+	if (list_empty(&mnts))
49b67f
+		goto done;
49b67f
+	pthread_cleanup_push(mnts_cleanup, &mnts);
49b67f
+	list_for_each_entry(mnt, &mnts, expire) {
49b67f
 		char *ind_key;
49b67f
 		int ret;
49b67f
 
49b67f
-		if (next->flags & MNTS_AUTOFS) {
49b67f
+		if (mnt->flags & (MNTS_AUTOFS|MNTS_OFFSET)) {
49b67f
 			/*
49b67f
 			 * If we have submounts check if this path lives below
49b67f
 			 * one of them and pass on the state change.
49b67f
 			 */
49b67f
 			pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
49b67f
-			if (next->flags & MNTS_INDIRECT)
49b67f
-				master_notify_submount(ap, next->mp, ap->state);
49b67f
-			else if (next->flags & MNTS_OFFSET) {
49b67f
+			if (mnt->flags & MNTS_AUTOFS)
49b67f
+				master_notify_submount(ap, mnt->mp, ap->state);
49b67f
+
49b67f
+			/* An offset without a real mount, check for manual umount */
49b67f
+			if (mnt->flags & MNTS_OFFSET &&
49b67f
+			    !is_mounted(mnt->mp, MNTS_REAL)) {
49b67f
 				struct mnt_list *sbmnt;
49b67f
 				struct map_source *map;
49b67f
 				struct mapent_cache *mc = NULL;
49b67f
-				struct mapent *me = NULL;
49b67f
 				struct stat st;
49b67f
 
49b67f
-				/* It's got a mount, deal with in the outer loop */
49b67f
-				if (is_mounted(next->mp, MNTS_REAL)) {
49b67f
-					pthread_setcancelstate(cur_state, NULL);
49b67f
-					continue;
49b67f
-				}
49b67f
-
49b67f
 				/* Don't touch submounts */
49b67f
-				sbmnt = mnts_find_submount(next->mp);
49b67f
+				sbmnt = mnts_find_submount(mnt->mp);
49b67f
 				if (sbmnt) {
49b67f
 					mnts_put_mount(sbmnt);
49b67f
 					pthread_setcancelstate(cur_state, NULL);
49b67f
@@ -427,7 +425,7 @@ void *expire_proc_indirect(void *arg)
49b67f
 				while (map) {
49b67f
 					mc = map->mc;
49b67f
 					cache_writelock(mc);
49b67f
-					me = cache_lookup_distinct(mc, next->mp);
49b67f
+					me = cache_lookup_distinct(mc, mnt->mp);
49b67f
 					if (me)
49b67f
 						break;
49b67f
 					cache_unlock(mc);
49b67f
@@ -456,10 +454,10 @@ void *expire_proc_indirect(void *arg)
49b67f
 
49b67f
 				cache_unlock(mc);
49b67f
 				master_source_unlock(ap->entry);
49b67f
+				pthread_setcancelstate(cur_state, NULL);
49b67f
+				continue;
49b67f
 			}
49b67f
-
49b67f
 			pthread_setcancelstate(cur_state, NULL);
49b67f
-			continue;
49b67f
 		}
49b67f
 
49b67f
 		if (ap->state == ST_EXPIRE || ap->state == ST_PRUNE)
49b67f
@@ -469,7 +467,7 @@ void *expire_proc_indirect(void *arg)
49b67f
 		 * If the mount corresponds to an offset trigger then
49b67f
 		 * the key is the path, otherwise it's the last component.
49b67f
 		 */
49b67f
-		ind_key = strrchr(next->mp, '/');
49b67f
+		ind_key = strrchr(mnt->mp, '/');
49b67f
 		if (ind_key)
49b67f
 			ind_key++;
49b67f
 
49b67f
@@ -482,7 +480,7 @@ void *expire_proc_indirect(void *arg)
49b67f
 		 */
49b67f
 		pthread_cleanup_push(master_source_lock_cleanup, ap->entry);
49b67f
 		master_source_readlock(ap->entry);
49b67f
-		me = lookup_source_mapent(ap, next->mp, LKP_DISTINCT);
49b67f
+		me = lookup_source_mapent(ap, mnt->mp, LKP_DISTINCT);
49b67f
 		if (!me && ind_key)
49b67f
 			me = lookup_source_mapent(ap, ind_key, LKP_NORMAL);
49b67f
 		pthread_cleanup_pop(1);
49b67f
@@ -494,10 +492,10 @@ void *expire_proc_indirect(void *arg)
49b67f
 			cache_unlock(me->mc);
49b67f
 		}
49b67f
 
49b67f
-		debug(ap->logopt, "expire %s", next->mp);
49b67f
+		debug(ap->logopt, "expire %s", mnt->mp);
49b67f
 
49b67f
 		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
49b67f
-		ret = ops->expire(ap->logopt, ioctlfd, next->mp, how);
49b67f
+		ret = ops->expire(ap->logopt, ioctlfd, mnt->mp, how);
49b67f
 		if (ret)
49b67f
 			left++;
49b67f
 		pthread_setcancelstate(cur_state, NULL);
49b67f
@@ -519,14 +517,14 @@ void *expire_proc_indirect(void *arg)
49b67f
 	pthread_cleanup_pop(1);
49b67f
 
49b67f
 	count = offsets = submnts = 0;
49b67f
-	mnts = get_mnt_list(ap->path, 0);
49b67f
-	pthread_cleanup_push(mnts_cleanup, mnts);
49b67f
+	mnts_get_expire_list(&mnts, ap);
49b67f
+	pthread_cleanup_push(mnts_cleanup, &mnts);
49b67f
 	/* Are there any real mounts left */
49b67f
-	for (next = mnts; next; next = next->next) {
49b67f
-		if (!(next->flags & MNTS_AUTOFS))
49b67f
+	list_for_each_entry(mnt, &mnts, expire) {
49b67f
+		if (!(mnt->flags & MNTS_AUTOFS))
49b67f
 			count++;
49b67f
 		else {
49b67f
-			if (next->flags & MNTS_INDIRECT)
49b67f
+			if (mnt->flags & MNTS_INDIRECT)
49b67f
 				submnts++;
49b67f
 			else
49b67f
 				offsets++;
49b67f
@@ -544,7 +542,7 @@ void *expire_proc_indirect(void *arg)
49b67f
 	 */
49b67f
 	if (count)
49b67f
 		debug(ap->logopt, "%d remaining in %s", count, ap->path);
49b67f
-
49b67f
+done:
49b67f
 	ec.status = left;
49b67f
 
49b67f
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
49b67f
--- autofs-5.1.4.orig/include/mounts.h
49b67f
+++ autofs-5.1.4/include/mounts.h
49b67f
@@ -63,6 +63,8 @@ struct mnt_list {
49b67f
 
49b67f
 	/* List of mounts of an autofs_point */
49b67f
 	struct list_head mount;
49b67f
+	/* Mounted mounts list for expire */
49b67f
+	struct list_head expire;
49b67f
 
49b67f
 	/* List of sub-mounts of an autofs_point */
49b67f
 	struct autofs_point *ap;
49b67f
@@ -129,15 +131,12 @@ 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 *mnts_find_amdmount(const char *path);
49b67f
 struct mnt_list *mnts_add_amdmount(struct autofs_point *ap, struct amd_entry *entry);
49b67f
 void mnts_remove_amdmount(const char *mp);
49b67f
 struct mnt_list *mnts_add_mount(struct autofs_point *ap, const char *name, unsigned int flags);
49b67f
 void mnts_remove_mount(const char *mp, unsigned int flags);
49b67f
 struct mnt_list *get_mnt_list(const char *path, int include);
49b67f
-unsigned int mnts_has_mounted_mounts(struct autofs_point *ap);
49b67f
 void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap);
49b67f
 void mnts_put_expire_list(struct list_head *mnts);
49b67f
 void mnts_set_mounted_mount(struct autofs_point *ap, const char *name);
49b67f
--- autofs-5.1.4.orig/lib/master.c
49b67f
+++ autofs-5.1.4/lib/master.c
49b67f
@@ -1133,40 +1133,17 @@ int master_submount_list_empty(struct au
49b67f
 int master_notify_submount(struct autofs_point *ap, const char *path, enum states state)
49b67f
 {
49b67f
 	struct mnt_list *this, *sbmnt;
49b67f
-	LIST_HEAD(sbmnts);
49b67f
 	int ret = 1;
49b67f
 
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->mp, path))
49b67f
-			continue;
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
+	this = mnts_find_submount(path);
49b67f
+	if (this) {
49b67f
+		/* We have found a submount to expire */
49b67f
 		st_mutex_lock();
49b67f
 
49b67f
 		if (this->ap->state == ST_SHUTDOWN) {
49b67f
 			this = NULL;
49b67f
 			st_mutex_unlock();
49b67f
-			break;
49b67f
+			goto done;
49b67f
 		}
49b67f
 
49b67f
 		this->ap->shutdown = ap->shutdown;
49b67f
@@ -1202,11 +1179,10 @@ int master_notify_submount(struct autofs
49b67f
 			st_mutex_lock();
49b67f
 		}
49b67f
 		st_mutex_unlock();
49b67f
-		break;
49b67f
+done:
49b67f
+		mnts_put_mount(this);
49b67f
 	}
49b67f
 
49b67f
-	mnts_put_submount_list(&sbmnts);
49b67f
-
49b67f
 	return ret;
49b67f
 }
49b67f
 
49b67f
--- autofs-5.1.4.orig/lib/mounts.c
49b67f
+++ autofs-5.1.4/lib/mounts.c
49b67f
@@ -888,6 +888,7 @@ static struct mnt_list *mnts_alloc_mount
49b67f
 	INIT_LIST_HEAD(&this->submount);
49b67f
 	INIT_LIST_HEAD(&this->submount_work);
49b67f
 	INIT_LIST_HEAD(&this->amdmount);
49b67f
+	INIT_LIST_HEAD(&this->expire);
49b67f
 done:
49b67f
 	return this;
49b67f
 }
49b67f
@@ -1022,33 +1023,6 @@ void mnts_remove_submount(const char *mp
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
 struct mnt_list *mnts_find_amdmount(const char *path)
49b67f
 {
49b67f
 	struct mnt_list *mnt;
49b67f
@@ -1234,6 +1208,163 @@ void mnts_set_mounted_mount(struct autof
49b67f
 	}
49b67f
 }
49b67f
 
49b67f
+struct node {
49b67f
+	struct mnt_list *mnt;
49b67f
+	struct node *left;
49b67f
+	struct node *right;
49b67f
+};
49b67f
+
49b67f
+static struct node *new(struct mnt_list *mnt)
49b67f
+{
49b67f
+	struct node *n;
49b67f
+
49b67f
+	n = malloc(sizeof(struct node));
49b67f
+	if (!n)
49b67f
+		return NULL;
49b67f
+	memset(n, 0, sizeof(struct node));
49b67f
+	n->mnt = mnt;
49b67f
+
49b67f
+	return n;
49b67f
+}
49b67f
+
49b67f
+static struct node *tree_root(struct mnt_list *mnt)
49b67f
+{
49b67f
+	struct node *n;
49b67f
+
49b67f
+	n = new(mnt);
49b67f
+	if (!n) {
49b67f
+		error(LOGOPT_ANY, "failed to allcate tree root");
49b67f
+		return NULL;
49b67f
+	}
49b67f
+
49b67f
+	return n;
49b67f
+}
49b67f
+
49b67f
+static struct node *add_left(struct node *this, struct mnt_list *mnt)
49b67f
+{
49b67f
+	struct node *n;
49b67f
+
49b67f
+	n = new(mnt);
49b67f
+	if (!n) {
49b67f
+		error(LOGOPT_ANY, "failed to allcate tree node");
49b67f
+		return NULL;
49b67f
+	}
49b67f
+	this->left = n;
49b67f
+
49b67f
+	return n;
49b67f
+}
49b67f
+
49b67f
+static struct node *add_right(struct node *this, struct mnt_list *mnt)
49b67f
+{
49b67f
+	struct node *n;
49b67f
+
49b67f
+	n = new(mnt);
49b67f
+	if (!n) {
49b67f
+		error(LOGOPT_ANY, "failed to allcate tree node");
49b67f
+		return NULL;
49b67f
+	}
49b67f
+	this->right = n;
49b67f
+
49b67f
+	return n;
49b67f
+}
49b67f
+
49b67f
+static struct node *add_node(struct node *root, struct mnt_list *mnt)
49b67f
+{
49b67f
+	struct node *p, *q;
49b67f
+	unsigned int mp_len;
49b67f
+
49b67f
+	mp_len = strlen(mnt->mp);
49b67f
+
49b67f
+	q = root;
49b67f
+	p = root;
49b67f
+
49b67f
+	while (q && strcmp(mnt->mp, p->mnt->mp)) {
49b67f
+		p = q;
49b67f
+		if (mp_len < strlen(p->mnt->mp))
49b67f
+			q = p->left;
49b67f
+		else
49b67f
+			q = p->right;
49b67f
+	}
49b67f
+
49b67f
+	if (strcmp(mnt->mp, p->mnt->mp) == 0)
49b67f
+		error(LOGOPT_ANY, "duplicate entry in mounts list");
49b67f
+	else {
49b67f
+		if (mp_len < strlen(p->mnt->mp))
49b67f
+			return add_left(p, mnt);
49b67f
+		else
49b67f
+			return add_right(p, mnt);
49b67f
+	}
49b67f
+
49b67f
+	return NULL;
49b67f
+}
49b67f
+
49b67f
+static void tree_free(struct node *tree)
49b67f
+{
49b67f
+	if (tree->right)
49b67f
+		tree_free(tree->right);
49b67f
+	if (tree->left)
49b67f
+		tree_free(tree->left);
49b67f
+	free(tree);
49b67f
+}
49b67f
+
49b67f
+static void traverse(struct node *node, struct list_head *mnts)
49b67f
+{
49b67f
+	if (node->right)
49b67f
+		traverse(node->right, mnts);
49b67f
+	list_add_tail(&node->mnt->expire, mnts);
49b67f
+	if (node->left)
49b67f
+		traverse(node->left, mnts);
49b67f
+}
49b67f
+
49b67f
+void mnts_get_expire_list(struct list_head *mnts, struct autofs_point *ap)
49b67f
+{
49b67f
+	struct mnt_list *mnt;
49b67f
+	struct node *tree = NULL;
49b67f
+
49b67f
+	mnts_hash_mutex_lock();
49b67f
+	if (list_empty(&ap->mounts))
49b67f
+		goto done;
49b67f
+
49b67f
+	list_for_each_entry(mnt, &ap->mounts, mount) {
49b67f
+		struct node *n;
49b67f
+
49b67f
+		__mnts_get_mount(mnt);
49b67f
+
49b67f
+		if (!tree) {
49b67f
+			tree = tree_root(mnt);
49b67f
+			if (!tree) {
49b67f
+				error(LOGOPT_ANY, "failed to create expire tree root");
49b67f
+				goto done;
49b67f
+			}
49b67f
+			continue;
49b67f
+		}
49b67f
+
49b67f
+		n = add_node(tree, mnt);
49b67f
+		if (!n) {
49b67f
+			error(LOGOPT_ANY, "failed to add expire tree node");
49b67f
+			tree_free(tree);
49b67f
+			goto done;
49b67f
+		}
49b67f
+	}
49b67f
+
49b67f
+	traverse(tree, mnts);
49b67f
+	tree_free(tree);
49b67f
+done:
49b67f
+	mnts_hash_mutex_unlock();
49b67f
+}
49b67f
+
49b67f
+void mnts_put_expire_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, expire) {
49b67f
+		list_del_init(&mnt->expire);
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