cluster/*: get logic to calculate min() of the 'stime' xattr

* in both distribute and replicate (ignoring stripe for now),
  add logic to calculate the min() of stime values.

* What is a 'stime' ? Why is this required:
  -  stime means 'slave xtime', mainly used to keep track of slave
  node's sync status when distributed geo-replication is used.
  Logic of calculating 'min()' for this stime is very important as
  in case of crashes/reboots/shutdown, we will have to 'restart'
  with crawling from stime time value from the mount point, which
  gives the 'min()' of all the bricks, which means, we don't miss
  syncing any files in the above cases.

Change-Id: I2be8d434326572be9d4986db665570a6181db1ee
BUG: 847839
Original Author: Amar Tumballi <amarts@redhat.com>
Signed-off-by: Avra Sengupta <asengupt@redhat.com>
Reviewed-on: http://review.gluster.org/4893
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
This commit is contained in:
Avra Sengupta 2013-04-27 12:44:05 +05:30 committed by Vijay Bellur
parent 61b09562b9
commit 74f67e3a86
5 changed files with 121 additions and 2 deletions

View File

@ -112,6 +112,7 @@
#define GLUSTERFS_PARENT_ENTRYLK "glusterfs.parent-entrylk"
#define QUOTA_SIZE_KEY "trusted.glusterfs.quota.size"
#define GFID_TO_PATH_KEY "glusterfs.gfid2path"
#define GF_XATTR_STIME_PATTERN "trusted.glusterfs.*.stime"
/* Index xlator related */
#define GF_XATTROP_INDEX_GFID "glusterfs.xattrop_index_gfid"

View File

@ -1323,6 +1323,62 @@ afr_getxattr_pathinfo_cbk (call_frame_t *frame, void *cookie,
return ret;
}
static int
afr_aggregate_stime_xattr (dict_t *this, char *key, data_t *value, void *data)
{
int ret = 0;
if (fnmatch (GF_XATTR_STIME_PATTERN, key, FNM_NOESCAPE) == 0)
ret = gf_get_min_stime (THIS, data, key, value);
return ret;
}
int32_t
afr_common_getxattr_stime_cbk (call_frame_t *frame, void *cookie,
xlator_t *this, int32_t op_ret, int32_t op_errno,
dict_t *dict, dict_t *xdata)
{
afr_local_t *local = NULL;
int32_t callcnt = 0;
if (!frame || !frame->local || !this) {
gf_log ("", GF_LOG_ERROR, "possible NULL deref");
goto out;
}
local = frame->local;
LOCK (&frame->lock);
{
callcnt = --local->call_count;
if (!dict || (op_ret < 0)) {
local->op_errno = op_errno;
goto cleanup;
}
if (!local->dict)
local->dict = dict_copy_with_ref (dict, NULL);
else
dict_foreach (dict, afr_aggregate_stime_xattr,
local->dict);
local->op_ret = 0;
}
cleanup:
UNLOCK (&frame->lock);
if (!callcnt) {
AFR_STACK_UNWIND (getxattr, frame, local->op_ret,
local->op_errno, local->dict, xdata);
}
out:
return 0;
}
static gf_boolean_t
afr_is_special_xattr (const char *name, fop_getxattr_cbk_t *cbk,
gf_boolean_t is_fgetxattr)
@ -1355,6 +1411,8 @@ afr_is_special_xattr (const char *name, fop_getxattr_cbk_t *cbk,
} else {
*cbk = afr_getxattr_lockinfo_cbk;
}
} else if (fnmatch (GF_XATTR_STIME_PATTERN, name, FNM_NOESCAPE) == 0) {
*cbk = afr_common_getxattr_stime_cbk;
} else {
is_spl = _gf_false;
}

View File

@ -62,6 +62,11 @@ dht_aggregate (dict_t *this, char *key, data_t *value, void *data)
}
*size = hton64 (ntoh64 (*size) + ntoh64 (*ptr));
} else if (fnmatch (GF_XATTR_STIME_PATTERN, key, FNM_NOESCAPE) == 0) {
ret = gf_get_min_stime (THIS, dst, key, value);
if (ret < 0)
return ret;
} else {
/* compare user xattrs only */
if (!strncmp (key, "user.", strlen ("user."))) {

View File

@ -357,3 +357,58 @@ err:
return -1;
}
int
gf_get_min_stime (xlator_t *this, dict_t *dst, char *key, data_t *value)
{
int ret = -1;
uint32_t *net_timebuf = NULL;
uint32_t *value_timebuf = NULL;
uint32_t host_timebuf[2] = {0,};
uint32_t host_value_timebuf[2] = {0,};
/* stime should be minimum of all the other nodes */
ret = dict_get_bin (dst, key, (void **)&net_timebuf);
if (ret < 0) {
net_timebuf = GF_CALLOC (1, sizeof (int64_t),
gf_common_mt_char);
if (!net_timebuf)
goto out;
ret = dict_set_bin (dst, key, net_timebuf, sizeof (int64_t));
if (ret < 0) {
gf_log (this->name, GF_LOG_WARNING,
"key=%s: dict set failed", key);
goto error;
}
}
value_timebuf = data_to_bin (value);
if (!value_timebuf) {
gf_log (this->name, GF_LOG_WARNING,
"key=%s: getting value of stime failed", key);
ret = -1;
goto out;
}
get_hosttime (value_timebuf, host_value_timebuf);
get_hosttime (net_timebuf, host_timebuf);
/* can't use 'min()' macro here as we need to compare two fields
in the array, selectively */
if ((host_value_timebuf[0] > host_timebuf[0]) ||
((host_value_timebuf[0] == host_timebuf[0]) &&
(host_value_timebuf[1] > host_timebuf[1]))) {
update_timebuf (value_timebuf, net_timebuf);
}
ret = 0;
out:
return ret;
error:
/* To be used only when net_timebuf is not set in the dict */
if (net_timebuf)
GF_FREE (net_timebuf);
return ret;
}

View File

@ -98,7 +98,7 @@ cluster_getmarkerattr (call_frame_t *frame,xlator_t *this, loc_t *loc,
int
match_uuid_local (const char *name, char *uuid);
int
gf_get_min_stime (xlator_t *this, dict_t *dst, char *key, data_t *value);
#endif /* !_LIBXLATOR_H */