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:
parent
61b09562b9
commit
74f67e3a86
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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."))) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user