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/storage/posix/src/posix.c | 141 ++++++++++++++++++++++++++++++++++++-- xlators/storage/posix/src/posix.h | 11 +++ 2 files changed, 147 insertions(+), 5 deletions(-) (limited to 'xlators/storage/posix') diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index 1ff9a06f9fe..c9342ac4d69 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -4703,6 +4703,119 @@ posix_inode (xlator_t *this) return 0; } +void +posix_fsping_timer_expired (void *data) +{ + xlator_t *this = NULL; + struct posix_private *priv = NULL; + + this = data; + priv = this->private; + + pthread_mutex_lock (&priv->mutex); + { + if (priv->fsping_timer) { + gf_timer_call_cancel (this->ctx, + priv->fsping_timer); + priv->fsping_timer = NULL; + } + + if (priv->fs_state) { + priv->fs_state = 0; + default_notify (this, GF_EVENT_CHILD_DOWN, NULL); + } + } + pthread_mutex_unlock (&priv->mutex); +} + +void +posix_fsping (void *arg); + +void * +posix_fsping_statvfs (void *arg) +{ + int ret = -1; + xlator_t *this = NULL; + char *root_path = NULL; + struct statvfs buf = {0, }; + struct posix_private *priv = NULL; + struct timeval delta = {0, }; + + this = arg; + priv = this->private; + root_path = POSIX_BASE_PATH (this); + + ret = statvfs (root_path, &buf); + + pthread_mutex_lock (&priv->mutex); + { + if (priv->fsping_timer) { + gf_timer_call_cancel (this->ctx, + priv->fsping_timer); + priv->fsping_timer = NULL; + } + if (ret == 0) { + if (priv->fs_state == 0) { + priv->fs_state = 1; + default_notify (this, GF_EVENT_CHILD_UP, + NULL); + } + } else { + if (priv->fs_state) { + priv->fs_state = 0; + default_notify (this, GF_EVENT_CHILD_DOWN, + NULL); + } + } + } + pthread_mutex_unlock (&priv->mutex); + + delta.tv_sec = POSIX_FSPING_SLEEP_TIME; + priv->fsping_timer = + gf_timer_call_after (this->ctx, + delta, + posix_fsping, + (void *) this); + if (priv->fsping_timer == NULL) { + gf_log (this->name, GF_LOG_ERROR, + "unable to register timer"); + } + return NULL; +} + +void +posix_fsping (void *arg) +{ + xlator_t *this = NULL; + struct posix_private *priv = NULL; + struct timeval delta = {0, }; + + this = arg; + priv = this->private; + + delta.tv_sec = priv->fsping_timeout; + delta.tv_usec = 0; + + if (priv->fsping_timer) { + gf_timer_call_cancel (this->ctx, + priv->fsping_timer); + } + priv->fsping_timer = + gf_timer_call_after (this->ctx, + delta, + posix_fsping_timer_expired, + (void *) this); + + if (priv->fsping_timer == NULL) { + gf_log (this->name, GF_LOG_ERROR, + "unable to register timer"); + /*FIXME: handle error*/ + } + pthread_create (&priv->fsping, + NULL, + posix_fsping_statvfs, + this); +} int32_t posix_rchecksum (call_frame_t *frame, xlator_t *this, @@ -4780,12 +4893,15 @@ notify (xlator_t *this, void *data, ...) { + struct posix_private *priv = NULL; + + priv = this->private; + switch (event) { case GF_EVENT_PARENT_UP: { - /* Tell the parent that posix xlator is up */ - default_notify (this, GF_EVENT_CHILD_UP, data); + posix_fsping ((void *)this); } break; default: @@ -4809,9 +4925,9 @@ init (xlator_t *this) data_t * dir_data = NULL; data_t * tmp_data = NULL; uint64_t time64 = 0; - - int dict_ret = 0; - int32_t janitor_sleep; + int dict_ret = -1; + int fsping_timeout = -1; + int32_t janitor_sleep; dir_data = dict_get (this->options, "directory"); @@ -4908,6 +5024,7 @@ init (xlator_t *this) strcat (_private->trash_path, "/" GF_REPLICATE_TRASH_DIR); LOCK_INIT (&_private->lock); + pthread_mutex_init (&_private->mutex, NULL); ret = gethostname (_private->hostname, 256); if (ret < 0) { @@ -4923,6 +5040,17 @@ init (xlator_t *this) _private->max_write = 1; } + _private->fsping_timeout = POSIX_FSPING_TIMEOUT; + dict_ret = dict_get_int32 (this->options, + "fsping-timeout", + &fsping_timeout); + + if (dict_ret == 0) { + _private->fsping_timeout = fsping_timeout; + } + gf_log (this->name, GF_LOG_DEBUG, + "fsping-timeout set to %d", _private->fsping_timeout); + _private->export_statfs = 1; tmp_data = dict_get (this->options, "export-statfs-size"); if (tmp_data) { @@ -5056,6 +5184,7 @@ fini (xlator_t *this) { struct posix_private *priv = this->private; sys_lremovexattr (priv->base_path, "trusted.glusterfs.test"); + pthread_mutex_destroy (&priv->mutex); FREE (priv); return; } @@ -5132,6 +5261,8 @@ struct volume_options options[] = { .type = GF_OPTION_TYPE_BOOL }, { .key = {"span-devices"}, .type = GF_OPTION_TYPE_INT }, + { .key = {"fsping-timeout"}, + .type = GF_OPTION_TYPE_INT }, { .key = {"background-unlink"}, .type = GF_OPTION_TYPE_BOOL }, { .key = {"janitor-sleep-duration"}, diff --git a/xlators/storage/posix/src/posix.h b/xlators/storage/posix/src/posix.h index f92e256fbc0..92fe8e2515c 100644 --- a/xlators/storage/posix/src/posix.h +++ b/xlators/storage/posix/src/posix.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #ifdef linux @@ -50,6 +51,7 @@ #include "xlator.h" #include "inode.h" #include "compat.h" +#include "timer.h" /** * posix_fd - internal structure common to file and directory fd's @@ -70,6 +72,7 @@ struct posix_private { int32_t base_path_length; gf_lock_t lock; + pthread_mutex_t mutex; char hostname[256]; /* Statistics, provides activity of the server */ @@ -117,6 +120,11 @@ struct posix_private { int num_devices_to_span; dev_t *st_device; + pthread_t fsping; + gf_timer_t *fsping_timer; + int fsping_timeout; + int fs_state; + /* a global generation number sequence is used to assign generation numbers in sequence. */ @@ -129,6 +137,9 @@ struct posix_private { char * trash_path; }; +#define POSIX_FSPING_SLEEP_TIME 10 +#define POSIX_FSPING_TIMEOUT 10 + #define POSIX_BASE_PATH(this) (((struct posix_private *)this->private)->base_path) #define POSIX_BASE_PATH_LEN(this) (((struct posix_private *)this->private)->base_path_length) -- cgit