From acabde2c297c4175946565017ba17a251ad3fb1c Mon Sep 17 00:00:00 2001 From: Ajeet Jha Date: Sat, 23 Aug 2014 19:06:45 +0530 Subject: features/changelog: Crash consistency of changelog wrt snapshot This patch introduces call-path fop details logging for data operations in CHANGELOG.SNAP. This feature is enabled with barrier-enable notification and disabled with barrier-disable notification. Change-Id: Ib548d34203eb99cea478a6baff402e82251c73a4 BUG: 1128093 Signed-off-by: Ajeet Jha Reviewed-on: http://review.gluster.org/8533 Tested-by: Gluster Build System Reviewed-by: Vijay Bellur --- xlators/features/changelog/src/changelog-helpers.c | 156 +++++++++++++++++++++ xlators/features/changelog/src/changelog-helpers.h | 18 +++ xlators/features/changelog/src/changelog-misc.h | 6 + xlators/features/changelog/src/changelog.c | 52 +++++++ 4 files changed, 232 insertions(+) diff --git a/xlators/features/changelog/src/changelog-helpers.c b/xlators/features/changelog/src/changelog-helpers.c index 07c6096dce5..9dccf45187c 100644 --- a/xlators/features/changelog/src/changelog-helpers.c +++ b/xlators/features/changelog/src/changelog-helpers.c @@ -337,6 +337,101 @@ out: return ret; } +/* Description: + * Opens the snap changelog to log call path fops in it. + * This changelos name is "CHANGELOG.SNAP", stored in + * path ".glusterfs/changelogs/csnap". + * Returns: + * 0 : On success. + * -1 : On failure. + */ +int +changelog_snap_open (xlator_t *this, + changelog_priv_t *priv) +{ + int fd = -1; + int ret = 0; + int flags = 0; + char buffer[1024] = {0,}; + char c_snap_path[PATH_MAX] = {0,}; + char csnap_dir_path[PATH_MAX] = {0,}; + + CHANGELOG_FILL_CSNAP_DIR(priv->changelog_dir, csnap_dir_path); + + (void) snprintf (c_snap_path, PATH_MAX, + "%s/"CSNAP_FILE_NAME, + csnap_dir_path); + + flags |= (O_CREAT | O_RDWR | O_TRUNC); + + fd = open (c_snap_path, flags, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (fd < 0) { + gf_log (this->name, GF_LOG_ERROR, + "unable to open %s file " + "reason:(%s)", c_snap_path, strerror (errno)); + ret = -1; + goto out; + } + priv->c_snap_fd = fd; + + (void) snprintf (buffer, 1024, CHANGELOG_HEADER, + CHANGELOG_VERSION_MAJOR, + CHANGELOG_VERSION_MINOR, + priv->ce->encoder); + ret = changelog_snap_write_change (priv, buffer, strlen (buffer)); + if (ret < 0) { + close (priv->c_snap_fd); + priv->c_snap_fd = -1; + goto out; + } + +out: + return ret; +} + +/* + * Description: + * Starts logging fop details in CSNAP journal. + * Returns: + * 0 : On success. + * -1 : On Failure. + */ +int +changelog_snap_logging_start (xlator_t *this, + changelog_priv_t *priv) +{ + int ret = 0; + + ret = changelog_snap_open (this, priv); + gf_log (this->name, GF_LOG_INFO, + "Now starting to log in call path"); + + return ret; +} + +/* + * Description: + * Stops logging fop details in CSNAP journal. + * Returns: + * 0 : On success. + * -1 : On Failure. + */ +int +changelog_snap_logging_stop (xlator_t *this, + changelog_priv_t *priv) +{ + int ret = 0; + + close (priv->c_snap_fd); + priv->c_snap_fd = -1; + + gf_log (this->name, GF_LOG_INFO, + "Stopped to log in call path"); + + return ret; +} + int changelog_open (xlator_t *this, changelog_priv_t *priv) @@ -423,12 +518,73 @@ changelog_fill_rollover_data (changelog_log_data_t *cld, gf_boolean_t is_last) return 0; } +int +changelog_snap_write_change (changelog_priv_t *priv, char *buffer, size_t len) +{ + return changelog_write (priv->c_snap_fd, buffer, len); +} + int changelog_write_change (changelog_priv_t *priv, char *buffer, size_t len) { return changelog_write (priv->changelog_fd, buffer, len); } +/* + * Descriptions: + * Writes fop details in ascii format to CSNAP. + * Issues: + * Not Encoding agnostic. + * Returns: + * 0 : On Success. + * -1 : On Failure. + */ +int +changelog_snap_handle_ascii_change (xlator_t *this, + changelog_log_data_t *cld) +{ + size_t off = 0; + size_t gfid_len = 0; + char *gfid_str = NULL; + char *buffer = NULL; + changelog_priv_t *priv = NULL; + int ret = 0; + + if (this == NULL) { + ret = -1; + goto out; + } + + priv = this->private; + + if (priv == NULL) { + ret = -1; + goto out; + } + + gfid_str = uuid_utoa (cld->cld_gfid); + gfid_len = strlen (gfid_str); + + /* extra bytes for decorations */ + buffer = alloca (gfid_len + cld->cld_ptr_len + 10); + CHANGELOG_STORE_ASCII (priv, buffer, + off, gfid_str, gfid_len, cld); + + CHANGELOG_FILL_BUFFER (buffer, off, "\0", 1); + + ret = changelog_snap_write_change (priv, buffer, off); + + if (ret < 0) { + gf_log (this->name, GF_LOG_ERROR, + "error writing csnap to disk"); + } + gf_log (this->name, GF_LOG_INFO, + "Successfully wrote to csnap"); + ret = 0; +out: + return ret; +} + inline int changelog_handle_change (xlator_t *this, changelog_priv_t *priv, changelog_log_data_t *cld) diff --git a/xlators/features/changelog/src/changelog-helpers.h b/xlators/features/changelog/src/changelog-helpers.h index 87888fb8c4f..9bd4a3ff37c 100644 --- a/xlators/features/changelog/src/changelog-helpers.h +++ b/xlators/features/changelog/src/changelog-helpers.h @@ -212,11 +212,17 @@ struct changelog_priv { /* htime fd for current changelog session */ int htime_fd; + /* c_snap_fd is fd for call-path changelog */ + int c_snap_fd; + /* rollover_count used by htime */ int rollover_count; gf_lock_t lock; + /* lock to synchronize CSNAP updation */ + gf_lock_t c_snap_lock; + /* writen end of the pipe */ int wfd; @@ -431,6 +437,18 @@ changelog_drain_white_fops (xlator_t *this, changelog_priv_t *priv); void changelog_drain_black_fops (xlator_t *this, changelog_priv_t *priv); +/* Crash consistency of changelog wrt snapshot */ +int +changelog_snap_logging_stop ( xlator_t *this, changelog_priv_t *priv); +int +changelog_snap_logging_start ( xlator_t *this, changelog_priv_t *priv); +int +changelog_snap_open ( xlator_t *this, changelog_priv_t *priv); +int +changelog_snap_handle_ascii_change (xlator_t *this, + changelog_log_data_t *cld); +int +changelog_snap_write_change (changelog_priv_t *priv, char *buffer, size_t len); /* Changelog barrier routines */ void __chlog_barrier_enqueue (xlator_t *this, call_stub_t *stub); void __chlog_barrier_disable (xlator_t *this, struct list_head *queue); diff --git a/xlators/features/changelog/src/changelog-misc.h b/xlators/features/changelog/src/changelog-misc.h index 257c1f34218..58b10961463 100644 --- a/xlators/features/changelog/src/changelog-misc.h +++ b/xlators/features/changelog/src/changelog-misc.h @@ -17,6 +17,7 @@ #define CHANGELOG_MAX_TYPE 3 #define CHANGELOG_FILE_NAME "CHANGELOG" #define HTIME_FILE_NAME "HTIME" +#define CSNAP_FILE_NAME "CHANGELOG.SNAP" #define HTIME_KEY "trusted.glusterfs.htime" #define HTIME_INITIAL_VALUE "0:0" @@ -71,6 +72,11 @@ strcpy (path, changelog_dir); \ strcat (path, "/htime"); \ } while(0) + +#define CHANGELOG_FILL_CSNAP_DIR(changelog_dir, path) do { \ + strcpy (path, changelog_dir); \ + strcat (path, "/csnap"); \ + } while(0) /** * everything after 'CHANGELOG_TYPE_ENTRY' are internal types * (ie. none of the fops trigger this type of event), hence diff --git a/xlators/features/changelog/src/changelog.c b/xlators/features/changelog/src/changelog.c index 36643395815..75a62d686d6 100644 --- a/xlators/features/changelog/src/changelog.c +++ b/xlators/features/changelog/src/changelog.c @@ -1433,6 +1433,16 @@ changelog_truncate (call_frame_t *frame, CHANGELOG_INIT (this, frame->local, loc->inode, loc->inode->gfid, 0); + LOCK(&priv->c_snap_lock); + { + if (priv->c_snap_fd != -1 && + priv->barrier_enabled == _gf_true) { + changelog_snap_handle_ascii_change (this, + &( ((changelog_local_t *)(frame->local))->cld)); + } + } + UNLOCK(&priv->c_snap_lock); + wind: changelog_color_fop_and_inc_cnt (this, priv, frame->local); @@ -1476,6 +1486,15 @@ changelog_ftruncate (call_frame_t *frame, CHANGELOG_INIT (this, frame->local, fd->inode, fd->inode->gfid, 0); + LOCK(&priv->c_snap_lock); + { + if (priv->c_snap_fd != -1 && + priv->barrier_enabled == _gf_true) { + changelog_snap_handle_ascii_change (this, + &( ((changelog_local_t *)(frame->local))->cld)); + } + } + UNLOCK(&priv->c_snap_lock); wind: changelog_color_fop_and_inc_cnt (this, priv, frame->local); @@ -1523,6 +1542,15 @@ changelog_writev (call_frame_t *frame, CHANGELOG_INIT (this, frame->local, fd->inode, fd->inode->gfid, 0); + LOCK(&priv->c_snap_lock); + { + if (priv->c_snap_fd != -1 && + priv->barrier_enabled == _gf_true) { + changelog_snap_handle_ascii_change (this, + &( ((changelog_local_t *)(frame->local))->cld)); + } + } + UNLOCK(&priv->c_snap_lock); wind: changelog_color_fop_and_inc_cnt (this, priv, frame->local); @@ -1751,6 +1779,11 @@ notify (xlator_t *this, int event, void *data, ...) "Barrier off notification"); CHANGELOG_NOT_ON_THEN_GOTO(priv, ret, out); + LOCK(&priv->c_snap_lock); + { + changelog_snap_logging_stop (this, priv); + } + UNLOCK(&priv->c_snap_lock); LOCK (&priv->bflags.lock); { @@ -1800,6 +1833,11 @@ notify (xlator_t *this, int event, void *data, ...) "Barrier on notification"); CHANGELOG_NOT_ON_THEN_GOTO(priv, ret, out); + LOCK(&priv->c_snap_lock); + { + changelog_snap_logging_start (this, priv); + } + UNLOCK(&priv->c_snap_lock); LOCK (&priv->bflags.lock); { @@ -2080,6 +2118,7 @@ reconfigure (xlator_t *this, dict_t *options) changelog_time_slice_t *slice = NULL; changelog_log_data_t cld = {0,}; char htime_dir[PATH_MAX] = {0,}; + char csnap_dir[PATH_MAX] = {0,}; struct timeval tv = {0,}; uint32_t timeout = 0; @@ -2112,6 +2151,12 @@ reconfigure (xlator_t *this, dict_t *options) CHANGELOG_FILL_HTIME_DIR(priv->changelog_dir, htime_dir); ret = mkdir_p (htime_dir, 0600, _gf_true); + if (ret) + goto out; + + CHANGELOG_FILL_CSNAP_DIR(priv->changelog_dir, csnap_dir); + ret = mkdir_p (csnap_dir, 0600, _gf_true); + if (ret) goto out; @@ -2197,6 +2242,7 @@ init (xlator_t *this) changelog_priv_t *priv = NULL; gf_boolean_t cond_lock_init = _gf_false; char htime_dir[PATH_MAX] = {0,}; + char csnap_dir[PATH_MAX] = {0,}; uint32_t timeout = 0; GF_VALIDATE_OR_GOTO ("changelog", this, out); @@ -2225,6 +2271,7 @@ init (xlator_t *this) } LOCK_INIT (&priv->lock); + LOCK_INIT (&priv->c_snap_lock); GF_OPTION_INIT ("changelog-brick", tmp, str, out); if (!tmp) { @@ -2264,6 +2311,11 @@ init (xlator_t *this) if (ret) goto out; + CHANGELOG_FILL_CSNAP_DIR(priv->changelog_dir, csnap_dir); + ret = mkdir_p (csnap_dir, 0600, _gf_true); + if (ret) + goto out; + GF_OPTION_INIT ("changelog", priv->active, bool, out); GF_OPTION_INIT ("op-mode", tmp, str, out); -- cgit