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