diff options
-rw-r--r-- | glusterfsd/src/glusterfsd.c | 2 | ||||
-rw-r--r-- | libglusterfs/src/glusterfs.h | 4 | ||||
-rw-r--r-- | xlators/protocol/client/src/client-handshake.c | 15 | ||||
-rw-r--r-- | xlators/protocol/client/src/client.c | 78 | ||||
-rw-r--r-- | xlators/protocol/client/src/client.h | 2 |
5 files changed, 77 insertions, 24 deletions
diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c index a46385aa292..c410ffd40d9 100644 --- a/glusterfsd/src/glusterfsd.c +++ b/glusterfsd/src/glusterfsd.c @@ -1394,6 +1394,8 @@ glusterfs_ctx_defaults_init (glusterfs_ctx_t *ctx) goto out; pthread_mutex_init (&(ctx->lock), NULL); + pthread_mutex_init (&ctx->notify_lock, NULL); + pthread_cond_init (&ctx->notify_cond, NULL); ctx->clienttable = gf_clienttable_alloc(); if (!ctx->clienttable) diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h index 9c078e1d5f9..8f993b2086a 100644 --- a/libglusterfs/src/glusterfs.h +++ b/libglusterfs/src/glusterfs.h @@ -533,6 +533,10 @@ struct _glusterfs_ctx { /* Buffer to 'save' backtrace even under OOM-kill like situations*/ char btbuf[GF_BACKTRACE_LEN]; + pthread_mutex_t notify_lock; + pthread_cond_t notify_cond; + int notifying; + }; typedef struct _glusterfs_ctx glusterfs_ctx_t; diff --git a/xlators/protocol/client/src/client-handshake.c b/xlators/protocol/client/src/client-handshake.c index 42b7ac0745e..531b38eaf83 100644 --- a/xlators/protocol/client/src/client-handshake.c +++ b/xlators/protocol/client/src/client-handshake.c @@ -131,12 +131,11 @@ client_notify_parents_child_up (xlator_t *this) int ret = 0; conf = this->private; - ret = default_notify (this, GF_EVENT_CHILD_UP, NULL); + ret = client_notify_dispatch (this, GF_EVENT_CHILD_UP, NULL); if (ret) gf_log (this->name, GF_LOG_INFO, "notify of CHILD_UP failed"); - conf->last_sent_event = GF_EVENT_CHILD_UP; return 0; } @@ -1146,11 +1145,12 @@ client_setvolume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *m op_ret = 0; } if (op_errno == ESTALE) { - ret = default_notify (this, GF_EVENT_VOLFILE_MODIFIED, NULL); + ret = client_notify_dispatch (this, + GF_EVENT_VOLFILE_MODIFIED, + NULL); if (ret) gf_log (this->name, GF_LOG_INFO, "notify of VOLFILE_MODIFIED failed"); - conf->last_sent_event = GF_EVENT_VOLFILE_MODIFIED; } goto out; } @@ -1223,13 +1223,12 @@ client_setvolume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *m out: if (auth_fail) { gf_log (this->name, GF_LOG_INFO, "sending AUTH_FAILED event"); - ret = default_notify (this, GF_EVENT_AUTH_FAILED, NULL); + ret = client_notify_dispatch (this, GF_EVENT_AUTH_FAILED, NULL); if (ret) gf_log (this->name, GF_LOG_INFO, "notify of AUTH_FAILED failed"); conf->connecting = 0; conf->connected = 0; - conf->last_sent_event = GF_EVENT_AUTH_FAILED; ret = -1; } if (-1 == op_ret) { @@ -1238,11 +1237,11 @@ out: * tell the parents that i am all ok.. */ gf_log (this->name, GF_LOG_INFO, "sending CHILD_CONNECTING event"); - ret = default_notify (this, GF_EVENT_CHILD_CONNECTING, NULL); + ret = client_notify_dispatch (this, GF_EVENT_CHILD_CONNECTING, + NULL); if (ret) gf_log (this->name, GF_LOG_INFO, "notify of CHILD_CONNECTING failed"); - conf->last_sent_event = GF_EVENT_CHILD_CONNECTING; conf->connecting= 1; ret = 0; } diff --git a/xlators/protocol/client/src/client.c b/xlators/protocol/client/src/client.c index 999a4a5c836..00d88d6e7a1 100644 --- a/xlators/protocol/client/src/client.c +++ b/xlators/protocol/client/src/client.c @@ -34,6 +34,55 @@ int client_init_rpc (xlator_t *this); int client_destroy_rpc (xlator_t *this); int client_mark_fd_bad (xlator_t *this); +static int +client_notify_dispatch_uniq (xlator_t *this, int32_t event, void *data, ...) +{ + clnt_conf_t *conf = this->private; + + if (conf->last_sent_event == event) + return 0; + + return client_notify_dispatch (this, event, data); +} + +int +client_notify_dispatch (xlator_t *this, int32_t event, void *data, ...) +{ + int ret = -1; + glusterfs_ctx_t *ctx = this->ctx; + clnt_conf_t *conf = this->private; + + pthread_mutex_lock (&ctx->notify_lock); + { + while (ctx->notifying) + pthread_cond_wait (&ctx->notify_cond, + &ctx->notify_lock); + ctx->notifying = 1; + } + pthread_mutex_unlock (&ctx->notify_lock); + + /* We assume that all translators in the graph handle notification + * events in sequence. + * */ + ret = default_notify (this, event, data); + + /* NB (Even) with MT-epoll and EPOLLET|EPOLLONESHOT we are guaranteed + * that there would be atmost one poller thread executing this + * notification function. This allows us to update last_sent_event + * without explicit synchronization. See epoll(7). + */ + conf->last_sent_event = event; + + pthread_mutex_lock (&ctx->notify_lock); + { + ctx->notifying = 0; + pthread_cond_signal (&ctx->notify_cond); + } + pthread_mutex_unlock (&ctx->notify_lock); + + return ret; +} + int32_t client_type_to_gf_type (short l_type) { @@ -2169,14 +2218,12 @@ client_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, "handshake msg returned %d", ret); } else { //conf->rpc->connected = 1; - if (conf->last_sent_event != GF_EVENT_CHILD_UP) { - ret = default_notify (this, GF_EVENT_CHILD_UP, - NULL); - if (ret) - gf_log (this->name, GF_LOG_INFO, - "CHILD_UP notify failed"); - conf->last_sent_event = GF_EVENT_CHILD_UP; - } + ret = client_notify_dispatch_uniq (this, + GF_EVENT_CHILD_UP, + NULL); + if (ret) + gf_log (this->name, GF_LOG_INFO, + "CHILD_UP notify failed"); } /* Cancel grace timer if set */ @@ -2224,14 +2271,13 @@ client_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, may get screwed up.. (eg. CHILD_MODIFIED event in replicate), hence make sure events which are passed to parent are genuine */ - if (conf->last_sent_event != GF_EVENT_CHILD_DOWN) { - ret = default_notify (this, GF_EVENT_CHILD_DOWN, - NULL); - if (ret) - gf_log (this->name, GF_LOG_INFO, - "CHILD_DOWN notify failed"); - conf->last_sent_event = GF_EVENT_CHILD_DOWN; - } + ret = client_notify_dispatch_uniq (this, + GF_EVENT_CHILD_DOWN, + NULL); + if (ret) + gf_log (this->name, GF_LOG_INFO, + "CHILD_DOWN notify failed"); + } else { if (conf->connected) gf_log (this->name, GF_LOG_DEBUG, diff --git a/xlators/protocol/client/src/client.h b/xlators/protocol/client/src/client.h index af70926b178..1aea1353727 100644 --- a/xlators/protocol/client/src/client.h +++ b/xlators/protocol/client/src/client.h @@ -262,4 +262,6 @@ int client_fd_fop_prepare_local (call_frame_t *frame, fd_t *fd, int64_t remote_fd); gf_boolean_t __is_fd_reopen_in_progress (clnt_fd_ctx_t *fdctx); +int +client_notify_dispatch (xlator_t *this, int32_t event, void *data, ...); #endif /* !_CLIENT_H */ |