From a0b148ea4e2a0163548eeb89b7580be4adbb8070 Mon Sep 17 00:00:00 2001 From: Anand Avati Date: Sat, 23 Jan 2010 05:14:31 +0000 Subject: Server backend storage hang should not cause the mount point to hang. Submitted-by: Krishna Srinivas NOTE: fixed compilation issues in posix.c introduced while merging storage/posix polls for FS/kernel being functional by issuing statvfs() call. In case statvfs expires the timer, storage/posix will send CHILD_DOWN to upper translator. Ultimately this will cause protocol/server to disconnect all clients connected and also cleans up the data structures. Hence if soft lockup or other kernel bug causes backend FS to hang, the clients will not be hung. Signed-off-by: Krishna Srinivas Signed-off-by: Anand V. Avati Signed-off-by: Anand V. Avati BUG: 272 (Server backend storage hang should not cause the mount point to hang) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=272 --- xlators/protocol/server/src/server-helpers.c | 112 +++++++++++++++++++++++++- xlators/protocol/server/src/server-helpers.h | 6 ++ xlators/protocol/server/src/server-protocol.c | 39 ++++++++- xlators/protocol/server/src/server-protocol.h | 7 +- 4 files changed, 158 insertions(+), 6 deletions(-) (limited to 'xlators/protocol') diff --git a/xlators/protocol/server/src/server-helpers.c b/xlators/protocol/server/src/server-helpers.c index 88dada1516e..0e22f0ba5fa 100644 --- a/xlators/protocol/server/src/server-helpers.c +++ b/xlators/protocol/server/src/server-helpers.c @@ -645,13 +645,14 @@ out: int -server_connection_cleanup (xlator_t *this, server_connection_t *conn) +server_connection_cleanup (xlator_t *this, server_connection_t *conn, transport_t *trans) { char do_cleanup = 0; struct _lock_table *ltable = NULL; fdentry_t *fdentries = NULL; uint32_t fd_count = 0; int ret = 0; + int i = 0; if (conn == NULL) { goto out; @@ -659,6 +660,12 @@ server_connection_cleanup (xlator_t *this, server_connection_t *conn) pthread_mutex_lock (&conn->lock); { + for (i = 0; i < TRANSPORTS_PER_SERVER_CONN; i++) { + if (conn->transports[i] == trans) { + conn->transports[i] = NULL; + transport_unref (trans); + } + } conn->active_transports--; if (conn->active_transports == 0) { if (conn->ltable) { @@ -850,11 +857,12 @@ out: server_connection_t * -server_connection_get (xlator_t *this, const char *id) +server_connection_get (xlator_t *this, const char *id, transport_t *trans) { server_connection_t *conn = NULL; server_connection_t *trav = NULL; server_conf_t *conf = NULL; + int i = 0; conf = this->private; @@ -878,10 +886,30 @@ server_connection_get (xlator_t *this, const char *id) list_add (&conn->list, &conf->conns); } + if (conn->active_transports == TRANSPORTS_PER_SERVER_CONN) { + gf_log (this->name, GF_LOG_DEBUG, + "Maximum number of connections allowed is %d", + TRANSPORTS_PER_SERVER_CONN); + goto unlock; + } + + for (i = 0; i < TRANSPORTS_PER_SERVER_CONN; i++) { + if (!conn->transports[i]) + break; + } + + if (i == TRANSPORTS_PER_SERVER_CONN) { + gf_log (this->name, GF_LOG_DEBUG, + "Could not find a vacant slot"); + goto unlock; + } + + conn->transports[i] = transport_ref (trans); conn->ref++; conn->active_transports++; } +unlock: pthread_mutex_unlock (&conf->mutex); return conn; @@ -918,3 +946,83 @@ server_connection_put (xlator_t *this, server_connection_t *conn) out: return; } + +void +server_child_down (xlator_t *this, xlator_t *bound_xl) +{ + server_conf_t *conf = NULL; + server_connection_t *trav = NULL; + transport_t *trans = NULL; + int subvol_idx = 0; + int i = 0; + xlator_list_t *xltrav = NULL; + + conf = this->private; + + if (conf == NULL) + return; + + xltrav = this->children; + + while (xltrav) { + if (xltrav->xlator == bound_xl) + break; + xltrav = xltrav->next; + subvol_idx++; + } + gf_log (this->name, GF_LOG_DEBUG, + "subvolume %s(%d) went down", bound_xl->name, subvol_idx); + + conf->subvol_list[subvol_idx] = 0; + + pthread_mutex_lock (&conf->mutex); + { + if (!list_empty(&conf->conns)) { + list_for_each_entry (trav, &conf->conns, list) { + if (bound_xl == trav->bound_xl) { + gf_log (this->name, GF_LOG_DEBUG, + "disonnecting conn=%p", trav); + for (i = 0; i < TRANSPORTS_PER_SERVER_CONN; i++) + { + trans = trav->transports[i]; + if (trans == NULL) + continue; + gf_log (this->name, GF_LOG_DEBUG, + "disconnecting %p(%d)", + trans, i); + transport_disconnect (trans); + } + } + } + } + } + pthread_mutex_unlock (&conf->mutex); +} + +void +server_child_up (xlator_t *this, xlator_t *bound_xl) +{ + server_conf_t *conf = NULL; + int subvol_idx = 0; + xlator_list_t *xltrav = NULL; + + conf = this->private; + + if (conf == NULL) + return; + + xltrav = this->children; + + while (xltrav) { + if (bound_xl == xltrav->xlator) { + break; + } + subvol_idx++; + xltrav = xltrav->next; + } + + gf_log (this->name, GF_LOG_DEBUG, + "subvolume %s(%d) came up", bound_xl->name, subvol_idx); + + conf->subvol_list[subvol_idx] = 1; +} diff --git a/xlators/protocol/server/src/server-helpers.h b/xlators/protocol/server/src/server-helpers.h index 867035d3334..5c584b00aa7 100644 --- a/xlators/protocol/server/src/server-helpers.h +++ b/xlators/protocol/server/src/server-helpers.h @@ -69,4 +69,10 @@ gf_direntry_to_bin (dir_entry_t *head, char *bufferp); void server_print_request (call_frame_t *frame); +void +server_child_up (xlator_t *this, xlator_t *bound_xl); + +void +server_child_down (xlator_t *this, xlator_t *bound_xl); + #endif /* __SERVER_HELPERS_H__ */ diff --git a/xlators/protocol/server/src/server-protocol.c b/xlators/protocol/server/src/server-protocol.c index 0528699acbe..a7f6294f387 100644 --- a/xlators/protocol/server/src/server-protocol.c +++ b/xlators/protocol/server/src/server-protocol.c @@ -5654,6 +5654,8 @@ mop_setvolume (call_frame_t *frame, xlator_t *bound_xl, char *volfile_key = NULL; uint32_t checksum = 0; int32_t lru_limit = 1024; + xlator_list_t *xltrav = NULL; + int subvol_idx = 0; params = dict_new (); reply = dict_new (); @@ -5695,7 +5697,7 @@ mop_setvolume (call_frame_t *frame, xlator_t *bound_xl, } - conn = server_connection_get (frame->this, process_uuid); + conn = server_connection_get (frame->this, process_uuid, trans); if (trans->xl_private != conn) trans->xl_private = conn; @@ -5862,6 +5864,22 @@ mop_setvolume (call_frame_t *frame, xlator_t *bound_xl, ret = dict_set_uint64 (reply, "transport-ptr", ((uint64_t) (long) trans)); + xltrav = frame->this->children; + while (xltrav) { + if (xltrav->xlator == xl) + break; + xltrav = xltrav->next; + subvol_idx++; + } + + if (conf->subvol_list[subvol_idx] == 0) { + gf_log (xl->name, GF_LOG_DEBUG, + "subvolume %d down (filesystem not accesible), failed to setvolume", subvol_idx); + op_ret = -1; + op_errno = ENOTCONN; + goto fail; + } + fail: dict_len = dict_serialized_length (reply); if (dict_len < 0) { @@ -6550,6 +6568,8 @@ init (xlator_t *this) server_conf_t *conf = NULL; data_t *data = NULL; data_t *trace = NULL; + int i = 0; + xlator_list_t *xltrav = NULL; if (this->children == NULL) { gf_log (this->name, GF_LOG_ERROR, @@ -6635,6 +6655,15 @@ init (xlator_t *this) } } + xltrav = this->children; + + while (xltrav) { + i++; + xltrav = xltrav->next; + } + + conf->subvol_list = calloc (i, sizeof (char)); + #ifndef GF_DARWIN_HOST_OS { struct rlimit lim; @@ -6736,6 +6765,12 @@ notify (xlator_t *this, int32_t event, void *data, ...) } switch (event) { + case GF_EVENT_CHILD_DOWN: + server_child_down (this, data); + break; + case GF_EVENT_CHILD_UP: + server_child_up (this, data); + break; case GF_EVENT_POLLIN: ret = protocol_server_pollin (this, trans); break; @@ -6756,7 +6791,7 @@ notify (xlator_t *this, int32_t event, void *data, ...) * FIXME: shouldn't we check for return value? * what should be done if cleanup fails? */ - server_connection_cleanup (this, trans->xl_private); + server_connection_cleanup (this, trans->xl_private, trans); } } break; diff --git a/xlators/protocol/server/src/server-protocol.h b/xlators/protocol/server/src/server-protocol.h index 78bc138279a..73e7f78911b 100644 --- a/xlators/protocol/server/src/server-protocol.h +++ b/xlators/protocol/server/src/server-protocol.h @@ -37,6 +37,7 @@ #define DEFAULT_BLOCK_SIZE 4194304 /* 4MB */ #define DEFAULT_VOLUME_FILE_PATH CONFDIR "/glusterfs.vol" +#define TRANSPORTS_PER_SERVER_CONN 2 typedef struct _server_state server_state_t; @@ -64,6 +65,7 @@ struct _server_connection { char *id; int ref; int active_transports; + transport_t *transports[TRANSPORTS_PER_SERVER_CONN]; pthread_mutex_t lock; char disconnected; fdtable_t *fdtable; @@ -75,7 +77,7 @@ typedef struct _server_connection server_connection_t; server_connection_t * -server_connection_get (xlator_t *this, const char *id); +server_connection_get (xlator_t *this, const char *id, transport_t *trans); void server_connection_put (xlator_t *this, server_connection_t *conn); @@ -84,7 +86,7 @@ int server_connection_destroy (xlator_t *this, server_connection_t *conn); int -server_connection_cleanup (xlator_t *this, server_connection_t *conn); +server_connection_cleanup (xlator_t *this, server_connection_t *conn, transport_t *trans); int server_nop_cbk (call_frame_t *frame, void *cookie, @@ -107,6 +109,7 @@ typedef struct { pthread_mutex_t mutex; struct list_head conns; gf_boolean_t verify_volfile_checksum; + char *subvol_list; gf_boolean_t trace; } server_conf_t; -- cgit