Blob Blame History Raw
autofs-5.0.5 - expire thread use pending mutex

From: Ian Kent <raven@themaw.net>

Some time ago the mount request thread creation was changed to
use its own mutex for its condition handling due to execution
order problems under heavy mount request pressure. When there
are a large number of master map entries we see the same problem
with expire thread creation. This patch changes the expire thread
creation to use the same approach as the mount thread creation.
---

 CHANGELOG           |    1 
 daemon/direct.c     |   76 +++++++++++-----------------------------------------
 daemon/indirect.c   |   76 +++++++++++-----------------------------------------
 include/automount.h |   41 ++++++++++++++++++++++++++++
 4 files changed, 76 insertions(+), 118 deletions(-)


--- autofs-5.0.5.orig/CHANGELOG
+++ autofs-5.0.5/CHANGELOG
@@ -45,6 +45,7 @@
 - remove state machine timed wait.
 - remove extra read master map call.
 - fix error handing in do_mount_indirect().
+- expire thread use pending mutex.
 
 03/09/2009 autofs-5.0.5
 -----------------------
--- autofs-5.0.5.orig/daemon/direct.c
+++ autofs-5.0.5/daemon/direct.c
@@ -35,6 +35,7 @@
 #include <sys/vfs.h>
 #include <sched.h>
 
+#define INCLUDE_PENDING_FUNCTIONS
 #include "automount.h"
 
 /* Attribute to create detached thread */
@@ -48,8 +49,6 @@ pthread_key_t key_mnt_direct_params;
 pthread_key_t key_mnt_offset_params;
 pthread_once_t key_mnt_params_once = PTHREAD_ONCE_INIT;
 
-static pthread_mutex_t ea_mutex = PTHREAD_MUTEX_INITIALIZER;
-
 static void key_mnt_params_destroy(void *arg)
 {
 	struct mnt_params *mp;
@@ -952,17 +951,6 @@ void *expire_proc_direct(void *arg)
 	return NULL;
 }
 
-static void pending_cond_destroy(void *arg)
-{
-	struct pending_args *mt;
-	int status;
-
-	mt = (struct pending_args *) arg;
-	status = pthread_cond_destroy(&mt->cond);
-	if (status)
-		fatal(status);
-}
-
 static void expire_send_fail(void *arg)
 {
 	struct ioctl_ops *ops = get_ioctl_ops();
@@ -972,19 +960,6 @@ static void expire_send_fail(void *arg)
 		       mt->ioctlfd, mt->wait_queue_token, -ENOENT);
 }
 
