9ae3f9
From 143b93b230b429cc712353243ed794b68494c040 Mon Sep 17 00:00:00 2001
9ae3f9
From: Mohit Agrawal <moagrawa@redhat.com>
9ae3f9
Date: Mon, 27 Jul 2020 18:08:00 +0530
9ae3f9
Subject: [PATCH 465/465] posix: Implement a janitor thread to close fd
9ae3f9
9ae3f9
Problem: In the commit fb20713b380e1df8d7f9e9df96563be2f9144fd6 we use
9ae3f9
         syntask to close fd but we have found the patch is reducing the
9ae3f9
         performance
9ae3f9
9ae3f9
Solution: Use janitor thread to close fd's and save the pfd ctx into
9ae3f9
          ctx janitor list and also save the posix_xlator into pfd object to
9ae3f9
          avoid the race condition during cleanup in brick_mux environment
9ae3f9
9ae3f9
> Change-Id: Ifb3d18a854b267333a3a9e39845bfefb83fbc092
9ae3f9
> Fixes: #1396
9ae3f9
> Signed-off-by: Mohit Agrawal <moagrawa@redhat.com>
9ae3f9
> (Reviewed on upstream link https://review.gluster.org/#/c/glusterfs/+/24755/)
9ae3f9
> (Cherry pick from commit 41b9616435cbdf671805856e487e373060c9455b
9ae3f9
9ae3f9
Change-Id: Ifb3d18a854b267333a3a9e39845bfefb83fbc092
9ae3f9
BUG: 1851989
9ae3f9
Signed-off-by: Mohit Agrawal <moagrawa@redhat.com>
9ae3f9
Reviewed-on: https://code.engineering.redhat.com/gerrit/209448
9ae3f9
Tested-by: RHGS Build Bot <nigelb@redhat.com>
9ae3f9
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
9ae3f9
---
9ae3f9
 glusterfsd/src/glusterfsd.c                    |  4 ++
9ae3f9
 libglusterfs/src/glusterfs/glusterfs.h         |  7 ++
9ae3f9
 rpc/rpc-lib/src/rpcsvc.c                       |  6 --
9ae3f9
 xlators/storage/posix/src/posix-common.c       | 34 +++++++++-
9ae3f9
 xlators/storage/posix/src/posix-helpers.c      | 93 ++++++++++++++++++++++++++
9ae3f9
 xlators/storage/posix/src/posix-inode-fd-ops.c | 33 ++++-----
9ae3f9
 xlators/storage/posix/src/posix.h              |  7 ++
9ae3f9
 7 files changed, 161 insertions(+), 23 deletions(-)
9ae3f9
9ae3f9
diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c
9ae3f9
index 9821180..955bf1d 100644
9ae3f9
--- a/glusterfsd/src/glusterfsd.c
9ae3f9
+++ b/glusterfsd/src/glusterfsd.c
9ae3f9
@@ -1839,6 +1839,10 @@ glusterfs_ctx_defaults_init(glusterfs_ctx_t *ctx)
9ae3f9
 
9ae3f9
     INIT_LIST_HEAD(&cmd_args->xlator_options);
9ae3f9
     INIT_LIST_HEAD(&cmd_args->volfile_servers);
9ae3f9
+    ctx->pxl_count = 0;
9ae3f9
+    pthread_mutex_init(&ctx->fd_lock, NULL);
9ae3f9
+    pthread_cond_init(&ctx->fd_cond, NULL);
9ae3f9
+    INIT_LIST_HEAD(&ctx->janitor_fds);
9ae3f9
 
9ae3f9
     lim.rlim_cur = RLIM_INFINITY;
9ae3f9
     lim.rlim_max = RLIM_INFINITY;
9ae3f9
diff --git a/libglusterfs/src/glusterfs/glusterfs.h b/libglusterfs/src/glusterfs/glusterfs.h
9ae3f9
index 495a4d7..bf6a987 100644
9ae3f9
--- a/libglusterfs/src/glusterfs/glusterfs.h
9ae3f9
+++ b/libglusterfs/src/glusterfs/glusterfs.h
9ae3f9
@@ -733,6 +733,13 @@ struct _glusterfs_ctx {
9ae3f9
     } stats;
9ae3f9
 
9ae3f9
     struct list_head volfile_list;
9ae3f9
+    /* Add members to manage janitor threads for cleanup fd */
9ae3f9
+    struct list_head janitor_fds;
9ae3f9
+    pthread_cond_t fd_cond;
9ae3f9
+    pthread_mutex_t fd_lock;
9ae3f9
+    pthread_t janitor;
9ae3f9
+    /* The variable is use to save total posix xlator count */
9ae3f9
+    uint32_t pxl_count;
9ae3f9
 
9ae3f9
     char volume_id[GF_UUID_BUF_SIZE]; /* Used only in protocol/client */
9ae3f9
 };
9ae3f9
diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c
9ae3f9
index 23ca1fd..3f184bf 100644
9ae3f9
--- a/rpc/rpc-lib/src/rpcsvc.c
9ae3f9
+++ b/rpc/rpc-lib/src/rpcsvc.c
9ae3f9
@@ -375,12 +375,6 @@ rpcsvc_program_actor(rpcsvc_request_t *req)
9ae3f9
 
9ae3f9
     req->ownthread = program->ownthread;
9ae3f9
     req->synctask = program->synctask;
9ae3f9
-    if (((req->procnum == GFS3_OP_RELEASE) ||
9ae3f9
-         (req->procnum == GFS3_OP_RELEASEDIR)) &&
9ae3f9
-        (program->prognum == GLUSTER_FOP_PROGRAM)) {
9ae3f9
-        req->ownthread = _gf_false;
9ae3f9
-        req->synctask = _gf_true;
9ae3f9
-    }
9ae3f9
 
9ae3f9
     err = SUCCESS;
9ae3f9
     gf_log(GF_RPCSVC, GF_LOG_TRACE, "Actor found: %s - %s for %s",
9ae3f9
diff --git a/xlators/storage/posix/src/posix-common.c b/xlators/storage/posix/src/posix-common.c
9ae3f9
index b317627..c5a43a1 100644
9ae3f9
--- a/xlators/storage/posix/src/posix-common.c
9ae3f9
+++ b/xlators/storage/posix/src/posix-common.c
9ae3f9
@@ -150,6 +150,7 @@ posix_notify(xlator_t *this, int32_t event, void *data, ...)
9ae3f9
     struct timespec sleep_till = {
9ae3f9
         0,
9ae3f9
     };
9ae3f9
+    glusterfs_ctx_t *ctx = this->ctx;
9ae3f9
 
9ae3f9
     switch (event) {
9ae3f9
         case GF_EVENT_PARENT_UP: {
9ae3f9
@@ -160,8 +161,6 @@ posix_notify(xlator_t *this, int32_t event, void *data, ...)
9ae3f9
         case GF_EVENT_PARENT_DOWN: {
9ae3f9
             if (!victim->cleanup_starting)
9ae3f9
                 break;
9ae3f9
-            gf_log(this->name, GF_LOG_INFO, "Sending CHILD_DOWN for brick %s",
9ae3f9
-                   victim->name);
9ae3f9
 
9ae3f9
             if (priv->janitor) {
9ae3f9
                 pthread_mutex_lock(&priv->janitor_mutex);
9ae3f9
@@ -187,6 +186,16 @@ posix_notify(xlator_t *this, int32_t event, void *data, ...)
9ae3f9
                 GF_FREE(priv->janitor);
9ae3f9
             }
9ae3f9
             priv->janitor = NULL;
9ae3f9
+            pthread_mutex_lock(&ctx->fd_lock);
9ae3f9
+            {
9ae3f9
+                while (priv->rel_fdcount > 0) {
9ae3f9
+                    pthread_cond_wait(&priv->fd_cond, &ctx->fd_lock);
9ae3f9
+                }
9ae3f9
+            }
9ae3f9
+            pthread_mutex_unlock(&ctx->fd_lock);
9ae3f9
+
9ae3f9
+            gf_log(this->name, GF_LOG_INFO, "Sending CHILD_DOWN for brick %s",
9ae3f9
+                   victim->name);
9ae3f9
             default_notify(this->parents->xlator, GF_EVENT_CHILD_DOWN, data);
9ae3f9
         } break;
9ae3f9
         default:
9ae3f9
@@ -1038,7 +1047,13 @@ posix_init(xlator_t *this)
9ae3f9
     pthread_cond_init(&_private->fsync_cond, NULL);
9ae3f9
     pthread_mutex_init(&_private->janitor_mutex, NULL);
9ae3f9
     pthread_cond_init(&_private->janitor_cond, NULL);
9ae3f9
+    pthread_cond_init(&_private->fd_cond, NULL);
9ae3f9
     INIT_LIST_HEAD(&_private->fsyncs);
9ae3f9
+    _private->rel_fdcount = 0;
9ae3f9
+    ret = posix_spawn_ctx_janitor_thread(this);
9ae3f9
+    if (ret)
9ae3f9
+        goto out;
9ae3f9
+
9ae3f9
     ret = gf_thread_create(&_private->fsyncer, NULL, posix_fsyncer, this,
9ae3f9
                            "posixfsy");
9ae3f9
     if (ret) {
9ae3f9
@@ -1133,6 +1148,8 @@ posix_fini(xlator_t *this)
9ae3f9
 {
9ae3f9
     struct posix_private *priv = this->private;
9ae3f9
     gf_boolean_t health_check = _gf_false;
9ae3f9
+    glusterfs_ctx_t *ctx = this->ctx;
9ae3f9
+    uint32_t count;
9ae3f9
     int ret = 0;
9ae3f9
 
9ae3f9
     if (!priv)
9ae3f9
@@ -1166,6 +1183,19 @@ posix_fini(xlator_t *this)
9ae3f9
         priv->janitor = NULL;
9ae3f9
     }
9ae3f9
 
9ae3f9
+    pthread_mutex_lock(&ctx->fd_lock);
9ae3f9
+    {
9ae3f9
+        count = --ctx->pxl_count;
9ae3f9
+        if (count == 0) {
9ae3f9
+            pthread_cond_signal(&ctx->fd_cond);
9ae3f9
+        }
9ae3f9
+    }
9ae3f9
+    pthread_mutex_unlock(&ctx->fd_lock);
9ae3f9
+
9ae3f9
+    if (count == 0) {
9ae3f9
+        pthread_join(ctx->janitor, NULL);
9ae3f9
+    }
9ae3f9
+
9ae3f9
     if (priv->fsyncer) {
9ae3f9
         (void)gf_thread_cleanup_xint(priv->fsyncer);
9ae3f9
         priv->fsyncer = 0;
9ae3f9
diff --git a/xlators/storage/posix/src/posix-helpers.c b/xlators/storage/posix/src/posix-helpers.c
9ae3f9
index 39dbcce..73a44be 100644
9ae3f9
--- a/xlators/storage/posix/src/posix-helpers.c
9ae3f9
+++ b/xlators/storage/posix/src/posix-helpers.c
9ae3f9
@@ -1582,6 +1582,99 @@ unlock:
9ae3f9
     return;
9ae3f9
 }
9ae3f9
 
9ae3f9
+static struct posix_fd *
9ae3f9
+janitor_get_next_fd(glusterfs_ctx_t *ctx)
9ae3f9
+{
9ae3f9
+    struct posix_fd *pfd = NULL;
9ae3f9
+
9ae3f9
+    while (list_empty(&ctx->janitor_fds)) {
9ae3f9
+        if (ctx->pxl_count == 0) {
9ae3f9
+            return NULL;
9ae3f9
+        }
9ae3f9
+
9ae3f9
+        pthread_cond_wait(&ctx->fd_cond, &ctx->fd_lock);
9ae3f9
+    }
9ae3f9
+
9ae3f9
+    pfd = list_first_entry(&ctx->janitor_fds, struct posix_fd, list);
9ae3f9
+    list_del_init(&pfd->list);
9ae3f9
+
9ae3f9
+    return pfd;
9ae3f9
+}
9ae3f9
+
9ae3f9
+static void
9ae3f9
+posix_close_pfd(xlator_t *xl, struct posix_fd *pfd)
9ae3f9
+{
9ae3f9
+    THIS = xl;
9ae3f9
+
9ae3f9
+    if (pfd->dir == NULL) {
9ae3f9
+        gf_msg_trace(xl->name, 0, "janitor: closing file fd=%d", pfd->fd);
9ae3f9
+        sys_close(pfd->fd);
9ae3f9
+    } else {
9ae3f9
+        gf_msg_debug(xl->name, 0, "janitor: closing dir fd=%p", pfd->dir);
9ae3f9
+        sys_closedir(pfd->dir);
9ae3f9
+    }
9ae3f9
+
9ae3f9
+    GF_FREE(pfd);
9ae3f9
+}
9ae3f9
+
9ae3f9
+static void *
9ae3f9
+posix_ctx_janitor_thread_proc(void *data)
9ae3f9
+{
9ae3f9
+    xlator_t *xl;
9ae3f9
+    struct posix_fd *pfd;
9ae3f9
+    glusterfs_ctx_t *ctx = NULL;
9ae3f9
+    struct posix_private *priv_fd;
9ae3f9
+
9ae3f9
+    ctx = data;
9ae3f9
+
9ae3f9
+    pthread_mutex_lock(&ctx->fd_lock);
9ae3f9
+
9ae3f9
+    while ((pfd = janitor_get_next_fd(ctx)) != NULL) {
9ae3f9
+        pthread_mutex_unlock(&ctx->fd_lock);
9ae3f9
+
9ae3f9
+        xl = pfd->xl;
9ae3f9
+        posix_close_pfd(xl, pfd);
9ae3f9
+
9ae3f9
+        pthread_mutex_lock(&ctx->fd_lock);
9ae3f9
+
9ae3f9
+        priv_fd = xl->private;
9ae3f9
+        priv_fd->rel_fdcount--;
9ae3f9
+        if (!priv_fd->rel_fdcount)
9ae3f9
+            pthread_cond_signal(&priv_fd->fd_cond);
9ae3f9
+    }
9ae3f9
+
9ae3f9
+    pthread_mutex_unlock(&ctx->fd_lock);
9ae3f9
+
9ae3f9
+    return NULL;
9ae3f9
+}
9ae3f9
+
9ae3f9
+int
9ae3f9
+posix_spawn_ctx_janitor_thread(xlator_t *this)
9ae3f9
+{
9ae3f9
+    int ret = 0;
9ae3f9
+    glusterfs_ctx_t *ctx = NULL;
9ae3f9
+
9ae3f9
+    ctx = this->ctx;
9ae3f9
+
9ae3f9
+    pthread_mutex_lock(&ctx->fd_lock);
9ae3f9
+    {
9ae3f9
+        if (ctx->pxl_count++ == 0) {
9ae3f9
+            ret = gf_thread_create(&ctx->janitor, NULL,
9ae3f9
+                                   posix_ctx_janitor_thread_proc, ctx,
9ae3f9
+                                   "posixctxjan");
9ae3f9
+
9ae3f9
+            if (ret) {
9ae3f9
+                gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_THREAD_FAILED,
9ae3f9
+                       "spawning janitor thread failed");
9ae3f9
+                ctx->pxl_count--;
9ae3f9
+            }
9ae3f9
+        }
9ae3f9
+    }
9ae3f9
+    pthread_mutex_unlock(&ctx->fd_lock);
9ae3f9
+
9ae3f9
+    return ret;
9ae3f9
+}
9ae3f9
+
9ae3f9
 static int
9ae3f9
 is_fresh_file(int64_t ctime_sec)
9ae3f9
 {
9ae3f9
diff --git a/xlators/storage/posix/src/posix-inode-fd-ops.c b/xlators/storage/posix/src/posix-inode-fd-ops.c
9ae3f9
index 81f4a6b..21119ea 100644
9ae3f9
--- a/xlators/storage/posix/src/posix-inode-fd-ops.c
9ae3f9
+++ b/xlators/storage/posix/src/posix-inode-fd-ops.c
9ae3f9
@@ -1352,6 +1352,22 @@ out:
9ae3f9
     return 0;
9ae3f9
 }
9ae3f9
 
9ae3f9
+static void
9ae3f9
+posix_add_fd_to_cleanup(xlator_t *this, struct posix_fd *pfd)
9ae3f9
+{
9ae3f9
+    glusterfs_ctx_t *ctx = this->ctx;
9ae3f9
+    struct posix_private *priv = this->private;
9ae3f9
+
9ae3f9
+    pfd->xl = this;
9ae3f9
+    pthread_mutex_lock(&ctx->fd_lock);
9ae3f9
+    {
9ae3f9
+        list_add_tail(&pfd->list, &ctx->janitor_fds);
9ae3f9
+        priv->rel_fdcount++;
9ae3f9
+        pthread_cond_signal(&ctx->fd_cond);
9ae3f9
+    }
9ae3f9
+    pthread_mutex_unlock(&ctx->fd_lock);
9ae3f9
+}
9ae3f9
+
9ae3f9
 int32_t
9ae3f9
 posix_releasedir(xlator_t *this, fd_t *fd)
9ae3f9
 {
9ae3f9
@@ -1374,11 +1390,7 @@ posix_releasedir(xlator_t *this, fd_t *fd)
9ae3f9
                "pfd->dir is NULL for fd=%p", fd);
9ae3f9
         goto out;
9ae3f9
     }
9ae3f9
-
9ae3f9
-    gf_msg_debug(this->name, 0, "janitor: closing dir fd=%p", pfd->dir);
9ae3f9
-
9ae3f9
-    sys_closedir(pfd->dir);
9ae3f9
-    GF_FREE(pfd);
9ae3f9
+    posix_add_fd_to_cleanup(this, pfd);
9ae3f9
 
9ae3f9
 out:
9ae3f9
     return 0;
9ae3f9
@@ -2494,7 +2506,6 @@ out:
9ae3f9
 int32_t
9ae3f9
 posix_release(xlator_t *this, fd_t *fd)
9ae3f9
 {
9ae3f9
-    struct posix_private *priv = NULL;
9ae3f9
     struct posix_fd *pfd = NULL;
9ae3f9
     int ret = -1;
9ae3f9
     uint64_t tmp_pfd = 0;
9ae3f9
@@ -2502,8 +2513,6 @@ posix_release(xlator_t *this, fd_t *fd)
9ae3f9
     VALIDATE_OR_GOTO(this, out);
9ae3f9
     VALIDATE_OR_GOTO(fd, out);
9ae3f9
 
9ae3f9
-    priv = this->private;
9ae3f9
-
9ae3f9
     ret = fd_ctx_del(fd, this, &tmp_pfd);
9ae3f9
     if (ret < 0) {
9ae3f9
         gf_msg(this->name, GF_LOG_WARNING, 0, P_MSG_PFD_NULL,
9ae3f9
@@ -2517,13 +2526,7 @@ posix_release(xlator_t *this, fd_t *fd)
9ae3f9
                "pfd->dir is %p (not NULL) for file fd=%p", pfd->dir, fd);
9ae3f9
     }
9ae3f9
 
9ae3f9
-    gf_msg_debug(this->name, 0, "janitor: closing dir fd=%p", pfd->dir);
9ae3f9
-
9ae3f9
-    sys_close(pfd->fd);
9ae3f9
-    GF_FREE(pfd);
9ae3f9
-
9ae3f9
-    if (!priv)
9ae3f9
-        goto out;
9ae3f9
+    posix_add_fd_to_cleanup(this, pfd);
9ae3f9
 
9ae3f9
 out:
9ae3f9
     return 0;
9ae3f9
diff --git a/xlators/storage/posix/src/posix.h b/xlators/storage/posix/src/posix.h
9ae3f9
index 124dbb4..07f367b 100644
9ae3f9
--- a/xlators/storage/posix/src/posix.h
9ae3f9
+++ b/xlators/storage/posix/src/posix.h
9ae3f9
@@ -134,6 +134,8 @@ struct posix_fd {
9ae3f9
     off_t dir_eof; /* offset at dir EOF */
9ae3f9
     int odirect;
9ae3f9
     struct list_head list; /* to add to the janitor list */
9ae3f9
+    xlator_t *xl;
9ae3f9
+    char _pad[4]; /* manual padding */
9ae3f9
 };
9ae3f9
 
9ae3f9
 struct posix_private {
9ae3f9
@@ -204,6 +206,7 @@ struct posix_private {
9ae3f9
     pthread_cond_t fsync_cond;
9ae3f9
     pthread_mutex_t janitor_mutex;
9ae3f9
     pthread_cond_t janitor_cond;
9ae3f9
+    pthread_cond_t fd_cond;
9ae3f9
     int fsync_queue_count;
9ae3f9
 
9ae3f9
     enum {
9ae3f9
@@ -259,6 +262,7 @@ struct posix_private {
9ae3f9
     gf_boolean_t fips_mode_rchecksum;
9ae3f9
     gf_boolean_t ctime;
9ae3f9
     gf_boolean_t janitor_task_stop;
9ae3f9
+    uint32_t rel_fdcount;
9ae3f9
 };
9ae3f9
 
9ae3f9
 typedef struct {
9ae3f9
@@ -665,6 +669,9 @@ posix_cs_maintenance(xlator_t *this, fd_t *fd, loc_t *loc, int *pfd,
9ae3f9
 int
9ae3f9
 posix_check_dev_file(xlator_t *this, inode_t *inode, char *fop, int *op_errno);
9ae3f9
 
9ae3f9
+int
9ae3f9
+posix_spawn_ctx_janitor_thread(xlator_t *this);
9ae3f9
+
9ae3f9
 void
9ae3f9
 posix_update_iatt_buf(struct iatt *buf, int fd, char *loc, dict_t *xdata);
9ae3f9
 
9ae3f9
-- 
9ae3f9
1.8.3.1
9ae3f9