diff options
| -rw-r--r-- | libglusterfs/src/common-utils.c | 43 | ||||
| -rw-r--r-- | libglusterfs/src/common-utils.h | 1 | ||||
| -rw-r--r-- | xlators/features/marker/src/marker.c | 4 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 69 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.c | 65 | 
5 files changed, 169 insertions, 13 deletions
diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c index 54ee3e53818..be8bd6298ac 100644 --- a/libglusterfs/src/common-utils.c +++ b/libglusterfs/src/common-utils.c @@ -3232,3 +3232,46 @@ gf_compare_sockaddr (const struct sockaddr *addr1,          }          return _gf_false;  } + +/* + * gf_set_timestamp: + *      It sets the mtime and atime of 'dest' file as of 'src'. + */ + +int +gf_set_timestamp  (const char *src, const char* dest) +{ +        struct stat    sb             = {0, }; +        struct timeval new_time[2]    = {{0, },{0,}}; +        int            ret            = 0; +        xlator_t       *this          = NULL; + +        this = THIS; +        GF_ASSERT (this); +        GF_ASSERT (src); +        GF_ASSERT (dest); + +        ret = stat (src, &sb); +        if (ret) { +                gf_log (this->name, GF_LOG_ERROR, "stat on %s failed: %s", +                        src, strerror(errno)); +                goto out; +        } +        new_time[0].tv_sec = sb.st_atime; +        new_time[0].tv_usec = ST_ATIM_NSEC (&sb)/1000; + +        new_time[1].tv_sec = sb.st_mtime; +        new_time[1].tv_usec = ST_MTIM_NSEC (&sb)/1000; + +        /* The granularity is micro seconds as per the current +         * requiremnt. Hence using 'utimes'. This can be updated +         * to 'utimensat' if we need timestamp in nanoseconds. +         */ +        ret = utimes (dest, new_time); +        if (ret) { +                gf_log (this->name, GF_LOG_ERROR, "utimes on %s failed: %s", +                        dest, strerror(errno)); +        } +out: +        return ret; +} diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index 98f30fc47b0..4eec5170c60 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -620,6 +620,7 @@ int gf_get_hostname_from_ip (char *client_ip, char **hostname);  gf_boolean_t gf_is_local_addr (char *hostname);  gf_boolean_t gf_is_same_address (char *host1, char *host2);  void md5_wrapper(const unsigned char *data, size_t len, char *md5); +int gf_set_timestamp  (const char *src, const char* dest);  int gf_thread_create (pthread_t *thread, const pthread_attr_t *attr,                        void *(*start_routine)(void *), void *arg); diff --git a/xlators/features/marker/src/marker.c b/xlators/features/marker/src/marker.c index a92c57dac1e..e9a8e544b3b 100644 --- a/xlators/features/marker/src/marker.c +++ b/xlators/features/marker/src/marker.c @@ -216,8 +216,8 @@ stat_stampfile (xlator_t *this, marker_conf_t *priv,          if (stat (priv->timestamp_file, &buf) != -1) {                  vol_mark->retval = 0; -                vol_mark->sec = htonl (buf.st_ctime); -                vol_mark->usec = htonl (ST_CTIM_NSEC (&buf)/1000); +                vol_mark->sec = htonl (buf.st_mtime); +                vol_mark->usec = htonl (ST_MTIM_NSEC (&buf)/1000);          } else                  vol_mark->retval = 1; diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index ee3759e91d4..8b9b4b1a018 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -621,6 +621,62 @@ out:          return ret;  } +/* + * glusterd_snap_geo_rep_restore: + *      This function restores the atime and mtime of marker.tstamp + *      if present from snapped marker.tstamp file. + */ +static int +glusterd_snap_geo_rep_restore (glusterd_volinfo_t *snap_volinfo, +                               glusterd_volinfo_t *new_volinfo) +{ +        char                    vol_tstamp_file[PATH_MAX]  = {0,}; +        char                    snap_tstamp_file[PATH_MAX] = {0,}; +        glusterd_conf_t         *priv                      = NULL; +        xlator_t                *this                      = NULL; +        int                     geo_rep_indexing_on        = 0; +        int                     ret                        = 0; + +        this = THIS; +        GF_ASSERT (this); +        GF_ASSERT (snap_volinfo); +        GF_ASSERT (new_volinfo); + +        priv = this->private; +        GF_ASSERT (priv); + +        /* Check if geo-rep indexing is enabled, if yes, we need restore +         * back the mtime of 'marker.tstamp' file. +         */ +        geo_rep_indexing_on = glusterd_volinfo_get_boolean (new_volinfo, +                                                            VKEY_MARKER_XTIME); +        if (geo_rep_indexing_on == -1) { +                gf_log (this->name, GF_LOG_DEBUG, "Failed" +                        " to check whether geo-rep-indexing enabled or not"); +                ret = 0; +                goto out; +        } + +        if (geo_rep_indexing_on == 1) { +                GLUSTERD_GET_VOLUME_DIR (vol_tstamp_file, new_volinfo, priv); +                strncat (vol_tstamp_file, "/marker.tstamp", +                         PATH_MAX - strlen(vol_tstamp_file) - 1); +                GLUSTERD_GET_VOLUME_DIR (snap_tstamp_file, snap_volinfo, priv); +                strncat (snap_tstamp_file, "/marker.tstamp", +                         PATH_MAX - strlen(snap_tstamp_file) - 1); +                ret = gf_set_timestamp (snap_tstamp_file, vol_tstamp_file); +                if (ret) { +                        gf_log (this->name, GF_LOG_ERROR, +                                "Unable to set atime and mtime of %s as of %s", +                                vol_tstamp_file, snap_tstamp_file); +                        goto out; +                } +        } + +out: +        return ret; +} +  /* This function will copy snap volinfo to the new   * passed volinfo and regenerate backend store files   * for the restored snap. @@ -760,6 +816,19 @@ glusterd_snap_volinfo_restore (dict_t *dict, dict_t *rsp_dict,          /* Regenerate all volfiles */          ret = glusterd_create_volfiles_and_notify_services (new_volinfo); +        if (ret) { +                gf_log (this->name, GF_LOG_ERROR, +                        "Failed to regenerate volfiles"); +                goto out; +        } + +        /* Restore geo-rep marker.tstamp's timestamp */ +        ret = glusterd_snap_geo_rep_restore (snap_volinfo, new_volinfo); +        if (ret) { +                gf_log (this->name, GF_LOG_ERROR, +                        "Geo-rep: marker.tstamp's timestamp restoration failed"); +                goto out; +        }  out:          if (ret && (NULL != new_brickinfo)) { diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index 9701c6b939c..f1e30e1ee82 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -16,6 +16,7 @@  #include <fnmatch.h>  #include <sys/wait.h>  #include <dlfcn.h> +#include <utime.h>  #if (HAVE_LIB_XML)  #include <libxml/encoding.h> @@ -3824,12 +3825,34 @@ get_vol_tstamp_file (char *filename, glusterd_volinfo_t *volinfo)                   PATH_MAX - strlen(filename) - 1);  } +static void +get_parent_vol_tstamp_file (char *filename, glusterd_volinfo_t *volinfo) +{ +        glusterd_conf_t *priv  = NULL; +        xlator_t        *this  = NULL; + +        this = THIS; +        GF_ASSERT (this); +        priv = this->private; +        GF_ASSERT (priv); + +        snprintf (filename, PATH_MAX, "%s/vols/%s", priv->workdir, +                  volinfo->parent_volname); +        strncat (filename, "/marker.tstamp", +                 PATH_MAX - strlen(filename) - 1); +} +  int  generate_brick_volfiles (glusterd_volinfo_t *volinfo)  { -        glusterd_brickinfo_t    *brickinfo = NULL; -        char                     tstamp_file[PATH_MAX] = {0,}; -        int                      ret = -1; +        glusterd_brickinfo_t    *brickinfo                    = NULL; +        char                     tstamp_file[PATH_MAX]        = {0,}; +        char                     parent_tstamp_file[PATH_MAX] = {0,}; +        int                      ret                          = -1; +        xlator_t                *this                         = NULL; + +        this = THIS; +        GF_ASSERT (this);          ret = glusterd_volinfo_get_boolean (volinfo, VKEY_MARKER_XTIME);          if (ret == -1) @@ -3840,29 +3863,49 @@ generate_brick_volfiles (glusterd_volinfo_t *volinfo)          if (ret) {                  ret = open (tstamp_file, O_WRONLY|O_CREAT|O_EXCL, 0600);                  if (ret == -1 && errno == EEXIST) { -                        gf_log ("", GF_LOG_DEBUG, "timestamp file exist"); +                        gf_log (this->name, GF_LOG_DEBUG, +                                "timestamp file exist");                          ret = -2;                  }                  if (ret == -1) { -                        gf_log ("", GF_LOG_ERROR, "failed to create %s (%s)", -                                tstamp_file, strerror (errno)); +                        gf_log (this->name, GF_LOG_ERROR, "failed to create " +                                "%s (%s)", tstamp_file, strerror (errno));                          return -1;                  } -                if (ret >= 0) +                if (ret >= 0) {                          close (ret); +                        /* If snap_volume, retain timestamp for marker.tstamp +                         * from parent. Geo-replication depends on mtime of +                         * 'marker.tstamp' to decide the volume-mark, i.e., +                         * geo-rep start time just after session is created. +                         */ +                        if (volinfo->is_snap_volume) { +                                get_parent_vol_tstamp_file (parent_tstamp_file, +                                                            volinfo); +                                ret = gf_set_timestamp (parent_tstamp_file, +                                                        tstamp_file); +                                if (ret) { +                                        gf_log (this->name, GF_LOG_ERROR, +                                                "Unable to set atime and mtime" +                                                " of %s as of %s", tstamp_file, +                                                parent_tstamp_file); +                                        goto out; +                                } +                        } +                }          } else {                  ret = unlink (tstamp_file);                  if (ret == -1 && errno == ENOENT)                          ret = 0;                  if (ret == -1) { -                        gf_log ("", GF_LOG_ERROR, "failed to unlink %s (%s)", -                                tstamp_file, strerror (errno)); +                        gf_log (this->name, GF_LOG_ERROR, "failed to unlink " +                                "%s (%s)", tstamp_file, strerror (errno));                          return -1;                  }          }          list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { -                gf_log ("", GF_LOG_DEBUG, +                gf_log (this->name, GF_LOG_DEBUG,                          "Found a brick - %s:%s", brickinfo->hostname,                          brickinfo->path); @@ -3875,7 +3918,7 @@ generate_brick_volfiles (glusterd_volinfo_t *volinfo)          ret = 0;  out: -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret);          return ret;  }  | 
