summaryrefslogtreecommitdiffstats
path: root/utils/gssd/gssd.c
diff options
context:
space:
mode:
authorOlga Kornievskaia <kolga@netapp.com>2016-05-14 12:13:29 -0400
committerSteve Dickson <steved@redhat.com>2016-05-14 12:35:14 -0400
commitd9ba9eede533fed6dde146f891d5d596016b314b (patch)
treef77624acc5ee7b2b92cd4b8332414ad8764c7727 /utils/gssd/gssd.c
parent28e244eb8eb986b75261a48c2e49685be2f2f005 (diff)
downloadnfs-utils-d9ba9eede533fed6dde146f891d5d596016b314b.tar.gz
nfs-utils-d9ba9eede533fed6dde146f891d5d596016b314b.tar.xz
nfs-utils-d9ba9eede533fed6dde146f891d5d596016b314b.zip
gssd: move read of upcall into main thread
This patch moves reading of the upcall information from the child thread into the main thread. It removes the need to synchronize between the parent and child thread before processing upcall. Also it creates the thread in a detached state. Signed-off-by: Olga Kornievskaia <kolga@netapp.com> Signed-off-by: Steve Dickson <steved@redhat.com>
Diffstat (limited to 'utils/gssd/gssd.c')
-rw-r--r--utils/gssd/gssd.c93
1 files changed, 65 insertions, 28 deletions
diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
index 9bf7917..2179e15 100644
--- a/utils/gssd/gssd.c
+++ b/utils/gssd/gssd.c
@@ -363,54 +363,91 @@ gssd_destroy_client(struct clnt_info *clp)
static void gssd_scan(void);
-static inline void
-wait_for_child_and_detach(pthread_t th)
+static int
+start_upcall_thread(void (*func)(struct clnt_upcall_info *), void *info)
{
- pthread_mutex_lock(&pmutex);
- while (!thread_started)
- pthread_cond_wait(&pcond, &pmutex);
- thread_started = false;
- pthread_mutex_unlock(&pmutex);
- pthread_detach(th);
+ pthread_attr_t attr;
+ pthread_t th;
+ int ret;
+
+ ret = pthread_attr_init(&attr);
+ if (ret != 0) {
+ printerr(0, "ERROR: failed to init pthread attr: ret %d: %s\n",
+ ret, strerror(errno));
+ return ret;
+ }
+ ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ if (ret != 0) {
+ printerr(0, "ERROR: failed to create pthread attr: ret %d: "
+ "%s\n", ret, strerror(errno));
+ return ret;
+ }
+
+ ret = pthread_create(&th, &attr, (void *)func, (void *)info);
+ if (ret != 0)
+ printerr(0, "ERROR: pthread_create failed: ret %d: %s\n",
+ ret, strerror(errno));
+ return ret;
+}
+
+static struct clnt_upcall_info *alloc_upcall_info(struct clnt_info *clp)
+{
+ struct clnt_upcall_info *info;
+
+ info = malloc(sizeof(struct clnt_upcall_info));
+ if (info == NULL)
+ return NULL;
+ info->clp = clp;
+
+ return info;
}
-/* For each upcall create a thread, detach from the main process so that
- * resources are released back into the system without the need for a join.
- * We need to wait for the child thread to start and consume the event from
- * the file descriptor.
+/* For each upcall read the upcall info into the buffer, then create a
+ * thread in a detached state so that resources are released back into
+ * the system without the need for a join.
*/
static void
gssd_clnt_gssd_cb(int UNUSED(fd), short UNUSED(which), void *data)
{
struct clnt_info *clp = data;
- pthread_t th;
- int ret;
+ struct clnt_upcall_info *info;
- ret = pthread_create(&th, NULL, (void *)handle_gssd_upcall,
- (void *)clp);
- if (ret != 0) {
- printerr(0, "ERROR: pthread_create failed: ret %d: %s\n",
- ret, strerror(errno));
+ info = alloc_upcall_info(clp);
+ if (info == NULL)
+ return;
+
+ info->lbuflen = read(clp->gssd_fd, info->lbuf, sizeof(info->lbuf));
+ if (info->lbuflen <= 0 || info->lbuf[info->lbuflen-1] != '\n') {
+ printerr(0, "WARNING: %s: failed reading request\n", __func__);
+ free(info);
return;
}
- wait_for_child_and_detach(th);
+ info->lbuf[info->lbuflen-1] = 0;
+
+ if (start_upcall_thread(handle_gssd_upcall, info))
+ free(info);
}
static void
gssd_clnt_krb5_cb(int UNUSED(fd), short UNUSED(which), void *data)
{
struct clnt_info *clp = data;
- pthread_t th;
- int ret;
+ struct clnt_upcall_info *info;
- ret = pthread_create(&th, NULL, (void *)handle_krb5_upcall,
- (void *)clp);
- if (ret != 0) {
- printerr(0, "ERROR: pthread_create failed: ret %d: %s\n",
- ret, strerror(errno));
+ info = alloc_upcall_info(clp);
+ if (info == NULL)
+ return;
+
+ if (read(clp->krb5_fd, &info->uid,
+ sizeof(info->uid)) < (ssize_t)sizeof(info->uid)) {
+ printerr(0, "WARNING: %s: failed reading uid from krb5 "
+ "upcall pipe: %s\n", __func__, strerror(errno));
+ free(info);
return;
}
- wait_for_child_and_detach(th);
+
+ if (start_upcall_thread(handle_krb5_upcall, info))
+ free(info);
}
static struct clnt_info *