summaryrefslogtreecommitdiffstats
path: root/libglusterfs
diff options
context:
space:
mode:
authorKotresh HR <khiremat@redhat.com>2019-06-24 13:06:49 +0530
committerKotresh HR <khiremat@redhat.com>2019-08-06 12:53:43 +0530
commit173ec95d89244f169af778677fbc508843d83ef4 (patch)
treed3d07768d9b0a79af506f2a83d024e211dc19a8f /libglusterfs
parent70b52c3461ab7f9af570bfbf6b8117e25cc824ba (diff)
ctime: Set mdata xattr on legacy files
Problem: The files which were created before ctime enabled would not have "trusted.glusterfs.mdata"(stores time attributes) xattr. Upon fops which modifies either ctime or mtime, the xattr gets created with latest ctime, mtime and atime, which is incorrect. It should update only the corresponding time attribute and rest from backend Solution: Creating xattr with values from brick is not possible as each brick of replica set would have different times. So create the xattr upon successful lookup if the xattr is not created Note To Reviewers: The time attributes used to set xattr is got from successful lookup. Instead of sending the whole iatt over the wire via setxattr, a structure called mdata_iatt is sent. The mdata_iatt contains only time attributes. Backport of: > Patch: https://review.gluster.org/22936 > Change-Id: I5e535631ddef04195361ae0364336410a2895dd4 > BUG: 1593542 > Signed-off-by: Kotresh HR <khiremat@redhat.com> Change-Id: I5e535631ddef04195361ae0364336410a2895dd4 updates: bz#1733885 Signed-off-by: Kotresh HR <khiremat@redhat.com>
Diffstat (limited to 'libglusterfs')
-rw-r--r--libglusterfs/src/dict.c59
-rw-r--r--libglusterfs/src/glusterfs/dict.h5
-rw-r--r--libglusterfs/src/glusterfs/glusterfs.h3
-rw-r--r--libglusterfs/src/glusterfs/iatt.h20
-rw-r--r--libglusterfs/src/libglusterfs.sym3
5 files changed, 90 insertions, 0 deletions
diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c
index 4cd1fcf5bc0..a5568fc1ef2 100644
--- a/libglusterfs/src/dict.c
+++ b/libglusterfs/src/dict.c
@@ -124,6 +124,7 @@ int32_t
is_data_equal(data_t *one, data_t *two)
{
struct iatt *iatt1, *iatt2;
+ struct mdata_iatt *mdata_iatt1, *mdata_iatt2;
if (!one || !two || !one->data || !two->data) {
gf_msg_callingfn("dict", GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG,
@@ -188,6 +189,24 @@ is_data_equal(data_t *one, data_t *two)
*/
return 1;
}
+ if (one->data_type == GF_DATA_TYPE_MDATA) {
+ if ((one->len < sizeof(struct mdata_iatt)) ||
+ (two->len < sizeof(struct mdata_iatt))) {
+ return 0;
+ }
+ mdata_iatt1 = (struct mdata_iatt *)one->data;
+ mdata_iatt2 = (struct mdata_iatt *)two->data;
+
+ if (mdata_iatt1->ia_atime != mdata_iatt2->ia_atime ||
+ mdata_iatt1->ia_mtime != mdata_iatt2->ia_mtime ||
+ mdata_iatt1->ia_ctime != mdata_iatt2->ia_ctime ||
+ mdata_iatt1->ia_atime_nsec != mdata_iatt2->ia_atime_nsec ||
+ mdata_iatt1->ia_mtime_nsec != mdata_iatt2->ia_mtime_nsec ||
+ mdata_iatt1->ia_ctime_nsec != mdata_iatt2->ia_ctime_nsec) {
+ return 0;
+ }
+ return 1;
+ }
if (one->len != two->len)
return 0;
@@ -1078,6 +1097,7 @@ static char *data_type_name[GF_DATA_TYPE_MAX] = {
[GF_DATA_TYPE_PTR] = "pointer",
[GF_DATA_TYPE_GFUUID] = "gf-uuid",
[GF_DATA_TYPE_IATT] = "iatt",
+ [GF_DATA_TYPE_MDATA] = "mdata",
};
int64_t
@@ -2666,6 +2686,45 @@ err:
}
int
+dict_set_mdata(dict_t *this, char *key, struct mdata_iatt *mdata,
+ bool is_static)
+{
+ return dict_set_bin_common(this, key, mdata, sizeof(struct mdata_iatt),
+ is_static, GF_DATA_TYPE_MDATA);
+}
+
+int
+dict_get_mdata(dict_t *this, char *key, struct mdata_iatt *mdata)
+{
+ data_t *data = NULL;
+ int ret = -EINVAL;
+
+ if (!this || !key || !mdata) {
+ goto err;
+ }
+ ret = dict_get_with_ref(this, key, &data);
+ if (ret < 0) {
+ goto err;
+ }
+
+ VALIDATE_DATA_AND_LOG(data, GF_DATA_TYPE_MDATA, key, -EINVAL);
+ if (data->len < sizeof(struct mdata_iatt)) {
+ gf_msg("glusterfs", GF_LOG_ERROR, ENOBUFS, LG_MSG_UNDERSIZED_BUF,
+ "data value for '%s' is smaller than expected", key);
+ ret = -ENOBUFS;
+ goto err;
+ }
+
+ memcpy(mdata, data->data, min(data->len, sizeof(struct mdata_iatt)));
+
+err:
+ if (data)
+ data_unref(data);
+
+ return ret;
+}
+
+int
dict_set_iatt(dict_t *this, char *key, struct iatt *iatt, bool is_static)
{
return dict_set_bin_common(this, key, iatt, sizeof(struct iatt), is_static,
diff --git a/libglusterfs/src/glusterfs/dict.h b/libglusterfs/src/glusterfs/dict.h
index 52b833fd559..c8ea9c1bc0b 100644
--- a/libglusterfs/src/glusterfs/dict.h
+++ b/libglusterfs/src/glusterfs/dict.h
@@ -389,6 +389,11 @@ GF_MUST_CHECK int
dict_set_iatt(dict_t *this, char *key, struct iatt *iatt, bool is_static);
GF_MUST_CHECK int
dict_get_iatt(dict_t *this, char *key, struct iatt *iatt);
+GF_MUST_CHECK int
+dict_set_mdata(dict_t *this, char *key, struct mdata_iatt *mdata,
+ bool is_static);
+GF_MUST_CHECK int
+dict_get_mdata(dict_t *this, char *key, struct mdata_iatt *mdata);
void
dict_dump_to_statedump(dict_t *dict, char *dict_name, char *domain);
diff --git a/libglusterfs/src/glusterfs/glusterfs.h b/libglusterfs/src/glusterfs/glusterfs.h
index 3056a61d9af..cded97835a6 100644
--- a/libglusterfs/src/glusterfs/glusterfs.h
+++ b/libglusterfs/src/glusterfs/glusterfs.h
@@ -229,6 +229,9 @@ enum gf_internal_fop_indicator {
#define VIRTUAL_QUOTA_XATTR_CLEANUP_KEY "glusterfs.quota-xattr-cleanup"
#define QUOTA_READ_ONLY_KEY "trusted.glusterfs.quota.read-only"
+/* ctime related */
+#define CTIME_MDATA_XDATA_KEY "set-ctime-mdata"
+
/* afr related */
#define AFR_XATTR_PREFIX "trusted.afr"
diff --git a/libglusterfs/src/glusterfs/iatt.h b/libglusterfs/src/glusterfs/iatt.h
index bee7a0afa77..f03d68b02f0 100644
--- a/libglusterfs/src/glusterfs/iatt.h
+++ b/libglusterfs/src/glusterfs/iatt.h
@@ -92,6 +92,15 @@ struct old_iatt {
uint32_t ia_ctime_nsec;
};
+struct mdata_iatt {
+ int64_t ia_atime; /* last access time */
+ int64_t ia_mtime; /* last modification time */
+ int64_t ia_ctime; /* last status change time */
+ uint32_t ia_atime_nsec;
+ uint32_t ia_mtime_nsec;
+ uint32_t ia_ctime_nsec;
+};
+
/* 64-bit mask for valid members in struct iatt. */
#define IATT_TYPE 0x0000000000000001U
#define IATT_MODE 0x0000000000000002U
@@ -313,6 +322,17 @@ st_mode_from_ia(ia_prot_t prot, ia_type_t type)
return st_mode;
}
+static inline void
+iatt_to_mdata(struct mdata_iatt *mdata, struct iatt *iatt)
+{
+ mdata->ia_atime = iatt->ia_atime;
+ mdata->ia_atime_nsec = iatt->ia_atime_nsec;
+ mdata->ia_mtime = iatt->ia_mtime;
+ mdata->ia_mtime_nsec = iatt->ia_mtime_nsec;
+ mdata->ia_ctime = iatt->ia_ctime;
+ mdata->ia_ctime_nsec = iatt->ia_ctime_nsec;
+}
+
static inline int
iatt_from_stat(struct iatt *iatt, struct stat *stat)
{
diff --git a/libglusterfs/src/libglusterfs.sym b/libglusterfs/src/libglusterfs.sym
index 3a548305dd8..6a10af86a23 100644
--- a/libglusterfs/src/libglusterfs.sym
+++ b/libglusterfs/src/libglusterfs.sym
@@ -380,6 +380,7 @@ dict_get_bin
dict_get_double
dict_get_gfuuid
dict_get_iatt
+dict_get_mdata
dict_get_int16
dict_get_int32
dict_get_int32n
@@ -416,6 +417,7 @@ dict_set_dynstrn
dict_set_dynstr_with_alloc
dict_set_gfuuid
dict_set_iatt
+dict_set_mdata
dict_set_int16
dict_set_int32
dict_set_int32n
@@ -508,6 +510,7 @@ fop_lease_stub
fop_link_stub
fop_lk_stub
fop_log_level
+fop_lookup_cbk_stub
fop_lookup_stub
fop_mkdir_stub
fop_mknod_stub