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);                  }  | 
