From a3c380c78512200838740cbc11770b87e01a6a81 Mon Sep 17 00:00:00 2001 From: Sunil Kumar Acharya Date: Tue, 23 Jul 2019 12:15:46 -0400 Subject: [PATCH] autobuild v6.0-9 Resolves: bz#1708064 bz#1708180 bz#1715422 bz#1720992 bz#1722757 Signed-off-by: Sunil Kumar Acharya --- ...w-server-use-the-same-volfile-server.patch | 117 +++ ...-Test-case-for-upgrading-config-file.patch | 80 ++ ...geo-rep-Fix-mount-broker-setup-issue.patch | 53 ++ 0259-gluster-block-tuning-perf-options.patch | 47 + ...time-Set-mdata-xattr-on-legacy-files.patch | 885 ++++++++++++++++++ 0261-features-utime-Fix-mem_put-crash.patch | 52 + glusterfs.spec | 11 +- 7 files changed, 1244 insertions(+), 1 deletion(-) create mode 100644 0256-features-snapview-server-use-the-same-volfile-server.patch create mode 100644 0257-geo-rep-Test-case-for-upgrading-config-file.patch create mode 100644 0258-geo-rep-Fix-mount-broker-setup-issue.patch create mode 100644 0259-gluster-block-tuning-perf-options.patch create mode 100644 0260-ctime-Set-mdata-xattr-on-legacy-files.patch create mode 100644 0261-features-utime-Fix-mem_put-crash.patch diff --git a/0256-features-snapview-server-use-the-same-volfile-server.patch b/0256-features-snapview-server-use-the-same-volfile-server.patch new file mode 100644 index 0000000..d410373 --- /dev/null +++ b/0256-features-snapview-server-use-the-same-volfile-server.patch @@ -0,0 +1,117 @@ +From f90df1167bc70c634ba33c181232321da6770709 Mon Sep 17 00:00:00 2001 +From: Raghavendra Bhat +Date: Tue, 25 Jun 2019 10:51:33 -0400 +Subject: [PATCH 256/261] features/snapview-server: use the same volfile server + for gfapi options + +snapview server xlator makes use of "localhost" as the volfile server while +initing the new glfs instance to talk to a snapshot. While localhost is fine, +better use the same volfile server that was used to start the snapshot +daemon containing the snapview-server xlator. + +Upstream Patch: +>Change-Id: I4485d39b0e3d066f481adc6958ace53ea33237f7 +>fixes: bz#1725211 +>Signed-off-by: Raghavendra Bhat +> patch: https://review.gluster.org/#/c/glusterfs/+/22974/ + +BUG: 1722757 +Change-Id: I4485d39b0e3d066f481adc6958ace53ea33237f7 +Signed-off-by: Raghavendra Bhat +Reviewed-on: https://code.engineering.redhat.com/gerrit/175984 +Tested-by: RHGS Build Bot +Reviewed-by: Sunil Kumar Heggodu Gopala Acharya +--- + .../snapview-server/src/snapview-server-helpers.c | 44 ++++++++++++++++++++-- + .../snapview-server/src/snapview-server-messages.h | 2 +- + 2 files changed, 42 insertions(+), 4 deletions(-) + +diff --git a/xlators/features/snapview-server/src/snapview-server-helpers.c b/xlators/features/snapview-server/src/snapview-server-helpers.c +index 5514a54..62c1dda 100644 +--- a/xlators/features/snapview-server/src/snapview-server-helpers.c ++++ b/xlators/features/snapview-server/src/snapview-server-helpers.c +@@ -476,6 +476,7 @@ __svs_initialise_snapshot_volume(xlator_t *this, const char *name, + char logfile[PATH_MAX] = { + 0, + }; ++ char *volfile_server = NULL; + + GF_VALIDATE_OR_GOTO("snapview-server", this, out); + GF_VALIDATE_OR_GOTO(this->name, this->private, out); +@@ -512,14 +513,50 @@ __svs_initialise_snapshot_volume(xlator_t *this, const char *name, + goto out; + } + +- ret = glfs_set_volfile_server(fs, "tcp", "localhost", 24007); ++ /* ++ * Before, localhost was used as the volfile server. But, with that ++ * method, accessing snapshots started giving ENOENT error if a ++ * specific bind address is mentioned in the glusterd volume file. ++ * Check the bug https://bugzilla.redhat.com/show_bug.cgi?id=1725211. ++ * So, the new method is tried below, where, snapview-server first ++ * uses the volfile server used by the snapd (obtained from the ++ * command line arguments saved in the global context of the process). ++ * If the volfile server in global context is NULL, then localhost ++ * is tried (like before). ++ */ ++ if (this->ctx->cmd_args.volfile_server) { ++ volfile_server = gf_strdup(this->ctx->cmd_args.volfile_server); ++ if (!volfile_server) { ++ gf_msg(this->name, GF_LOG_WARNING, ENOMEM, ++ SVS_MSG_VOLFILE_SERVER_GET_FAIL, ++ "failed to copy volfile server %s. ", ++ this->ctx->cmd_args.volfile_server); ++ ret = -1; ++ goto out; ++ } ++ } else { ++ gf_msg(this->name, GF_LOG_WARNING, ENOMEM, ++ SVS_MSG_VOLFILE_SERVER_GET_FAIL, ++ "volfile server is NULL in cmd args. " ++ "Trying with localhost"); ++ volfile_server = gf_strdup("localhost"); ++ if (!volfile_server) { ++ gf_msg(this->name, GF_LOG_WARNING, ENOMEM, ++ SVS_MSG_VOLFILE_SERVER_GET_FAIL, ++ "failed to copy volfile server localhost."); ++ ret = -1; ++ goto out; ++ } ++ } ++ ++ ret = glfs_set_volfile_server(fs, "tcp", volfile_server, 24007); + if (ret) { + gf_msg(this->name, GF_LOG_ERROR, local_errno, + SVS_MSG_SET_VOLFILE_SERVR_FAILED, + "setting the " +- "volfile server for snap volume %s " ++ "volfile server %s for snap volume %s " + "failed", +- dirent->name); ++ volfile_server, dirent->name); + goto out; + } + +@@ -561,6 +598,7 @@ out: + dirent->fs = fs; + } + ++ GF_FREE(volfile_server); + return fs; + } + +diff --git a/xlators/features/snapview-server/src/snapview-server-messages.h b/xlators/features/snapview-server/src/snapview-server-messages.h +index 8548015..f634ab5 100644 +--- a/xlators/features/snapview-server/src/snapview-server-messages.h ++++ b/xlators/features/snapview-server/src/snapview-server-messages.h +@@ -49,6 +49,6 @@ GLFS_MSGID(SNAPVIEW_SERVER, SVS_MSG_NO_MEMORY, SVS_MSG_MEM_ACNT_FAILED, + SVS_MSG_CLOSEDIR_FAILED, SVS_MSG_CLOSE_FAILED, + SVS_MSG_GFID_GEN_FAILED, SVS_MSG_GLFS_NEW_FAILED, + SVS_MSG_SET_VOLFILE_SERVR_FAILED, SVS_MSG_SET_LOGGING_FAILED, +- SVS_MSG_GLFS_INIT_FAILED); ++ SVS_MSG_VOLFILE_SERVER_GET_FAIL, SVS_MSG_GLFS_INIT_FAILED); + + #endif /* !_SNAPVIEW_CLIENT_MESSAGES_H_ */ +-- +1.8.3.1 + diff --git a/0257-geo-rep-Test-case-for-upgrading-config-file.patch b/0257-geo-rep-Test-case-for-upgrading-config-file.patch new file mode 100644 index 0000000..ffe44f1 --- /dev/null +++ b/0257-geo-rep-Test-case-for-upgrading-config-file.patch @@ -0,0 +1,80 @@ +From ed6cd2b7674896c810fdd059e35a0d319aacb068 Mon Sep 17 00:00:00 2001 +From: Shwetha K Acharya +Date: Tue, 2 Jul 2019 15:00:25 +0530 +Subject: [PATCH 257/261] geo-rep: Test case for upgrading config file + +Added test case for the patch +https://review.gluster.org/#/c/glusterfs/+/22894/4 + +Also updated if else structure in gsyncdconfig.py to avoid +repeated occurance of values in new configfile. + +>fixes: bz#1707731 +>Change-Id: If97e1d37ac52dbd17d47be6cb659fc5a3ccab6d7 +>Signed-off-by: Shwetha K Acharya + +backport of https://review.gluster.org/#/c/glusterfs/+/22982/ + +Bug: 1708064 +Change-Id: If97e1d37ac52dbd17d47be6cb659fc5a3ccab6d7 +Signed-off-by: Shwetha K Acharya +Reviewed-on: https://code.engineering.redhat.com/gerrit/176603 +Tested-by: RHGS Build Bot +Reviewed-by: Sunil Kumar Heggodu Gopala Acharya +--- + geo-replication/syncdaemon/gsyncdconfig.py | 11 +++++------ + tests/00-geo-rep/georep-basic-dr-rsync.t | 13 +++++++++++++ + 2 files changed, 18 insertions(+), 6 deletions(-) + +diff --git a/geo-replication/syncdaemon/gsyncdconfig.py b/geo-replication/syncdaemon/gsyncdconfig.py +index 7edc582..1fc451f 100644 +--- a/geo-replication/syncdaemon/gsyncdconfig.py ++++ b/geo-replication/syncdaemon/gsyncdconfig.py +@@ -353,15 +353,14 @@ def config_upgrade(config_file, ret): + new_value = "tarssh" + else: + new_value = "rsync" +- config.set('vars', new_key, new_value) +- +- if key == "timeout": ++ config.set('vars', new_key, new_value) ++ elif key == "timeout": + new_key = "slave-timeout" + config.set('vars', new_key, value) +- + #for changes like: ignore_deletes to ignore-deletes +- new_key = key.replace("_", "-") +- config.set('vars', new_key, value) ++ else: ++ new_key = key.replace("_", "-") ++ config.set('vars', new_key, value) + + with open(config_file, 'w') as configfile: + config.write(configfile) +diff --git a/tests/00-geo-rep/georep-basic-dr-rsync.t b/tests/00-geo-rep/georep-basic-dr-rsync.t +index 428e9ed..b432635 100644 +--- a/tests/00-geo-rep/georep-basic-dr-rsync.t ++++ b/tests/00-geo-rep/georep-basic-dr-rsync.t +@@ -212,6 +212,19 @@ EXPECT_WITHIN $GEO_REP_TIMEOUT 0 verify_rename_with_existing_destination ${slave + #Verify arequal for whole volume + EXPECT_WITHIN $GEO_REP_TIMEOUT "x0" arequal_checksum ${master_mnt} ${slave_mnt} + ++#Test config upgrade BUG: 1707731 ++config_file=$GLUSTERD_WORKDIR/geo-replication/${GMV0}_${SH0}_${GSV0}/gsyncd.conf ++cat >> $config_file< +Date: Mon, 22 Jul 2019 17:35:21 +0530 +Subject: [PATCH 258/261] geo-rep: Fix mount broker setup issue + +The patch [1] added validation in gverify.sh to check if the gluster +binary on slave by executing gluster directly on slave. But for +non-root users, even though gluster binary is present, path is not +found when executed via ssh. Hence validate the gluster binary using +bash builtin 'type' command. + +[1] https://review.gluster.org/19224 + +Backport of: + > Patch: https://review.gluster.org/23089 + > Change-Id: I93ca62c0c5b1e16263e586ddbbca8407d60ca126 + > fixes: bz#1731920 + > Signed-off-by: Kotresh HR + +Change-Id: I93ca62c0c5b1e16263e586ddbbca8407d60ca126 +BUG: 1720992 +Signed-off-by: Kotresh HR +Reviewed-on: https://code.engineering.redhat.com/gerrit/176727 +Tested-by: RHGS Build Bot +Reviewed-by: Atin Mukherjee +--- + geo-replication/src/gverify.sh | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/geo-replication/src/gverify.sh b/geo-replication/src/gverify.sh +index 7c88f9f..692c1d6 100755 +--- a/geo-replication/src/gverify.sh ++++ b/geo-replication/src/gverify.sh +@@ -207,13 +207,13 @@ function main() + fi; + + if [[ -z "${GR_SSH_IDENTITY_KEY}" ]]; then +- err=$((ssh -p ${SSH_PORT} -oNumberOfPasswordPrompts=0 -oStrictHostKeyChecking=no $2@$3 "gluster --version") 2>&1) ++ ssh -p ${SSH_PORT} -oNumberOfPasswordPrompts=0 -oStrictHostKeyChecking=no $2@$3 "type -p gluster" + else +- err=$((ssh -p ${SSH_PORT} -i ${GR_SSH_IDENTITY_KEY} -oNumberOfPasswordPrompts=0 -oStrictHostKeyChecking=no $2@$3 "gluster --version") 2>&1) ++ ssh -p ${SSH_PORT} -i ${GR_SSH_IDENTITY_KEY} -oNumberOfPasswordPrompts=0 -oStrictHostKeyChecking=no $2@$3 "type -p gluster" + fi + + if [ $? -ne 0 ]; then +- echo "FORCE_BLOCKER|gluster command on $2@$3 failed. Error: $err" > $log_file ++ echo "FORCE_BLOCKER|gluster command not found on $3 for user $2." > $log_file + exit 1; + fi; + +-- +1.8.3.1 + diff --git a/0259-gluster-block-tuning-perf-options.patch b/0259-gluster-block-tuning-perf-options.patch new file mode 100644 index 0000000..a8ef9f4 --- /dev/null +++ b/0259-gluster-block-tuning-perf-options.patch @@ -0,0 +1,47 @@ +From 775a62906030e5b5dc60f17284a7d516ce4118f9 Mon Sep 17 00:00:00 2001 +From: Prasanna Kumar Kalever +Date: Thu, 27 Jun 2019 13:18:32 +0530 +Subject: [PATCH 259/261] gluster-block: tuning perf options + +As per the perf experiment run by Elvir, with NVME devices used for OCP (gluster) +it was seen that particularly read operations (read/randread) benefited from +these options. + +> upstream patch : https://review.gluster.org/#/c/glusterfs/+/22963/ + +>Change-Id: Ibec4b96afd28e6f7e757b6ef203ccdbc0d9854d5 +>Fixes: bz#1727852 +>Signed-off-by: Prasanna Kumar Kalever + +Change-Id: Ibec4b96afd28e6f7e757b6ef203ccdbc0d9854d5 +BUG: 1708180 +Signed-off-by: Prasanna Kumar Kalever +Reviewed-on: https://code.engineering.redhat.com/gerrit/176724 +Tested-by: RHGS Build Bot +Reviewed-by: Atin Mukherjee +--- + extras/group-gluster-block | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/extras/group-gluster-block b/extras/group-gluster-block +index 56b406e..1e39801 100644 +--- a/extras/group-gluster-block ++++ b/extras/group-gluster-block +@@ -5,6 +5,14 @@ performance.stat-prefetch=off + performance.open-behind=off + performance.readdir-ahead=off + performance.strict-o-direct=on ++performance.client-io-threads=on ++performance.io-thread-count=32 ++performance.high-prio-threads=32 ++performance.normal-prio-threads=32 ++performance.low-prio-threads=32 ++performance.least-prio-threads=4 ++client.event-threads=8 ++server.event-threads=8 + network.remote-dio=disable + cluster.eager-lock=enable + cluster.quorum-type=auto +-- +1.8.3.1 + diff --git a/0260-ctime-Set-mdata-xattr-on-legacy-files.patch b/0260-ctime-Set-mdata-xattr-on-legacy-files.patch new file mode 100644 index 0000000..f07fb21 --- /dev/null +++ b/0260-ctime-Set-mdata-xattr-on-legacy-files.patch @@ -0,0 +1,885 @@ +From fc0903de1f7565e06db9d41e6dfd62221a745d24 Mon Sep 17 00:00:00 2001 +From: Kotresh HR +Date: Mon, 24 Jun 2019 13:06:49 +0530 +Subject: [PATCH 260/261] 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 + > fixes: bz#1593542 + +Change-Id: I5e535631ddef04195361ae0364336410a2895dd4 +BUG: 1715422 +Signed-off-by: Kotresh HR +Reviewed-on: https://code.engineering.redhat.com/gerrit/176725 +Tested-by: RHGS Build Bot +Reviewed-by: Amar Tumballi Suryanarayan +Reviewed-by: Atin Mukherjee +--- + libglusterfs/src/dict.c | 59 ++++++++++ + libglusterfs/src/glusterfs/dict.h | 5 + + libglusterfs/src/glusterfs/glusterfs.h | 3 + + libglusterfs/src/glusterfs/iatt.h | 20 ++++ + libglusterfs/src/libglusterfs.sym | 3 + + rpc/xdr/src/glusterfs-fops.x | 1 + + rpc/xdr/src/glusterfs3.h | 59 ++++++++++ + rpc/xdr/src/glusterfs4-xdr.x | 12 ++ + rpc/xdr/src/libgfxdr.sym | 3 +- + tests/basic/ctime/ctime-mdata-legacy-files.t | 83 +++++++++++++ + xlators/features/utime/src/utime-messages.h | 3 +- + xlators/features/utime/src/utime.c | 154 ++++++++++++++++++++++--- + xlators/storage/posix/src/posix-inode-fd-ops.c | 17 +++ + xlators/storage/posix/src/posix-messages.h | 3 +- + xlators/storage/posix/src/posix-metadata.c | 103 ++++++++++------- + xlators/storage/posix/src/posix-metadata.h | 4 + + 16 files changed, 475 insertions(+), 57 deletions(-) + create mode 100644 tests/basic/ctime/ctime-mdata-legacy-files.t + +diff --git a/libglusterfs/src/dict.c b/libglusterfs/src/dict.c +index 6917df9..d8cdda4 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 022f564..8239c7a 100644 +--- a/libglusterfs/src/glusterfs/dict.h ++++ b/libglusterfs/src/glusterfs/dict.h +@@ -392,6 +392,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 2cedf1a..79c93ae 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 bee7a0a..f03d68b 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 4dca7de..b161380 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 +@@ -417,6 +418,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 +@@ -509,6 +511,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 +diff --git a/rpc/xdr/src/glusterfs-fops.x b/rpc/xdr/src/glusterfs-fops.x +index bacf0773..651f8de 100644 +--- a/rpc/xdr/src/glusterfs-fops.x ++++ b/rpc/xdr/src/glusterfs-fops.x +@@ -245,5 +245,6 @@ enum gf_dict_data_type_t { + GF_DATA_TYPE_PTR, + GF_DATA_TYPE_GFUUID, + GF_DATA_TYPE_IATT, ++ GF_DATA_TYPE_MDATA, + GF_DATA_TYPE_MAX + }; +diff --git a/rpc/xdr/src/glusterfs3.h b/rpc/xdr/src/glusterfs3.h +index 5521f4d..86b3a4c 100644 +--- a/rpc/xdr/src/glusterfs3.h ++++ b/rpc/xdr/src/glusterfs3.h +@@ -585,6 +585,34 @@ out: + } + + static inline void ++gfx_mdata_iatt_to_mdata_iatt(struct gfx_mdata_iatt *gf_mdata_iatt, ++ struct mdata_iatt *mdata_iatt) ++{ ++ if (!mdata_iatt || !gf_mdata_iatt) ++ return; ++ mdata_iatt->ia_atime = gf_mdata_iatt->ia_atime; ++ mdata_iatt->ia_atime_nsec = gf_mdata_iatt->ia_atime_nsec; ++ mdata_iatt->ia_mtime = gf_mdata_iatt->ia_mtime; ++ mdata_iatt->ia_mtime_nsec = gf_mdata_iatt->ia_mtime_nsec; ++ mdata_iatt->ia_ctime = gf_mdata_iatt->ia_ctime; ++ mdata_iatt->ia_ctime_nsec = gf_mdata_iatt->ia_ctime_nsec; ++} ++ ++static inline void ++gfx_mdata_iatt_from_mdata_iatt(struct gfx_mdata_iatt *gf_mdata_iatt, ++ struct mdata_iatt *mdata_iatt) ++{ ++ if (!mdata_iatt || !gf_mdata_iatt) ++ return; ++ gf_mdata_iatt->ia_atime = mdata_iatt->ia_atime; ++ gf_mdata_iatt->ia_atime_nsec = mdata_iatt->ia_atime_nsec; ++ gf_mdata_iatt->ia_mtime = mdata_iatt->ia_mtime; ++ gf_mdata_iatt->ia_mtime_nsec = mdata_iatt->ia_mtime_nsec; ++ gf_mdata_iatt->ia_ctime = mdata_iatt->ia_ctime; ++ gf_mdata_iatt->ia_ctime_nsec = mdata_iatt->ia_ctime_nsec; ++} ++ ++static inline void + gfx_stat_to_iattx(struct gfx_iattx *gf_stat, struct iatt *iatt) + { + if (!iatt || !gf_stat) +@@ -721,6 +749,12 @@ dict_to_xdr(dict_t *this, gfx_dict *dict) + gfx_stat_from_iattx(&xpair->value.gfx_value_u.iatt, + (struct iatt *)dpair->value->data); + break; ++ case GF_DATA_TYPE_MDATA: ++ index++; ++ gfx_mdata_iatt_from_mdata_iatt( ++ &xpair->value.gfx_value_u.mdata_iatt, ++ (struct mdata_iatt *)dpair->value->data); ++ break; + case GF_DATA_TYPE_GFUUID: + index++; + memcpy(&xpair->value.gfx_value_u.uuid, dpair->value->data, +@@ -787,6 +821,7 @@ xdr_to_dict(gfx_dict *dict, dict_t **to) + dict_t *this = NULL; + unsigned char *uuid = NULL; + struct iatt *iatt = NULL; ++ struct mdata_iatt *mdata_iatt = NULL; + + if (!to || !dict) + goto out; +@@ -854,6 +889,30 @@ xdr_to_dict(gfx_dict *dict, dict_t **to) + gfx_stat_to_iattx(&xpair->value.gfx_value_u.iatt, iatt); + ret = dict_set_iatt(this, key, iatt, false); + break; ++ case GF_DATA_TYPE_MDATA: ++ mdata_iatt = GF_CALLOC(1, sizeof(struct mdata_iatt), ++ gf_common_mt_char); ++ if (!mdata_iatt) { ++ errno = ENOMEM; ++ gf_msg(THIS->name, GF_LOG_ERROR, ENOMEM, LG_MSG_NO_MEMORY, ++ "failed to allocate memory. key: %s", key); ++ ret = -1; ++ goto out; ++ } ++ gfx_mdata_iatt_to_mdata_iatt( ++ &xpair->value.gfx_value_u.mdata_iatt, mdata_iatt); ++ ret = dict_set_mdata(this, key, mdata_iatt, false); ++ if (ret != 0) { ++ GF_FREE(mdata_iatt); ++ gf_msg(THIS->name, GF_LOG_ERROR, ENOMEM, ++ LG_MSG_DICT_SET_FAILED, ++ "failed to set the key (%s)" ++ " into dict", ++ key); ++ ret = -1; ++ goto out; ++ } ++ break; + case GF_DATA_TYPE_PTR: + case GF_DATA_TYPE_STR_OLD: + value = GF_MALLOC(xpair->value.gfx_value_u.other.other_len + 1, +diff --git a/rpc/xdr/src/glusterfs4-xdr.x b/rpc/xdr/src/glusterfs4-xdr.x +index bec0872..6f92b70 100644 +--- a/rpc/xdr/src/glusterfs4-xdr.x ++++ b/rpc/xdr/src/glusterfs4-xdr.x +@@ -46,6 +46,16 @@ struct gfx_iattx { + unsigned int mode; /* type of file and rwx mode */ + }; + ++struct gfx_mdata_iatt { ++ hyper ia_atime; /* last access time */ ++ hyper ia_mtime; /* last modification time */ ++ hyper ia_ctime; /* last status change time */ ++ ++ unsigned int ia_atime_nsec; ++ unsigned int ia_mtime_nsec; ++ unsigned int ia_ctime_nsec; ++}; ++ + union gfx_value switch (gf_dict_data_type_t type) { + case GF_DATA_TYPE_INT: + hyper value_int; +@@ -62,6 +72,8 @@ union gfx_value switch (gf_dict_data_type_t type) { + case GF_DATA_TYPE_PTR: + case GF_DATA_TYPE_STR_OLD: + opaque other<>; ++ case GF_DATA_TYPE_MDATA: ++ gfx_mdata_iatt mdata_iatt; + }; + + /* AUTH */ +diff --git a/rpc/xdr/src/libgfxdr.sym b/rpc/xdr/src/libgfxdr.sym +index 22cdf30..dd4ac85 100644 +--- a/rpc/xdr/src/libgfxdr.sym ++++ b/rpc/xdr/src/libgfxdr.sym +@@ -251,6 +251,7 @@ xdr_to_write3args + xdr_vector_round_up + xdr_gfx_read_rsp + xdr_gfx_iattx ++xdr_gfx_mdata_iatt + xdr_gfx_value + xdr_gfx_dict_pair + xdr_gfx_dict +@@ -344,4 +345,4 @@ xdr_compound_req_v2 + xdr_gfx_compound_req + xdr_compound_rsp_v2 + xdr_gfx_compound_rsp +-xdr_gfx_copy_file_range_req +\ No newline at end of file ++xdr_gfx_copy_file_range_req +diff --git a/tests/basic/ctime/ctime-mdata-legacy-files.t b/tests/basic/ctime/ctime-mdata-legacy-files.t +new file mode 100644 +index 0000000..2e782d5 +--- /dev/null ++++ b/tests/basic/ctime/ctime-mdata-legacy-files.t +@@ -0,0 +1,83 @@ ++#!/bin/bash ++. $(dirname $0)/../../include.rc ++. $(dirname $0)/../../volume.rc ++. $(dirname $0)/../../afr.rc ++cleanup; ++ ++############################################################################### ++#Replica volume ++ ++TEST glusterd ++TEST pidof glusterd ++TEST $CLI volume create $V0 replica 3 $H0:$B0/${V0}{0,1,2} ++TEST $CLI volume set $V0 performance.stat-prefetch off ++TEST $CLI volume start $V0 ++ ++TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 --entry-timeout=0 $M0; ++ ++#Disable ctime and create file, file doesn't contain "trusted.glusterfs.mdata" xattr ++TEST $CLI volume set $V0 ctime off ++ ++TEST "mkdir $M0/DIR" ++TEST "echo hello_world > $M0/DIR/FILE" ++ ++#Verify absence of xattr ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}0/DIR" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}0/DIR/FILE" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}1/DIR" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}1/DIR/FILE" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}2/DIR" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}2/DIR/FILE" ++ ++#Enable ctime ++TEST $CLI volume set $V0 ctime on ++sleep 3 ++TEST stat $M0/DIR/FILE ++ ++#Verify presence "trusted.glusterfs.mdata" xattr on backend ++#The lookup above should have created xattr ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}0/DIR" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}0/DIR/FILE" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}1/DIR" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}1/DIR/FILE" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}2/DIR" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V0}2/DIR/FILE" ++ ++############################################################################### ++#Disperse Volume ++ ++TEST $CLI volume create $V1 disperse 3 redundancy 1 $H0:$B0/${V1}{0,1,2} ++TEST $CLI volume set $V1 performance.stat-prefetch off ++TEST $CLI volume start $V1 ++ ++TEST glusterfs --volfile-id=$V1 --volfile-server=$H0 --entry-timeout=0 $M1; ++ ++#Disable ctime and create file, file doesn't contain "trusted.glusterfs.mdata" xattr ++TEST $CLI volume set $V1 ctime off ++TEST "mkdir $M1/DIR" ++TEST "echo hello_world > $M1/DIR/FILE" ++ ++#Verify absence of xattr ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}0/DIR" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}0/DIR/FILE" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}1/DIR" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}1/DIR/FILE" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}2/DIR" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT "" check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}2/DIR/FILE" ++ ++#Enable ctime ++TEST $CLI volume set $V1 ctime on ++sleep 3 ++TEST stat $M1/DIR/FILE ++ ++#Verify presence "trusted.glusterfs.mdata" xattr on backend ++#The lookup above should have created xattr ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}0/DIR" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}0/DIR/FILE" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}1/DIR" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}1/DIR/FILE" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}2/DIR" ++EXPECT_WITHIN $PROCESS_UP_TIMEOUT 'trusted.glusterfs.mdata' check_for_xattr 'trusted.glusterfs.mdata' "$B0/${V1}2/DIR/FILE" ++ ++cleanup; ++############################################################################### +diff --git a/xlators/features/utime/src/utime-messages.h b/xlators/features/utime/src/utime-messages.h +index bac18ab..bd40265 100644 +--- a/xlators/features/utime/src/utime-messages.h ++++ b/xlators/features/utime/src/utime-messages.h +@@ -23,6 +23,7 @@ + * glfs-message-id.h. + */ + +-GLFS_MSGID(UTIME, UTIME_MSG_NO_MEMORY); ++GLFS_MSGID(UTIME, UTIME_MSG_NO_MEMORY, UTIME_MSG_SET_MDATA_FAILED, ++ UTIME_MSG_DICT_SET_FAILED); + + #endif /* __UTIME_MESSAGES_H__ */ +diff --git a/xlators/features/utime/src/utime.c b/xlators/features/utime/src/utime.c +index 877c751..2a986e7 100644 +--- a/xlators/features/utime/src/utime.c ++++ b/xlators/features/utime/src/utime.c +@@ -9,8 +9,10 @@ + */ + + #include "utime.h" ++#include "utime-helpers.h" + #include "utime-messages.h" + #include "utime-mem-types.h" ++#include + + int32_t + gf_utime_invalidate(xlator_t *this, inode_t *inode) +@@ -133,6 +135,124 @@ mem_acct_init(xlator_t *this) + } + + int32_t ++gf_utime_set_mdata_setxattr_cbk(call_frame_t *frame, void *cookie, ++ xlator_t *this, int op_ret, int op_errno, ++ dict_t *xdata) ++{ ++ /* Don't fail lookup if mdata setxattr fails */ ++ if (op_ret) { ++ gf_msg(this->name, GF_LOG_ERROR, op_errno, UTIME_MSG_SET_MDATA_FAILED, ++ "dict set of key for set-ctime-mdata failed"); ++ } ++ call_resume(frame->local); ++ return 0; ++} ++ ++int32_t ++gf_utime_set_mdata_lookup_cbk(call_frame_t *frame, void *cookie, xlator_t *this, ++ int32_t op_ret, int32_t op_errno, inode_t *inode, ++ struct iatt *stbuf, dict_t *xdata, ++ struct iatt *postparent) ++{ ++ dict_t *dict = NULL; ++ struct mdata_iatt *mdata = NULL; ++ int ret = 0; ++ loc_t loc = { ++ 0, ++ }; ++ ++ if (!op_ret && dict_get(xdata, GF_XATTR_MDATA_KEY) == NULL) { ++ dict = dict_new(); ++ if (!dict) { ++ op_errno = ENOMEM; ++ goto err; ++ } ++ mdata = GF_MALLOC(sizeof(struct mdata_iatt), gf_common_mt_char); ++ if (mdata == NULL) { ++ op_errno = ENOMEM; ++ goto err; ++ } ++ iatt_to_mdata(mdata, stbuf); ++ ret = dict_set_mdata(dict, CTIME_MDATA_XDATA_KEY, mdata, _gf_false); ++ if (ret < 0) { ++ gf_msg(this->name, GF_LOG_WARNING, ENOMEM, UTIME_MSG_NO_MEMORY, ++ "dict set of key for set-ctime-mdata failed"); ++ goto err; ++ } ++ frame->local = fop_lookup_cbk_stub(frame, default_lookup_cbk, op_ret, ++ op_errno, inode, stbuf, xdata, ++ postparent); ++ if (!frame->local) { ++ gf_msg(this->name, GF_LOG_WARNING, ENOMEM, UTIME_MSG_NO_MEMORY, ++ "lookup_cbk stub allocation failed"); ++ goto stub_err; ++ } ++ ++ loc.inode = inode_ref(inode); ++ gf_uuid_copy(loc.gfid, stbuf->ia_gfid); ++ STACK_WIND(frame, gf_utime_set_mdata_setxattr_cbk, FIRST_CHILD(this), ++ FIRST_CHILD(this)->fops->setxattr, &loc, dict, 0, NULL); ++ ++ dict_unref(dict); ++ inode_unref(loc.inode); ++ return 0; ++ } ++ ++ STACK_UNWIND_STRICT(lookup, frame, op_ret, op_errno, inode, stbuf, xdata, ++ postparent); ++ return 0; ++ ++err: ++ if (mdata) { ++ GF_FREE(mdata); ++ } ++stub_err: ++ if (dict) { ++ dict_unref(dict); ++ } ++ STACK_UNWIND_STRICT(lookup, frame, -1, op_errno, NULL, NULL, NULL, NULL); ++ return 0; ++} ++ ++int ++gf_utime_lookup(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) ++{ ++ int op_errno = -1; ++ int ret = -1; ++ ++ VALIDATE_OR_GOTO(frame, err); ++ VALIDATE_OR_GOTO(this, err); ++ VALIDATE_OR_GOTO(loc, err); ++ VALIDATE_OR_GOTO(loc->inode, err); ++ ++ xdata = xdata ? dict_ref(xdata) : dict_new(); ++ if (!xdata) { ++ op_errno = ENOMEM; ++ goto err; ++ } ++ ++ ret = dict_set_int8(xdata, GF_XATTR_MDATA_KEY, 1); ++ if (ret < 0) { ++ gf_msg(this->name, GF_LOG_WARNING, -ret, UTIME_MSG_DICT_SET_FAILED, ++ "%s: Unable to set dict value for %s", loc->path, ++ GF_XATTR_MDATA_KEY); ++ op_errno = -ret; ++ goto free_dict; ++ } ++ ++ STACK_WIND(frame, gf_utime_set_mdata_lookup_cbk, FIRST_CHILD(this), ++ FIRST_CHILD(this)->fops->lookup, loc, xdata); ++ dict_unref(xdata); ++ return 0; ++ ++free_dict: ++ dict_unref(xdata); ++err: ++ STACK_UNWIND_STRICT(lookup, frame, -1, op_errno, NULL, NULL, NULL, NULL); ++ return 0; ++} ++ ++int32_t + init(xlator_t *this) + { + utime_priv_t *utime = NULL; +@@ -182,19 +302,27 @@ notify(xlator_t *this, int event, void *data, ...) + } + + struct xlator_fops fops = { +- /* TODO: Need to go through other fops and +- * check if they modify time attributes +- */ +- .rename = gf_utime_rename, .mknod = gf_utime_mknod, +- .readv = gf_utime_readv, .fremovexattr = gf_utime_fremovexattr, +- .open = gf_utime_open, .create = gf_utime_create, +- .mkdir = gf_utime_mkdir, .writev = gf_utime_writev, +- .rmdir = gf_utime_rmdir, .fallocate = gf_utime_fallocate, +- .truncate = gf_utime_truncate, .symlink = gf_utime_symlink, +- .zerofill = gf_utime_zerofill, .link = gf_utime_link, +- .ftruncate = gf_utime_ftruncate, .unlink = gf_utime_unlink, +- .setattr = gf_utime_setattr, .fsetattr = gf_utime_fsetattr, +- .opendir = gf_utime_opendir, .removexattr = gf_utime_removexattr, ++ .rename = gf_utime_rename, ++ .mknod = gf_utime_mknod, ++ .readv = gf_utime_readv, ++ .fremovexattr = gf_utime_fremovexattr, ++ .open = gf_utime_open, ++ .create = gf_utime_create, ++ .mkdir = gf_utime_mkdir, ++ .writev = gf_utime_writev, ++ .rmdir = gf_utime_rmdir, ++ .fallocate = gf_utime_fallocate, ++ .truncate = gf_utime_truncate, ++ .symlink = gf_utime_symlink, ++ .zerofill = gf_utime_zerofill, ++ .link = gf_utime_link, ++ .ftruncate = gf_utime_ftruncate, ++ .unlink = gf_utime_unlink, ++ .setattr = gf_utime_setattr, ++ .fsetattr = gf_utime_fsetattr, ++ .opendir = gf_utime_opendir, ++ .removexattr = gf_utime_removexattr, ++ .lookup = gf_utime_lookup, + }; + struct xlator_cbks cbks = { + .invalidate = gf_utime_invalidate, +diff --git a/xlators/storage/posix/src/posix-inode-fd-ops.c b/xlators/storage/posix/src/posix-inode-fd-ops.c +index ea3b69c..d22bbc2 100644 +--- a/xlators/storage/posix/src/posix-inode-fd-ops.c ++++ b/xlators/storage/posix/src/posix-inode-fd-ops.c +@@ -2625,6 +2625,9 @@ posix_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, + gf_cs_obj_state state = -1; + int i = 0; + int len; ++ struct mdata_iatt mdata_iatt = { ++ 0, ++ }; + + DECLARE_OLD_FS_ID_VAR; + SET_FS_ID(frame->root->uid, frame->root->gid); +@@ -2638,6 +2641,20 @@ posix_setxattr(call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *dict, + priv = this->private; + DISK_SPACE_CHECK_AND_GOTO(frame, priv, xdata, op_ret, op_errno, out); + ++ ret = dict_get_mdata(dict, CTIME_MDATA_XDATA_KEY, &mdata_iatt); ++ if (ret == 0) { ++ /* This is initiated by lookup when ctime feature is enabled to create ++ * "trusted.glusterfs.mdata" xattr if not present. These are the files ++ * which were created when ctime feature is disabled. ++ */ ++ ret = posix_set_mdata_xattr_legacy_files(this, loc->inode, &mdata_iatt, ++ &op_errno); ++ if (ret != 0) { ++ op_ret = -1; ++ } ++ goto out; ++ } ++ + MAKE_INODE_HANDLE(real_path, this, loc, NULL); + if (!real_path) { + op_ret = -1; +diff --git a/xlators/storage/posix/src/posix-messages.h b/xlators/storage/posix/src/posix-messages.h +index 3229275..15e23ff 100644 +--- a/xlators/storage/posix/src/posix-messages.h ++++ b/xlators/storage/posix/src/posix-messages.h +@@ -68,6 +68,7 @@ GLFS_MSGID(POSIX, P_MSG_XATTR_FAILED, P_MSG_NULL_GFID, P_MSG_FCNTL_FAILED, + P_MSG_FALLOCATE_FAILED, P_MSG_STOREMDATA_FAILED, + P_MSG_FETCHMDATA_FAILED, P_MSG_GETMDATA_FAILED, + P_MSG_SETMDATA_FAILED, P_MSG_FRESHFILE, P_MSG_MUTEX_FAILED, +- P_MSG_COPY_FILE_RANGE_FAILED, P_MSG_TIMER_DELETE_FAILED); ++ P_MSG_COPY_FILE_RANGE_FAILED, P_MSG_TIMER_DELETE_FAILED, ++ P_MSG_NOMEM); + + #endif /* !_GLUSTERD_MESSAGES_H_ */ +diff --git a/xlators/storage/posix/src/posix-metadata.c b/xlators/storage/posix/src/posix-metadata.c +index 5a5e6cd..647c0bb 100644 +--- a/xlators/storage/posix/src/posix-metadata.c ++++ b/xlators/storage/posix/src/posix-metadata.c +@@ -245,6 +245,10 @@ __posix_get_mdata_xattr(xlator_t *this, const char *real_path, int _fd, + if (ret == -1 || !mdata) { + mdata = GF_CALLOC(1, sizeof(posix_mdata_t), gf_posix_mt_mdata_attr); + if (!mdata) { ++ gf_msg(this->name, GF_LOG_ERROR, ENOMEM, P_MSG_NOMEM, ++ "Could not allocate mdata. file: %s: gfid: %s", ++ real_path ? real_path : "null", ++ inode ? uuid_utoa(inode->gfid) : "null"); + ret = -1; + goto out; + } +@@ -262,18 +266,8 @@ __posix_get_mdata_xattr(xlator_t *this, const char *real_path, int _fd, + } + } else { + /* Failed to get mdata from disk, xattr missing. +- * This happens on two cases. +- * 1. File is created before ctime is enabled. +- * 2. On new file creation. +- * +- * Do nothing, just return success. It is as +- * good as ctime feature is not enabled for this +- * file. For files created before ctime is enabled, +- * time attributes gets updated into ctime structure +- * once the metadata modification fop happens and +- * time attributes become consistent eventually. +- * For new files, it would obviously get updated +- * before the fop completion. ++ * This happens when the file is created before ++ * ctime is enabled. + */ + if (stbuf && op_errno != ENOENT) { + ret = 0; +@@ -345,6 +339,54 @@ posix_compare_timespec(struct timespec *first, struct timespec *second) + return first->tv_sec - second->tv_sec; + } + ++int ++posix_set_mdata_xattr_legacy_files(xlator_t *this, inode_t *inode, ++ struct mdata_iatt *mdata_iatt, int *op_errno) ++{ ++ posix_mdata_t *mdata = NULL; ++ int ret = 0; ++ ++ GF_VALIDATE_OR_GOTO("posix", this, out); ++ GF_VALIDATE_OR_GOTO(this->name, inode, out); ++ ++ LOCK(&inode->lock); ++ { ++ mdata = GF_CALLOC(1, sizeof(posix_mdata_t), gf_posix_mt_mdata_attr); ++ if (!mdata) { ++ gf_msg(this->name, GF_LOG_ERROR, ENOMEM, P_MSG_NOMEM, ++ "Could not allocate mdata. gfid: %s", ++ uuid_utoa(inode->gfid)); ++ ret = -1; ++ *op_errno = ENOMEM; ++ goto unlock; ++ } ++ ++ mdata->version = 1; ++ mdata->flags = 0; ++ mdata->ctime.tv_sec = mdata_iatt->ia_ctime; ++ mdata->ctime.tv_nsec = mdata_iatt->ia_ctime_nsec; ++ mdata->atime.tv_sec = mdata_iatt->ia_atime; ++ mdata->atime.tv_nsec = mdata_iatt->ia_atime_nsec; ++ mdata->mtime.tv_sec = mdata_iatt->ia_mtime; ++ mdata->mtime.tv_nsec = mdata_iatt->ia_mtime_nsec; ++ ++ __inode_ctx_set1(inode, this, (uint64_t *)&mdata); ++ ++ ret = posix_store_mdata_xattr(this, NULL, -1, inode, mdata); ++ if (ret) { ++ gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_STOREMDATA_FAILED, ++ "gfid: %s key:%s ", uuid_utoa(inode->gfid), ++ GF_XATTR_MDATA_KEY); ++ *op_errno = errno; ++ goto unlock; ++ } ++ } ++unlock: ++ UNLOCK(&inode->lock); ++out: ++ return ret; ++} ++ + /* posix_set_mdata_xattr updates the posix_mdata_t based on the flag + * in inode context and stores it on disk + */ +@@ -372,6 +414,9 @@ posix_set_mdata_xattr(xlator_t *this, const char *real_path, int fd, + */ + mdata = GF_CALLOC(1, sizeof(posix_mdata_t), gf_posix_mt_mdata_attr); + if (!mdata) { ++ gf_msg(this->name, GF_LOG_ERROR, ENOMEM, P_MSG_NOMEM, ++ "Could not allocate mdata. file: %s: gfid: %s", ++ real_path ? real_path : "null", uuid_utoa(inode->gfid)); + ret = -1; + goto unlock; + } +@@ -386,35 +431,11 @@ posix_set_mdata_xattr(xlator_t *this, const char *real_path, int fd, + __inode_ctx_set1(inode, this, (uint64_t *)&mdata); + } else { + /* +- * This is the first time creating the time +- * attr. This happens when you activate this +- * feature, and the legacy file will not have +- * any xattr set. +- * +- * New files will create extended attributes. +- */ +- +- /* +- * TODO: This is wrong approach, because before +- * creating fresh xattr, we should consult +- * to all replica and/or distribution set. +- * +- * We should contact the time management +- * xlators, and ask them to create an xattr. +- */ +- /* We should not be relying on backend file's +- * time attributes to load the initial ctime +- * time attribute structure. This is incorrect +- * as each replica set would have witnessed the +- * file creation at different times. +- * +- * For new file creation, ctime, atime and mtime +- * should be same, hence initiate the ctime +- * structure with the time from the frame. But +- * for the files which were created before ctime +- * feature is enabled, this is not accurate but +- * still fine as the times would get eventually +- * accurate. ++ * This is the first time creating the time attr. This happens ++ * when you activate this feature. On this code path, only new ++ * files will create mdata xattr. The legacy files (files ++ * created before ctime enabled) will not have any xattr set. ++ * The xattr on legacy file will be set via lookup. + */ + + /* Don't create xattr with utimes/utimensat, only update if +diff --git a/xlators/storage/posix/src/posix-metadata.h b/xlators/storage/posix/src/posix-metadata.h +index 3416148..dc25e59 100644 +--- a/xlators/storage/posix/src/posix-metadata.h ++++ b/xlators/storage/posix/src/posix-metadata.h +@@ -53,5 +53,9 @@ posix_set_ctime_cfr(call_frame_t *frame, xlator_t *this, + const char *real_path_in, int fd_in, inode_t *inode_in, + struct iatt *stbuf_in, const char *read_path_put, + int fd_out, inode_t *inode_out, struct iatt *stbuf_out); ++int ++posix_set_mdata_xattr_legacy_files(xlator_t *this, inode_t *inode, ++ struct mdata_iatt *mdata_iatt, ++ int *op_errno); + + #endif /* _POSIX_METADATA_H */ +-- +1.8.3.1 + diff --git a/0261-features-utime-Fix-mem_put-crash.patch b/0261-features-utime-Fix-mem_put-crash.patch new file mode 100644 index 0000000..2c3fe9e --- /dev/null +++ b/0261-features-utime-Fix-mem_put-crash.patch @@ -0,0 +1,52 @@ +From 1aa175f353325775517daf1d48a19799e0cafc7a Mon Sep 17 00:00:00 2001 +From: Pranith Kumar K +Date: Mon, 22 Jul 2019 20:55:33 +0530 +Subject: [PATCH 261/261] features/utime: Fix mem_put crash + +Problem: +When frame->local is not null FRAME_DESTROY calls mem_put on it. +Since the stub is already destroyed in call_resume(), it leads +to crash + +Fix: +Set frame->local to NULL before calling call_resume() + +Backport of: + > Patch: https://review.gluster.org/23091 + > fixes: bz#1593542 + > Change-Id: I0f8adf406f4cefdb89d7624ba7a9d9c2eedfb1de + > Signed-off-by: Pranith Kumar K + +BUG: 1715422 +Change-Id: I0f8adf406f4cefdb89d7624ba7a9d9c2eedfb1de +Signed-off-by: Kotresh HR +Reviewed-on: https://code.engineering.redhat.com/gerrit/176726 +Tested-by: RHGS Build Bot +Reviewed-by: Atin Mukherjee +--- + xlators/features/utime/src/utime.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/xlators/features/utime/src/utime.c b/xlators/features/utime/src/utime.c +index 2a986e7..e3a80b6 100644 +--- a/xlators/features/utime/src/utime.c ++++ b/xlators/features/utime/src/utime.c +@@ -139,12 +139,14 @@ gf_utime_set_mdata_setxattr_cbk(call_frame_t *frame, void *cookie, + xlator_t *this, int op_ret, int op_errno, + dict_t *xdata) + { ++ call_stub_t *stub = frame->local; + /* Don't fail lookup if mdata setxattr fails */ + if (op_ret) { + gf_msg(this->name, GF_LOG_ERROR, op_errno, UTIME_MSG_SET_MDATA_FAILED, + "dict set of key for set-ctime-mdata failed"); + } +- call_resume(frame->local); ++ frame->local = NULL; ++ call_resume(stub); + return 0; + } + +-- +1.8.3.1 + diff --git a/glusterfs.spec b/glusterfs.spec index 9b3cab2..cc8267d 100644 --- a/glusterfs.spec +++ b/glusterfs.spec @@ -231,7 +231,7 @@ Release: 0.1%{?prereltag:.%{prereltag}}%{?dist} %else Name: glusterfs Version: 6.0 -Release: 8%{?dist} +Release: 9%{?dist} ExcludeArch: i686 %endif License: GPLv2 or LGPLv3+ @@ -564,6 +564,12 @@ Patch0252: 0252-glusterd-do-not-mark-skip_locking-as-true-for-geo-re.patch Patch0253: 0253-core-fix-deadlock-between-statedump-and-fd_anonymous.patch Patch0254: 0254-Detach-iot_worker-to-release-its-resources.patch Patch0255: 0255-Revert-tier-shd-glusterd-with-shd-mux-the-shd-volfil.patch +Patch0256: 0256-features-snapview-server-use-the-same-volfile-server.patch +Patch0257: 0257-geo-rep-Test-case-for-upgrading-config-file.patch +Patch0258: 0258-geo-rep-Fix-mount-broker-setup-issue.patch +Patch0259: 0259-gluster-block-tuning-perf-options.patch +Patch0260: 0260-ctime-Set-mdata-xattr-on-legacy-files.patch +Patch0261: 0261-features-utime-Fix-mem_put-crash.patch %description GlusterFS is a distributed file-system capable of scaling to several @@ -2272,6 +2278,9 @@ fi %endif %changelog +* Tue Jul 23 2019 Sunil Kumar Acharya - 6.0-9 +- fixes bugs bz#1708064 bz#1708180 bz#1715422 bz#1720992 bz#1722757 + * Tue Jul 16 2019 Sunil Kumar Acharya - 6.0-8 - fixes bugs bz#1698435 bz#1712591 bz#1715447 bz#1720488 bz#1722209 bz#1722512 bz#1724089 bz#1726991 bz#1727785 bz#1729108