summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libglusterfs/src/common-utils.c43
-rw-r--r--libglusterfs/src/common-utils.h1
-rw-r--r--xlators/features/marker/src/marker.c4
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c69
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volgen.c65
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;
}