-static void free_pending_args(void *arg)
-{
-	struct pending_args *mt = arg;
-	free(mt);
-}
-
-static void expire_mutex_unlock(void *arg)
-{
-	int status = pthread_mutex_unlock(&ea_mutex);
-	if (status)
-		fatal(status);
-}
-
 static void *do_expire_direct(void *arg)
 {
 	struct ioctl_ops *ops = get_ioctl_ops();
@@ -995,9 +970,7 @@ static void *do_expire_direct(void *arg)
 
 	args = (struct pending_args *) arg;
 
-	status = pthread_mutex_lock(&ea_mutex);
-	if (status)
-		fatal(status);
+	pending_mutex_lock(args);
 
 	memcpy(&mt, args, sizeof(struct pending_args));
 
@@ -1008,7 +981,7 @@ static void *do_expire_direct(void *arg)
 	if (status)
 		fatal(status);
 
-	expire_mutex_unlock(NULL);
+	pending_mutex_unlock(args);
 
 	pthread_cleanup_push(expire_send_fail, &mt);
 
@@ -1124,7 +1097,7 @@ int handle_packet_expire_direct(struct a
 	if (status)
 		fatal(status);
 
-	status = pthread_mutex_lock(&ea_mutex);
+	status = pthread_mutex_init(&mt->mutex, NULL);
 	if (status)
 		fatal(status);
 
@@ -1140,6 +1113,8 @@ int handle_packet_expire_direct(struct a
 	debug(ap->logopt, "token %ld, name %s",
 		  (unsigned long) pkt->wait_queue_token, mt->name);
 
+	pending_mutex_lock(mt);
+
 	status = pthread_create(&thid, &th_attr_detached, do_expire_direct, mt);
 	if (status) {
 		error(ap->logopt, "expire thread create failed");
@@ -1147,8 +1122,9 @@ int handle_packet_expire_direct(struct a
 			       mt->ioctlfd, pkt->wait_queue_token, -status);
 		cache_unlock(mc);
 		master_source_unlock(ap->entry);
-		expire_mutex_unlock(NULL);
+		pending_mutex_unlock(mt);
 		pending_cond_destroy(mt);
+		pending_mutex_destroy(mt);
 		free_pending_args(mt);
 		pthread_setcancelstate(state, NULL);
 		return 1;
@@ -1158,8 +1134,9 @@ int handle_packet_expire_direct(struct a
 	master_source_unlock(ap->entry);
 
 	pthread_cleanup_push(free_pending_args, mt);
+	pthread_cleanup_push(pending_mutex_destroy, mt);
 	pthread_cleanup_push(pending_cond_destroy, mt);
-	pthread_cleanup_push(expire_mutex_unlock, NULL);
+	pthread_cleanup_push(pending_mutex_unlock, mt);
 	pthread_setcancelstate(state, NULL);
 
 	mt->signaled = 0;
@@ -1167,7 +1144,7 @@ int handle_packet_expire_direct(struct a
 		gettimeofday(&now, NULL);
 		wait.tv_sec = now.tv_sec + 2;
 		wait.tv_nsec = now.tv_usec * 1000;
-		status = pthread_cond_wait(&mt->cond, &ea_mutex);
+		status = pthread_cond_timedwait(&mt->cond, &mt->mutex, &wait);
 		if (status && status != ETIMEDOUT)
 			fatal(status);
 	}
@@ -1175,6 +1152,7 @@ int handle_packet_expire_direct(struct a
 	pthread_cleanup_pop(1);
 	pthread_cleanup_pop(1);
 	pthread_cleanup_pop(1);
+	pthread_cleanup_pop(1);
 
 	return 0;
 }
@@ -1188,22 +1166,6 @@ static void mount_send_fail(void *arg)
 	ops->close(ap->logopt, mt->ioctlfd);
 }
 
-static void pending_mutex_destroy(void *arg)
-{
-	struct pending_args *mt = (struct pending_args *) arg;
-	int status = pthread_mutex_destroy(&mt->mutex);
-	if (status)
-		fatal(status);
-}
-
-static void mount_mutex_unlock(void *arg)
-{
-	struct pending_args *mt = (struct pending_args *) arg;
-	int status = pthread_mutex_unlock(&mt->mutex);
-	if (status)
-		fatal(status);
-}
-
 static void *do_mount_direct(void *arg)
 {
 	struct ioctl_ops *ops = get_ioctl_ops();
@@ -1214,9 +1176,7 @@ static void *do_mount_direct(void *arg)
 
 	args = (struct pending_args *) arg;
 
-	status = pthread_mutex_lock(&args->mutex);
-	if (status)
-		fatal(status);
+	pending_mutex_lock(args);
 
 	memcpy(&mt, args, sizeof(struct pending_args));
 
@@ -1227,7 +1187,7 @@ static void *do_mount_direct(void *arg)
 	if (status)
 		fatal(status);
 
-	mount_mutex_unlock(args);
+	pending_mutex_unlock(args);
 
 	pthread_cleanup_push(mount_send_fail, &mt);
 
@@ -1434,9 +1394,7 @@ int handle_packet_missing_direct(struct 
 	if (status)
 		fatal(status);
 
-	status = pthread_mutex_lock(&mt->mutex);
-	if (status)
-		fatal(status);
+	pending_mutex_lock(mt);
 
 	mt->ap = ap;
 	mt->ioctlfd = ioctlfd;
@@ -1458,7 +1416,7 @@ int handle_packet_missing_direct(struct 
 		cache_unlock(mc);
 		master_source_unlock(ap->entry);
 		master_mutex_unlock();
-		mount_mutex_unlock(mt);
+		pending_mutex_unlock(mt);
 		pending_cond_destroy(mt);
 		pending_mutex_destroy(mt);
 		free_pending_args(mt);
@@ -1474,7 +1432,7 @@ int handle_packet_missing_direct(struct 
 	pthread_cleanup_push(free_pending_args, mt);
 	pthread_cleanup_push(pending_mutex_destroy, mt);
 	pthread_cleanup_push(pending_cond_destroy, mt);
-	pthread_cleanup_push(mount_mutex_unlock, mt);
+	pthread_cleanup_push(pending_mutex_unlock, mt);
 	pthread_setcancelstate(state, NULL);
 
 	mt->signaled = 0;
--- autofs-5.0.5.orig/daemon/indirect.c
+++ autofs-5.0.5/daemon/indirect.c
@@ -34,13 +34,12 @@
 #include <sys/vfs.h>
 #include <sched.h>
 
+#define INCLUDE_PENDING_FUNCTIONS
 #include "automount.h"
 
 /* Attribute to create detached thread */
 extern pthread_attr_t th_attr_detached;
 
-static pthread_mutex_t ea_mutex = PTHREAD_MUTEX_INITIALIZER;
-
 static int unlink_mount_tree(struct autofs_point *ap, struct mnt_list *mnts)
 {
 	struct mnt_list *this;
@@ -587,17 +586,6 @@ void *expire_proc_indirect(void *arg)
 	return NULL;
 }
 
-static void pending_cond_destroy(void *arg)
-{
-	struct pending_args *mt;
-	int status;
-
-	mt = (struct pending_args *) arg;
-	status = pthread_cond_destroy(&mt->cond);
-	if (status)
-		fatal(status);
-}
-
 static void expire_send_fail(void *arg)
 {
 	struct ioctl_ops *ops = get_ioctl_ops();
@@ -607,19 +595,6 @@ static void expire_send_fail(void *arg)
 		       ap->ioctlfd, mt->wait_queue_token, -ENOENT);
 }
 
-static void free_pending_args(void *arg)
-{
-	struct pending_args *mt = arg;
-	free(mt);
-}
-
-static void expire_mutex_unlock(void *arg)
-{
-	int status = pthread_mutex_unlock(&ea_mutex);
-	if (status)
-		fatal(status);
-}
-
 static void *do_expire_indirect(void *arg)
 {
 	struct ioctl_ops *ops = get_ioctl_ops();
@@ -629,9 +604,7 @@ static void *do_expire_indirect(void *ar
 
 	args = (struct pending_args *) arg;
 
-	status = pthread_mutex_lock(&ea_mutex);
-	if (status)
-		fatal(status);
+	pending_mutex_lock(args);
 
 	memcpy(&mt, args, sizeof(struct pending_args));
 
@@ -642,7 +615,7 @@ static void *do_expire_indirect(void *ar
 	if (status)
 		fatal(status);
 
-	expire_mutex_unlock(NULL);
+	pending_mutex_unlock(args);
 
 	pthread_cleanup_push(expire_send_fail, &mt);
 
@@ -690,7 +663,7 @@ int handle_packet_expire_indirect(struct
 	if (status)
 		fatal(status);
 
-	status = pthread_mutex_lock(&ea_mutex);
+	status = pthread_mutex_init(&mt->mutex, NULL);
 	if (status)
 		fatal(status);
 
@@ -700,21 +673,25 @@ int handle_packet_expire_indirect(struct
 	mt->len = pkt->len;
 	mt->wait_queue_token = pkt->wait_queue_token;
 
+	pending_mutex_lock(mt);
+
 	status = pthread_create(&thid, &th_attr_detached, do_expire_indirect, mt);
 	if (status) {
 		error(ap->logopt, "expire thread create failed");
 		ops->send_fail(ap->logopt,
 			       ap->ioctlfd, pkt->wait_queue_token, -status);
-		expire_mutex_unlock(NULL);
+		pending_mutex_unlock(mt);
 		pending_cond_destroy(mt);
+		pending_mutex_destroy(mt);
 		free_pending_args(mt);
 		pthread_setcancelstate(state, NULL);
 		return 1;
 	}
 
 	pthread_cleanup_push(free_pending_args, mt);
+	pthread_cleanup_push(pending_mutex_destroy, mt);
 	pthread_cleanup_push(pending_cond_destroy, mt);
-	pthread_cleanup_push(expire_mutex_unlock, NULL);
+	pthread_cleanup_push(pending_mutex_unlock, mt);
 	pthread_setcancelstate(state, NULL);
 
 	mt->signaled = 0;
@@ -722,7 +699,7 @@ int handle_packet_expire_indirect(struct
 		gettimeofday(&now, NULL);
 		wait.tv_sec = now.tv_sec + 2;
 		wait.tv_nsec = now.tv_usec * 1000;
-		status = pthread_cond_timedwait(&mt->cond, &ea_mutex, &wait);
+		status = pthread_cond_timedwait(&mt->cond, &mt->mutex, &wait);
 		if (status && status != ETIMEDOUT)
 			fatal(status);
 	}
@@ -730,6 +707,7 @@ int handle_packet_expire_indirect(struct
 	pthread_cleanup_pop(1);
 	pthread_cleanup_pop(1);
 	pthread_cleanup_pop(1);
+	pthread_cleanup_pop(1);
 
 	return 0;
 }
@@ -743,22 +721,6 @@ static void mount_send_fail(void *arg)
 		       ap->ioctlfd, mt->wait_queue_token, -ENOENT);
 }
 
-static void pending_mutex_destroy(void *arg)
-{
-	struct pending_args *mt = (struct pending_args *) arg;
-	int status = pthread_mutex_destroy(&mt->mutex);
-	if (status)
-		fatal(status);
-}
-
-static void mount_mutex_unlock(void *arg)
-{
-	struct pending_args *mt = (struct pending_args *) arg;
-	int status = pthread_mutex_unlock(&mt->mutex);
-	if (status)
-		fatal(status);
-}
-
 static void *do_mount_indirect(void *arg)
 {
 	struct ioctl_ops *ops = get_ioctl_ops();
@@ -770,9 +732,7 @@ static void *do_mount_indirect(void *arg
 
 	args = (struct pending_args *) arg;
 
-	status = pthread_mutex_lock(&args->mutex);
-	if (status)
-		fatal(status);
+	pending_mutex_lock(args);
 
 	memcpy(&mt, args, sizeof(struct pending_args));
 
@@ -783,7 +743,7 @@ static void *do_mount_indirect(void *arg
 	if (status)
 		fatal(status);
 
-	mount_mutex_unlock(args);
+	pending_mutex_unlock(args);
 
 	pthread_cleanup_push(mount_send_fail, &mt);
 
@@ -879,9 +839,7 @@ int handle_packet_missing_indirect(struc
 	if (status)
 		fatal(status);
 
-	status = pthread_mutex_lock(&mt->mutex);
-	if (status)
-		fatal(status);
+	pending_mutex_lock(mt);
 
 	mt->ap = ap;
 	strncpy(mt->name, pkt->name, pkt->len);
@@ -898,7 +856,7 @@ int handle_packet_missing_indirect(struc
 		ops->send_fail(ap->logopt,
 			       ap->ioctlfd, pkt->wait_queue_token, -status);
 		master_mutex_unlock();
-		mount_mutex_unlock(mt);
+		pending_mutex_unlock(mt);
 		pending_cond_destroy(mt);
 		pending_mutex_destroy(mt);
 		free_pending_args(mt);
@@ -911,7 +869,7 @@ int handle_packet_missing_indirect(struc
 	pthread_cleanup_push(free_pending_args, mt);
 	pthread_cleanup_push(pending_mutex_destroy, mt);
 	pthread_cleanup_push(pending_cond_destroy, mt);
-	pthread_cleanup_push(mount_mutex_unlock, mt);
+	pthread_cleanup_push(pending_mutex_unlock, mt);
 	pthread_setcancelstate(state, NULL);
 
 	mt->signaled = 0;
--- autofs-5.0.5.orig/include/automount.h
+++ autofs-5.0.5/include/automount.h
@@ -375,6 +375,47 @@ struct pending_args {
 	unsigned long wait_queue_token;	/* Associated kernel wait token */
 };
 
+#ifdef INCLUDE_PENDING_FUNCTIONS
+static void pending_cond_destroy(void *arg)
+{
+	struct pending_args *mt = (struct pending_args *) arg;
+	int status;
+	status = pthread_cond_destroy(&mt->cond);
+	if (status)
+		fatal(status);
+}
+
+static void pending_mutex_destroy(void *arg)
+{
+	struct pending_args *mt = (struct pending_args *) arg;
+	int status = pthread_mutex_destroy(&mt->mutex);
+	if (status)
+		fatal(status);
+}
+
+static void free_pending_args(void *arg)
+{
+	struct pending_args *mt = (struct pending_args *) arg;
+	free(mt);
+}
+
+static void pending_mutex_lock(void *arg)
+{
+        struct pending_args *mt = (struct pending_args *) arg;
+        int status = pthread_mutex_lock(&mt->mutex);
+        if (status)
+                fatal(status);
+}
+
+static void pending_mutex_unlock(void *arg)
+{
+        struct pending_args *mt = (struct pending_args *) arg;
+        int status = pthread_mutex_unlock(&mt->mutex);
+        if (status)
+                fatal(status);
+}
+#endif
+
 struct thread_stdenv_vars {
 	uid_t uid;
 	gid_t gid;