diff options
-rw-r--r-- | tests/bugs/changelog/bug-1211327.t | 48 | ||||
-rw-r--r-- | tests/changelog.rc | 4 | ||||
-rw-r--r-- | tests/volume.rc | 5 | ||||
-rw-r--r-- | xlators/features/changelog/src/changelog-helpers.c | 212 | ||||
-rw-r--r-- | xlators/features/changelog/src/changelog-helpers.h | 4 | ||||
-rw-r--r-- | xlators/features/changelog/src/changelog-misc.h | 1 | ||||
-rw-r--r-- | xlators/features/changelog/src/changelog.c | 5 |
7 files changed, 268 insertions, 11 deletions
diff --git a/tests/bugs/changelog/bug-1211327.t b/tests/bugs/changelog/bug-1211327.t new file mode 100644 index 00000000000..19d6e76ecab --- /dev/null +++ b/tests/bugs/changelog/bug-1211327.t @@ -0,0 +1,48 @@ +#!/bin/bash + +#Testcase: +#On brick restart, new HTIME.TSTAMP file should not be created. +#But on changelog disable/enable HTIME.TSTAMP should be created. + +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +. $(dirname $0)/../../changelog.rc +cleanup; + +## Start and create a volume +TEST glusterd; +TEST pidof glusterd; +TEST $CLI volume create $V0 $H0:$B0/$V0"1"; + +## Verify volume is is created +EXPECT "$V0" volinfo_field $V0 'Volume Name'; +EXPECT 'Created' volinfo_field $V0 'Status'; + +## Start volume and verify +TEST $CLI volume start $V0; +EXPECT 'Started' volinfo_field $V0 'Status'; + +TEST $CLI volume set $V0 changelog.changelog on; +##Let changelog init complete before killing gluster processes +sleep 1 + +TEST killall_gluster; +sleep 1 +EXPECT 0 online_brick_count; + +TEST glusterd; +TEST pidof glusterd; +##Let the brick processes starts +sleep 1; + +EXPECT 1 online_brick_count; + +##On brick restart only one HTIME should be found. +EXPECT 1 count_htime_files; + +##On changelog disable/enable, new HTIME should be created. +TEST $CLI volume set $V0 changelog.changelog off; +TEST $CLI volume set $V0 changelog.changelog on; +EXPECT 2 count_htime_files; + +cleanup; diff --git a/tests/changelog.rc b/tests/changelog.rc new file mode 100644 index 00000000000..e3b040226ec --- /dev/null +++ b/tests/changelog.rc @@ -0,0 +1,4 @@ + +function count_htime_files { + ls -l $B0/$V0"1"/.glusterfs/changelogs/htime/ | grep HTIME | wc -l +} diff --git a/tests/volume.rc b/tests/volume.rc index 6c0e6abea83..b0211cbe2fc 100644 --- a/tests/volume.rc +++ b/tests/volume.rc @@ -410,6 +410,11 @@ function volume_exists() { fi } +function killall_gluster() { + pkill gluster + sleep 1 +} + function afr_get_index_count { local brick=$1 ls $1/.glusterfs/indices/xattrop | grep -v xattrop | wc -l diff --git a/xlators/features/changelog/src/changelog-helpers.c b/xlators/features/changelog/src/changelog-helpers.c index aef847c037b..585214df635 100644 --- a/xlators/features/changelog/src/changelog-helpers.c +++ b/xlators/features/changelog/src/changelog-helpers.c @@ -422,17 +422,177 @@ changelog_rollover_changelog (xlator_t *this, return ret; } -/* Returns 0 on successful creation of htime file +int +filter_cur_par_dirs (const struct dirent *entry) +{ + if (entry == NULL) + return 0; + + if ((strcmp(entry->d_name, ".") == 0) || + (strcmp(entry->d_name, "..") == 0)) + return 0; + else + return 1; +} + +/* + * find_current_htime: + * It finds the latest htime file and sets the HTIME_CURRENT + * xattr. + * RETURN VALUE: + * -1 : Error + * ret: Number of directory entries; + */ + +int +find_current_htime (int ht_dir_fd, const char *ht_dir_path, char *ht_file_bname) +{ + struct dirent **namelist = NULL; + int ret = 0; + int cnt = 0; + int i = 0; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + GF_ASSERT (ht_dir_path); + + cnt = scandir (ht_dir_path, &namelist, filter_cur_par_dirs, alphasort); + if (cnt < 0) { + gf_log (this->name, GF_LOG_ERROR, + "scandir failed: %s", strerror (errno)); + } else if (cnt > 0) { + strncpy (ht_file_bname, namelist[cnt - 1]->d_name, NAME_MAX); + ht_file_bname[NAME_MAX - 1] = 0; + + if (sys_fsetxattr (ht_dir_fd, HTIME_CURRENT, ht_file_bname, + strlen (ht_file_bname), 0)) { + gf_log (this->name, GF_LOG_ERROR, "fsetxattr failed:" + " HTIME_CURRENT: %s", strerror (errno)); + ret = -1; + goto out; + } + + if (fsync (ht_dir_fd) < 0) { + gf_log (this->name, GF_LOG_ERROR, + "fsync failed (reason: %s)", strerror (errno)); + ret = -1; + goto out; + } + } + + out: + for (i = 0; i < cnt; i++) + free (namelist[i]); + free (namelist); + + if (ret) + cnt = ret; + + return cnt; +} + +/* Returns 0 on successful open of htime file * returns -1 on failure or error */ int htime_open (xlator_t *this, - changelog_priv_t * priv, unsigned long ts) + changelog_priv_t *priv, unsigned long ts) { - int fd = -1; + int ht_file_fd = -1; + int ht_dir_fd = -1; int ret = 0; + int cnt = 0; char ht_dir_path[PATH_MAX] = {0,}; char ht_file_path[PATH_MAX] = {0,}; + char ht_file_bname[NAME_MAX] = {0,}; + char x_value[NAME_MAX] = {0,}; + int flags = 0; + unsigned long min_ts = 0; + unsigned long max_ts = 0; + unsigned long total = 0; + ssize_t size = 0; + + CHANGELOG_FILL_HTIME_DIR(priv->changelog_dir, ht_dir_path); + + /* Open htime directory to get HTIME_CURRENT */ + ht_dir_fd = open (ht_dir_path, O_RDONLY); + if (ht_dir_fd == -1) { + gf_log (this->name, GF_LOG_ERROR, "open failed: %s : %s", + ht_dir_path, strerror (errno)); + ret = -1; + goto out; + } + + size = sys_fgetxattr (ht_dir_fd, HTIME_CURRENT, ht_file_bname, + sizeof (ht_file_bname)); + if (size < 0) { + gf_log (this->name, GF_LOG_ERROR, "Error extracting" + " HTIME_CURRENT: %s.", strerror (errno)); + + /* If upgrade scenario, find the latest HTIME.TSTAMP file + * and use the same. If error, create a new HTIME.TSTAMP + * file. + */ + cnt = find_current_htime (ht_dir_fd, ht_dir_path, + ht_file_bname); + if (cnt <= 0) + return htime_create (this, priv, ts); + } + + gf_log (this->name, GF_LOG_INFO, "HTIME_CURRENT: %s", ht_file_bname); + (void) snprintf (ht_file_path, PATH_MAX, "%s/%s", + ht_dir_path, ht_file_bname); + + /* Open in append mode as existing htime file is used */ + flags |= (O_RDWR | O_SYNC | O_APPEND); + ht_file_fd = open (ht_file_path, flags, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (ht_file_fd < 0) { + gf_log (this->name, GF_LOG_ERROR, + "unable to open htime file: %s" + "(reason: %s)", ht_file_path, strerror (errno)); + ret = -1; + goto out; + } + + /* save this htime_fd in priv->htime_fd */ + priv->htime_fd = ht_file_fd; + + /* Initialize rollover-number in priv to current number */ + size = sys_fgetxattr (ht_file_fd, HTIME_KEY, x_value, sizeof (x_value)); + if (size < 0) { + gf_log (this->name, GF_LOG_ERROR, "error extracting max" + " timstamp from htime file %s (reason %s)", + ht_file_path, strerror (errno)); + ret = -1; + goto out; + } + + sscanf (x_value, "%lu:%lu", &max_ts, &total); + gf_log (this->name, GF_LOG_INFO, "INIT CASE: MIN: %lu, MAX: %lu," + " TOTAL CHANGELOGS: %lu", min_ts, max_ts, total); + priv->rollover_count = total + 1; + +out: + if (ht_dir_fd != -1) + close (ht_dir_fd); + return ret; +} + +/* Returns 0 on successful creation of htime file + * returns -1 on failure or error + */ +int +htime_create (xlator_t *this, + changelog_priv_t *priv, unsigned long ts) +{ + int ht_file_fd = -1; + int ht_dir_fd = -1; + int ret = 0; + char ht_dir_path[PATH_MAX] = {0,}; + char ht_file_path[PATH_MAX] = {0,}; + char ht_file_bname[NAME_MAX] = {0,}; int flags = 0; CHANGELOG_FILL_HTIME_DIR(priv->changelog_dir, ht_dir_path); @@ -442,18 +602,17 @@ htime_open (xlator_t *this, HTIME_FILE_NAME, ts); flags |= (O_CREAT | O_RDWR | O_SYNC); - fd = open (ht_file_path, flags, + ht_file_fd = open (ht_file_path, flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (fd < 0) { + if (ht_file_fd < 0) { gf_log (this->name, GF_LOG_ERROR, - "unable to open/create htime file: %s" + "unable to create htime file: %s" "(reason: %s)", ht_file_path, strerror (errno)); ret = -1; goto out; - } - if (sys_fsetxattr (fd, HTIME_KEY, HTIME_INITIAL_VALUE, + if (sys_fsetxattr (ht_file_fd, HTIME_KEY, HTIME_INITIAL_VALUE, sizeof (HTIME_INITIAL_VALUE)-1, 0)) { gf_log (this->name, GF_LOG_ERROR, "Htime xattr initialization failed"); @@ -461,12 +620,47 @@ htime_open (xlator_t *this, goto out; } + ret = fsync (ht_file_fd); + if (ret < 0) { + gf_log (this->name, GF_LOG_ERROR, "fsync failed (reason: %s)", + strerror (errno)); + goto out; + } + + /* Set xattr HTIME_CURRENT on htime directory to htime filename */ + ht_dir_fd = open (ht_dir_path, O_RDONLY); + if (ht_dir_fd == -1) { + gf_log (this->name, GF_LOG_ERROR, "open of %s failed: %s", + ht_dir_path, strerror (errno)); + ret = -1; + goto out; + } + + (void) snprintf (ht_file_bname, PATH_MAX, "%s.%lu", + HTIME_FILE_NAME, ts); + if (sys_fsetxattr (ht_dir_fd, HTIME_CURRENT, ht_file_bname, + strlen (ht_file_bname), 0)) { + gf_log (this->name, GF_LOG_ERROR, "fsetxattr failed:" + " HTIME_CURRENT: %s", strerror (errno)); + ret = -1; + goto out; + } + + ret = fsync (ht_dir_fd); + if (ret < 0) { + gf_log (this->name, GF_LOG_ERROR, "fsync failed (reason: %s)", + strerror (errno)); + goto out; + } + /* save this htime_fd in priv->htime_fd */ - priv->htime_fd = fd; + priv->htime_fd = ht_file_fd; /* initialize rollover-number in priv to 1 */ priv->rollover_count = 1; out: + if (ht_dir_fd != -1) + close (ht_dir_fd); return ret; } diff --git a/xlators/features/changelog/src/changelog-helpers.h b/xlators/features/changelog/src/changelog-helpers.h index 765d5fd878b..b552c308e0f 100644 --- a/xlators/features/changelog/src/changelog-helpers.h +++ b/xlators/features/changelog/src/changelog-helpers.h @@ -432,7 +432,9 @@ int htime_update (xlator_t *this, changelog_priv_t *priv, unsigned long ts, char * buffer); int -htime_open (xlator_t *this, changelog_priv_t * priv, unsigned long ts); +htime_open (xlator_t *this, changelog_priv_t *priv, unsigned long ts); +int +htime_create (xlator_t *this, changelog_priv_t *priv, unsigned long ts); /* Geo-Rep snapshot dependency changes */ void diff --git a/xlators/features/changelog/src/changelog-misc.h b/xlators/features/changelog/src/changelog-misc.h index 196bd4c8195..0de0edd9516 100644 --- a/xlators/features/changelog/src/changelog-misc.h +++ b/xlators/features/changelog/src/changelog-misc.h @@ -19,6 +19,7 @@ #define HTIME_FILE_NAME "HTIME" #define CSNAP_FILE_NAME "CHANGELOG.SNAP" #define HTIME_KEY "trusted.glusterfs.htime" +#define HTIME_CURRENT "trusted.glusterfs.current_htime" #define HTIME_INITIAL_VALUE "0:0" #define CHANGELOG_VERSION_MAJOR 1 diff --git a/xlators/features/changelog/src/changelog.c b/xlators/features/changelog/src/changelog.c index df8172765d7..7429fc5e891 100644 --- a/xlators/features/changelog/src/changelog.c +++ b/xlators/features/changelog/src/changelog.c @@ -2359,13 +2359,16 @@ reconfigure (xlator_t *this, dict_t *options) if (active_now) { if (!active_earlier) { + gf_log (this->name, GF_LOG_INFO, + "Changelog enable: Creating new " + "HTIME.TSTAMP file"); if (gettimeofday(&tv, NULL) ) { gf_log (this->name, GF_LOG_ERROR, "unable to fetch htime"); ret = -1; goto out; } - htime_open(this, priv, tv.tv_sec); + htime_create (this, priv, tv.tv_sec); } ret = changelog_spawn_helper_threads (this, priv); } |