diff options
Diffstat (limited to 'xlators/protocol/server/src')
-rw-r--r-- | xlators/protocol/server/src/server-handshake.c | 78 | ||||
-rw-r--r-- | xlators/protocol/server/src/server-helpers.c | 48 | ||||
-rw-r--r-- | xlators/protocol/server/src/server-helpers.h | 6 | ||||
-rw-r--r-- | xlators/protocol/server/src/server-mem-types.h | 1 | ||||
-rw-r--r-- | xlators/protocol/server/src/server.c | 96 | ||||
-rw-r--r-- | xlators/protocol/server/src/server.h | 5 |
6 files changed, 213 insertions, 21 deletions
diff --git a/xlators/protocol/server/src/server-handshake.c b/xlators/protocol/server/src/server-handshake.c index 2c8cf059be3..374f5a49ae7 100644 --- a/xlators/protocol/server/src/server-handshake.c +++ b/xlators/protocol/server/src/server-handshake.c @@ -354,6 +354,7 @@ server_setvolume (rpcsvc_request_t *req) int32_t op_errno = EINVAL; int32_t fop_version = 0; int32_t mgmt_version = 0; + uint32_t lk_version = 0; char *buf = NULL; params = dict_new (); @@ -408,8 +409,33 @@ server_setvolume (rpcsvc_request_t *req) goto fail; } + /*lk_verion :: [1..2^31-1]*/ + ret = dict_get_uint32 (params, "clnt-lk-version", &lk_version); + if (ret < 0) { + ret = dict_set_str (reply, "ERROR", + "lock state verison not supplied"); + if (ret < 0) + gf_log (this->name, GF_LOG_DEBUG, + "failed to set error msg"); + + op_ret = -1; + op_errno = EINVAL; + goto fail; + } conn = server_connection_get (this, process_uuid); + if (!conn) { + op_ret = -1; + op_errno = ENOMEM; + goto fail; + } + + server_cancel_conn_timer (this, conn); + if (conn->lk_version != 0 && + conn->lk_version != lk_version) { + (void) server_connection_cleanup (this, conn); + } + if (req->trans->xl_private != conn) req->trans->xl_private = conn; @@ -595,6 +621,12 @@ server_setvolume (rpcsvc_request_t *req) gf_log (this->name, GF_LOG_DEBUG, "failed to set 'process-uuid'"); + ret = dict_set_uint32 (reply, "clnt-lk-version", + conn->lk_version); + if (ret) + gf_log (this->name, GF_LOG_WARNING, + "failed to set 'clnt-lk-version'"); + ret = dict_set_uint64 (reply, "transport-ptr", ((uint64_t) (long) req->trans)); if (ret) @@ -663,12 +695,50 @@ server_ping (rpcsvc_request_t *req) return 0; } +int +server_set_lk_version (rpcsvc_request_t *req) +{ + int op_ret = -1; + int op_errno = EINVAL; + gf_set_lk_ver_req args = {0, }; + gf_set_lk_ver_rsp rsp = {0,}; + server_connection_t *conn = NULL; + xlator_t *this = NULL; + + this = req->svc->mydata; + //TODO: Decide on an appropriate errno for the error-path + //below + if (!this) + goto fail; + + if (!xdr_to_generic (req->msg[0], &args, + (xdrproc_t)xdr_gf_set_lk_ver_req)) { + //failed to decode msg; + req->rpc_err = GARBAGE_ARGS; + goto fail; + } + + conn = server_connection_get (this, args.uid); + conn->lk_version = args.lk_ver; + server_connection_put (this, conn); + + rsp.lk_ver = args.lk_ver; + + op_ret = 0; +fail: + rsp.op_ret = op_ret; + rsp.op_errno = op_errno; + server_submit_reply (NULL, req, &rsp, NULL, 0, NULL, + (xdrproc_t)xdr_gf_set_lk_ver_rsp); + return 0; +} rpcsvc_actor_t gluster_handshake_actors[] = { - [GF_HNDSK_NULL] = {"NULL", GF_HNDSK_NULL, server_null, NULL, NULL, 0}, - [GF_HNDSK_SETVOLUME] = {"SETVOLUME", GF_HNDSK_SETVOLUME, server_setvolume, NULL, NULL, 0}, - [GF_HNDSK_GETSPEC] = {"GETSPEC", GF_HNDSK_GETSPEC, server_getspec, NULL, NULL, 0}, - [GF_HNDSK_PING] = {"PING", GF_HNDSK_PING, server_ping, NULL, NULL, 0}, + [GF_HNDSK_NULL] = {"NULL", GF_HNDSK_NULL, server_null, NULL, NULL, 0}, + [GF_HNDSK_SETVOLUME] = {"SETVOLUME", GF_HNDSK_SETVOLUME, server_setvolume, NULL, NULL, 0}, + [GF_HNDSK_GETSPEC] = {"GETSPEC", GF_HNDSK_GETSPEC, server_getspec, NULL, NULL, 0}, + [GF_HNDSK_PING] = {"PING", GF_HNDSK_PING, server_ping, NULL, NULL, 0}, + [GF_HNDSK_SET_LK_VER] = {"SET_LK_VER", GF_HNDSK_SET_LK_VER, server_set_lk_version, NULL, NULL }, }; diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c index 4980424d350..9de1082dc94 100644 --- a/xlators/protocol/server/src/server-helpers.c +++ b/xlators/protocol/server/src/server-helpers.c @@ -774,6 +774,7 @@ server_connection_t * server_connection_get (xlator_t *this, const char *id) { server_connection_t *conn = NULL; + server_connection_t *trav = NULL; server_conf_t *conf = NULL; GF_VALIDATE_OR_GOTO ("server", this, out); @@ -783,20 +784,29 @@ server_connection_get (xlator_t *this, const char *id) pthread_mutex_lock (&conf->mutex); { + list_for_each_entry (trav, &conf->conns, list) { + if (!strncmp (trav->id, id, strlen (id))) { + conn = trav; + conn->ref++; + goto unlock; + } + } + conn = (void *) GF_CALLOC (1, sizeof (*conn), gf_server_mt_conn_t); if (!conn) goto unlock; conn->id = gf_strdup (id); + /*'0' denotes uninitialised lock state*/ + conn->lk_version = 0; + conn->ref++; conn->fdtable = gf_fd_fdtable_alloc (); conn->ltable = gf_lock_table_new (); conn->this = this; pthread_mutex_init (&conn->lock, NULL); - list_add (&conn->list, &conf->conns); - conn->ref++; } unlock: pthread_mutex_unlock (&conf->mutex); @@ -982,6 +992,17 @@ out: return ret; } +void +put_server_conn_state (xlator_t *this, rpc_transport_t *xprt) +{ + GF_VALIDATE_OR_GOTO ("server", this, out); + GF_VALIDATE_OR_GOTO ("server", xprt, out); + + xprt->xl_private = NULL; +out: + return; +} + server_connection_t * get_server_conn_state (xlator_t *this, rpc_transport_t *xprt) { @@ -1497,3 +1518,26 @@ gf_server_check_setxattr_cmd (call_frame_t *frame, dict_t *dict) return 0; } + +void +server_cancel_conn_timer (xlator_t *this, server_connection_t *conn) +{ + if (!this || !conn) { + gf_log (THIS->name, GF_LOG_ERROR, "Invalid arguments to " + "cancel connection timer"); + return; + } + + pthread_mutex_lock (&conn->lock); + { + if (!conn->timer) + goto unlock; + + gf_timer_call_cancel (this->ctx, conn->timer); + conn->timer = NULL; + } +unlock: + pthread_mutex_unlock (&conn->lock); + + return; +} diff --git a/xlators/protocol/server/src/server-helpers.h b/xlators/protocol/server/src/server-helpers.h index 844c98c27bf..99ba7e546b4 100644 --- a/xlators/protocol/server/src/server-helpers.h +++ b/xlators/protocol/server/src/server-helpers.h @@ -68,6 +68,12 @@ server_print_request (call_frame_t *frame); call_frame_t * get_frame_from_request (rpcsvc_request_t *req); +void +server_cancel_conn_timer (xlator_t *this, server_connection_t *conn); + +void +put_server_conn_state (xlator_t *this, rpc_transport_t *xprt); + server_connection_t * get_server_conn_state (xlator_t *this, rpc_transport_t *xptr); diff --git a/xlators/protocol/server/src/server-mem-types.h b/xlators/protocol/server/src/server-mem-types.h index 88bae8cb45d..5438ed6db1a 100644 --- a/xlators/protocol/server/src/server-mem-types.h +++ b/xlators/protocol/server/src/server-mem-types.h @@ -33,6 +33,7 @@ enum gf_server_mem_types_ { gf_server_mt_dirent_rsp_t, gf_server_mt_rsp_buf_t, gf_server_mt_volfile_ctx_t, + gf_server_mt_timer_data_t, gf_server_mt_end, }; #endif /* __SERVER_MEM_TYPES_H__ */ diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c index b0697bb7b9d..b45b77baae0 100644 --- a/xlators/protocol/server/src/server.c +++ b/xlators/protocol/server/src/server.c @@ -36,6 +36,26 @@ #include "authenticate.h" #include "rpcsvc.h" +void +grace_time_handler (void *data) +{ + server_connection_t *conn = NULL; + xlator_t *this = NULL; + + conn = data; + this = conn->this; + + GF_VALIDATE_OR_GOTO (THIS->name, conn, out); + GF_VALIDATE_OR_GOTO (THIS->name, this, out); + + gf_log (this->name, GF_LOG_INFO, "grace timer expired"); + + server_cancel_conn_timer (this, conn); + server_connection_put (this, conn); +out: + return; +} + struct iobuf * gfs_serialize_reply (rpcsvc_request_t *req, void *arg, struct iovec *outmsg, xdrproc_t xdrproc) @@ -554,11 +574,10 @@ int server_rpc_notify (rpcsvc_t *rpc, void *xl, rpcsvc_event_t event, void *data) { - xlator_t *this = NULL; - rpc_transport_t *xprt = NULL; - server_connection_t *conn = NULL; - server_conf_t *conf = NULL; - + xlator_t *this = NULL; + rpc_transport_t *xprt = NULL; + server_connection_t *conn = NULL; + server_conf_t *conf = NULL; if (!xl || !data) { gf_log_callingfn ("server", GF_LOG_WARNING, @@ -589,20 +608,37 @@ server_rpc_notify (rpcsvc_t *rpc, void *xl, rpcsvc_event_t event, } case RPCSVC_EVENT_DISCONNECT: conn = get_server_conn_state (this, xprt); - if (conn) - server_connection_cleanup (this, conn); - - gf_log (this->name, GF_LOG_INFO, - "disconnected connection from %s", - xprt->peerinfo.identifier); + if (!conn) + break; + put_server_conn_state (this, xprt); + gf_log (this->name, GF_LOG_INFO, "disconnecting connection" + "from %s", xprt->peerinfo.identifier); list_del (&xprt->list); + pthread_mutex_lock (&conn->lock); + { + if (conn->timer) + goto unlock; + + gf_log (this->name, GF_LOG_INFO, "starting a grace " + "timer for %s", xprt->name); + + conn->timer = gf_timer_call_after (this->ctx, + conf->grace_tv, + grace_time_handler, + conn); + } + unlock: + pthread_mutex_unlock (&conn->lock); + break; case RPCSVC_EVENT_TRANSPORT_DESTROY: - conn = get_server_conn_state (this, xprt); - if (conn) - server_connection_put (this, conn); + /*- conn obj has been disassociated from xprt on first + * disconnect. + * conn cleanup and destruction is handed over to + * grace_time_handler or the subsequent handler that 'owns' + * the conn. Nothing left to be done here. */ break; default: break; @@ -668,6 +704,30 @@ _copy_auth_opt (dict_t *unused, int +server_init_grace_timer (xlator_t *this, dict_t *options, + server_conf_t *conf) +{ + int32_t ret = -1; + int32_t grace_timeout = -1; + + GF_VALIDATE_OR_GOTO ("server", this, out); + GF_VALIDATE_OR_GOTO (this->name, options, out); + GF_VALIDATE_OR_GOTO (this->name, conf, out); + + ret = dict_get_int32 (options, "grace-timeout", &grace_timeout); + if (!ret) + conf->grace_tv.tv_sec = grace_timeout; + else + conf->grace_tv.tv_sec = 10; + + conf->grace_tv.tv_usec = 0; + + ret = 0; +out: + return ret; +} + +int reconfigure (xlator_t *this, dict_t *options) { @@ -761,6 +821,7 @@ reconfigure (xlator_t *this, dict_t *options) "Reconfigure not found for transport" ); } } + ret = server_init_grace_timer (this, options, conf); out: gf_log ("", GF_LOG_DEBUG, "returning %d", ret); @@ -797,6 +858,10 @@ init (xlator_t *this) INIT_LIST_HEAD (&conf->xprt_list); pthread_mutex_init (&conf->mutex, NULL); + ret = server_init_grace_timer (this, this->options, conf); + if (ret) + goto out; + ret = server_build_config (this, conf); if (ret) goto out; @@ -1032,5 +1097,8 @@ struct volume_options options[] = { .type = GF_OPTION_TYPE_PATH, .default_value = "/tmp" }, + {.key = {"grace-timeout"}, + .type = GF_OPTION_TYPE_INT, + }, { .key = {NULL} }, }; diff --git a/xlators/protocol/server/src/server.h b/xlators/protocol/server/src/server.h index 92785c5a9d6..091a02ccba2 100644 --- a/xlators/protocol/server/src/server.h +++ b/xlators/protocol/server/src/server.h @@ -28,6 +28,7 @@ #include "protocol-common.h" #include "server-mem-types.h" #include "glusterfs3.h" +#include "timer.h" #define DEFAULT_BLOCK_SIZE 4194304 /* 4MB */ #define DEFAULT_VOLUME_FILE_PATH CONFDIR "/glusterfs.vol" @@ -60,8 +61,10 @@ struct _server_connection { pthread_mutex_t lock; fdtable_t *fdtable; struct _lock_table *ltable; + gf_timer_t *timer; xlator_t *bound_xl; xlator_t *this; + uint32_t lk_version; }; typedef struct _server_connection server_connection_t; @@ -92,7 +95,7 @@ struct server_conf { gf_boolean_t trace; char *conf_dir; struct _volfile_ctx *volfile; - + struct timeval grace_tv; dict_t *auth_modules; pthread_mutex_t mutex; struct list_head conns; |