diff options
Diffstat (limited to 'xlators/storage/posix/src/posix-metadata.c')
| -rw-r--r-- | xlators/storage/posix/src/posix-metadata.c | 557 |
1 files changed, 408 insertions, 149 deletions
diff --git a/xlators/storage/posix/src/posix-metadata.c b/xlators/storage/posix/src/posix-metadata.c index 3fce0b23d1f..b1889052f11 100644 --- a/xlators/storage/posix/src/posix-metadata.c +++ b/xlators/storage/posix/src/posix-metadata.c @@ -8,14 +8,14 @@ cases as published by the Free Software Foundation. */ -#include "xlator.h" +#include <glusterfs/xlator.h> #include "posix-metadata.h" #include "posix-metadata-disk.h" #include "posix-handle.h" #include "posix-messages.h" -#include "syscall.h" -#include "compat-errno.h" -#include "compat.h" +#include <glusterfs/syscall.h> +#include <glusterfs/compat-errno.h> +#include <glusterfs/compat.h> static int gf_posix_xattr_enotsup_log; @@ -56,22 +56,32 @@ posix_mdata_from_disk(posix_mdata_t *out, posix_mdata_disk_t *in) out->atime.tv_nsec = be64toh(in->atime.tv_nsec); } +void +posix_mdata_iatt_from_disk(struct mdata_iatt *out, posix_mdata_disk_t *in) +{ + out->ia_ctime = be64toh(in->ctime.tv_sec); + out->ia_ctime_nsec = be64toh(in->ctime.tv_nsec); + + out->ia_mtime = be64toh(in->mtime.tv_sec); + out->ia_mtime_nsec = be64toh(in->mtime.tv_nsec); + + out->ia_atime = be64toh(in->atime.tv_sec); + out->ia_atime_nsec = be64toh(in->atime.tv_nsec); +} + /* posix_fetch_mdata_xattr fetches the posix_mdata_t from disk */ static int posix_fetch_mdata_xattr(xlator_t *this, const char *real_path_arg, int _fd, inode_t *inode, posix_mdata_t *metadata, int *op_errno) { - size_t size = -1; + size_t size = 256; int op_ret = -1; char *value = NULL; gf_boolean_t fd_based_fop = _gf_false; char gfid_str[64] = {0}; char *real_path = NULL; - char *key = GF_XATTR_MDATA_KEY; - if (!metadata) { - op_ret = -1; goto out; } @@ -79,84 +89,101 @@ posix_fetch_mdata_xattr(xlator_t *this, const char *real_path_arg, int _fd, fd_based_fop = _gf_true; } if (!(fd_based_fop || real_path_arg)) { + GF_VALIDATE_OR_GOTO(this->name, inode, out); MAKE_HANDLE_PATH(real_path, this, inode->gfid, NULL); if (!real_path) { + *op_errno = errno; uuid_utoa_r(inode->gfid, gfid_str); - gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_LSTAT_FAILED, + gf_msg(this->name, GF_LOG_WARNING, *op_errno, P_MSG_LSTAT_FAILED, "lstat on gfid %s failed", gfid_str); - op_ret = -1; - *op_errno = errno; goto out; } } + value = GF_MALLOC(size * sizeof(char), gf_posix_mt_char); + if (!value) { + *op_errno = ENOMEM; + goto out; + } + if (fd_based_fop) { - size = sys_fgetxattr(_fd, key, NULL, 0); + size = sys_fgetxattr(_fd, GF_XATTR_MDATA_KEY, value, size); } else if (real_path_arg) { - size = sys_lgetxattr(real_path_arg, key, NULL, 0); + size = sys_lgetxattr(real_path_arg, GF_XATTR_MDATA_KEY, value, size); } else if (real_path) { - size = sys_lgetxattr(real_path, key, NULL, 0); + size = sys_lgetxattr(real_path, GF_XATTR_MDATA_KEY, value, size); } if (size == -1) { *op_errno = errno; + if (value) { + GF_FREE(value); + value = NULL; + } if ((*op_errno == ENOTSUP) || (*op_errno == ENOSYS)) { GF_LOG_OCCASIONALLY(gf_posix_xattr_enotsup_log, this->name, GF_LOG_WARNING, - "Extended attributes not " - "supported (try remounting" - " brick with 'user_xattr' " + "Extended attributes not supported" + " (try remounting brick with 'user xattr' " "flag)"); } else if (*op_errno == ENOATTR || *op_errno == ENODATA) { gf_msg_debug(this->name, 0, - "No such attribute:%s for file %s " - "gfid: %s", - key, + "No such attribute:%s for file %s gfid: %s", + GF_XATTR_MDATA_KEY, real_path ? real_path : (real_path_arg ? real_path_arg : "null"), - uuid_utoa(inode->gfid)); - } else { - gf_msg(this->name, GF_LOG_DEBUG, *op_errno, P_MSG_XATTR_FAILED, - "getxattr failed" - " on %s gfid: %s key: %s ", + inode ? uuid_utoa(inode->gfid) : "null"); + goto out; + } + + if (fd_based_fop) { + size = sys_fgetxattr(_fd, GF_XATTR_MDATA_KEY, NULL, 0); + } else if (real_path_arg) { + size = sys_lgetxattr(real_path_arg, GF_XATTR_MDATA_KEY, NULL, 0); + } else if (real_path) { + size = sys_lgetxattr(real_path, GF_XATTR_MDATA_KEY, NULL, 0); + } + + if (size == -1) { /* give up now and exist with an error */ + *op_errno = errno; + gf_msg(this->name, GF_LOG_ERROR, *op_errno, P_MSG_XATTR_FAILED, + "getxattr failed on %s gfid: %s key: %s ", real_path ? real_path : (real_path_arg ? real_path_arg : "null"), - uuid_utoa(inode->gfid), key); + inode ? uuid_utoa(inode->gfid) : "null", GF_XATTR_MDATA_KEY); + goto out; } - op_ret = -1; - goto out; - } - value = GF_CALLOC(size + 1, sizeof(char), gf_posix_mt_char); - if (!value) { - op_ret = -1; - *op_errno = ENOMEM; - goto out; - } + value = GF_MALLOC(size * sizeof(char), gf_posix_mt_char); + if (!value) { + *op_errno = ENOMEM; + goto out; + } - if (fd_based_fop) { - size = sys_fgetxattr(_fd, key, value, size); - } else if (real_path_arg) { - size = sys_lgetxattr(real_path_arg, key, value, size); - } else if (real_path) { - size = sys_lgetxattr(real_path, key, value, size); - } - if (size == -1) { - op_ret = -1; - *op_errno = errno; - gf_msg(this->name, GF_LOG_ERROR, errno, P_MSG_XATTR_FAILED, - "getxattr failed on " - " on %s gfid: %s key: %s ", - real_path ? real_path : (real_path_arg ? real_path_arg : "null"), - uuid_utoa(inode->gfid), key); - goto out; + if (fd_based_fop) { + size = sys_fgetxattr(_fd, GF_XATTR_MDATA_KEY, value, size); + } else if (real_path_arg) { + size = sys_lgetxattr(real_path_arg, GF_XATTR_MDATA_KEY, value, + size); + } else if (real_path) { + size = sys_lgetxattr(real_path, GF_XATTR_MDATA_KEY, value, size); + } + if (size == -1) { + *op_errno = errno; + gf_msg(this->name, GF_LOG_ERROR, *op_errno, P_MSG_XATTR_FAILED, + "getxattr failed on %s gfid: %s key: %s ", + real_path ? real_path + : (real_path_arg ? real_path_arg : "null"), + inode ? uuid_utoa(inode->gfid) : "null", GF_XATTR_MDATA_KEY); + goto out; + } } - posix_mdata_from_disk(metadata, (posix_mdata_disk_t *)value); op_ret = 0; out: - GF_FREE(value); + if (value) + GF_FREE(value); return op_ret; } @@ -229,16 +256,29 @@ int __posix_get_mdata_xattr(xlator_t *this, const char *real_path, int _fd, inode_t *inode, struct iatt *stbuf) { + uint64_t ctx; posix_mdata_t *mdata = NULL; int ret = -1; int op_errno = 0; - GF_VALIDATE_OR_GOTO(this->name, inode, out); + /* Handle readdirp: inode might be null, time attributes should be served + * from xattr not from backend's file attributes */ + if (inode) { + ret = __inode_ctx_get1(inode, this, &ctx); + if (ret == 0) { + mdata = (posix_mdata_t *)(uintptr_t)ctx; + } + } else { + ret = -1; + } - ret = __inode_ctx_get1(inode, this, (uint64_t *)&mdata); 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; } @@ -251,24 +291,18 @@ __posix_get_mdata_xattr(xlator_t *this, const char *real_path, int _fd, * is hit when in-memory status is lost due to brick * down scenario */ - __inode_ctx_set1(inode, this, (uint64_t *)&mdata); + if (inode) { + ctx = (uint64_t)(uintptr_t)mdata; + __inode_ctx_set1(inode, this, &ctx); + } } 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; + GF_FREE(mdata); goto out; } else { /* This case should not be hit. If it hits, @@ -277,7 +311,8 @@ __posix_get_mdata_xattr(xlator_t *this, const char *real_path, int _fd, */ gf_msg(this->name, GF_LOG_WARNING, op_errno, P_MSG_FETCHMDATA_FAILED, "file: %s: gfid: %s key:%s ", - real_path ? real_path : "null", uuid_utoa(inode->gfid), + real_path ? real_path : "null", + inode ? uuid_utoa(inode->gfid) : "null", GF_XATTR_MDATA_KEY); GF_FREE(mdata); ret = 0; @@ -296,6 +331,10 @@ __posix_get_mdata_xattr(xlator_t *this, const char *real_path, int _fd, stbuf->ia_atime = mdata->atime.tv_sec; stbuf->ia_atime_nsec = mdata->atime.tv_nsec; } + /* Not set in inode context, hence free mdata */ + if (!inode) { + GF_FREE(mdata); + } out: return ret; @@ -331,24 +370,129 @@ 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, + const char *realpath, + struct mdata_iatt *mdata_iatt, int *op_errno) +{ + uint64_t ctx; + posix_mdata_t *mdata = NULL; + posix_mdata_t imdata = { + 0, + }; + int ret = 0; + gf_boolean_t mdata_already_set = _gf_false; + + GF_VALIDATE_OR_GOTO("posix", this, out); + GF_VALIDATE_OR_GOTO(this->name, inode, out); + + LOCK(&inode->lock); + { + ret = __inode_ctx_get1(inode, this, &ctx); + if (ret == 0 && ctx) { + mdata = (posix_mdata_t *)(uintptr_t)ctx; + mdata_already_set = _gf_true; + } else { + 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; + } + + ret = posix_fetch_mdata_xattr(this, realpath, -1, inode, + (void *)mdata, op_errno); + if (ret == 0) { + /* Got mdata from disk. This is a race, another client + * has healed the xattr during lookup. So set it in inode + * ctx */ + ctx = (uint64_t)(uintptr_t)mdata; + __inode_ctx_set1(inode, this, &ctx); + mdata_already_set = _gf_true; + } else { + *op_errno = 0; + 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; + + ctx = (uint64_t)(uintptr_t)mdata; + __inode_ctx_set1(inode, this, &ctx); + } + } + + if (mdata_already_set) { + /* Compare and update the larger time */ + imdata.ctime.tv_sec = mdata_iatt->ia_ctime; + imdata.ctime.tv_nsec = mdata_iatt->ia_ctime_nsec; + imdata.atime.tv_sec = mdata_iatt->ia_atime; + imdata.atime.tv_nsec = mdata_iatt->ia_atime_nsec; + imdata.mtime.tv_sec = mdata_iatt->ia_mtime; + imdata.mtime.tv_nsec = mdata_iatt->ia_mtime_nsec; + + if (posix_compare_timespec(&imdata.ctime, &mdata->ctime) > 0) { + mdata->ctime = imdata.ctime; + } + if (posix_compare_timespec(&imdata.mtime, &mdata->mtime) > 0) { + mdata->mtime = imdata.mtime; + } + if (posix_compare_timespec(&imdata.atime, &mdata->atime) > 0) { + mdata->atime = imdata.atime; + } + } + + ret = posix_store_mdata_xattr(this, realpath, -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 */ static int posix_set_mdata_xattr(xlator_t *this, const char *real_path, int fd, - inode_t *inode, struct timespec *time, struct iatt *stbuf, - posix_mdata_flag_t *flag, gf_boolean_t update_utime) + inode_t *inode, struct timespec *time, + struct timespec *u_atime, struct timespec *u_mtime, + struct iatt *stbuf, posix_mdata_flag_t *flag, + gf_boolean_t update_utime) { + uint64_t ctx; posix_mdata_t *mdata = NULL; int ret = -1; int op_errno = 0; GF_VALIDATE_OR_GOTO("posix", this, out); GF_VALIDATE_OR_GOTO(this->name, inode, out); + GF_VALIDATE_OR_GOTO(this->name, time, out); + + if (update_utime && (flag->atime && !u_atime) && + (flag->mtime && !u_mtime)) { + goto out; + } LOCK(&inode->lock); { - ret = __inode_ctx_get1(inode, this, (uint64_t *)&mdata); + ret = __inode_ctx_get1(inode, this, &ctx); + if (ret == 0) { + mdata = (posix_mdata_t *)(uintptr_t)ctx; + } if (ret == -1 || !mdata) { /* * Do we need to fetch the data from xattr @@ -357,6 +501,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; } @@ -368,39 +515,32 @@ posix_set_mdata_xattr(xlator_t *this, const char *real_path, int fd, * is hit when in-memory status is lost due to brick * down scenario */ - __inode_ctx_set1(inode, this, (uint64_t *)&mdata); - } else if (ret && time) { + ctx = (uint64_t)(uintptr_t)mdata; + __inode_ctx_set1(inode, this, &ctx); + } 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. + * 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. */ - /* - * 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. + /* Don't create xattr with utimes/utimensat, only update if + * present. This otherwise causes issues during inservice + * upgrade. It causes inconsistent xattr values with in replica + * set. The scenario happens during upgrade where clients are + * older versions (without the ctime feature) and the server is + * upgraded to the new version (with the ctime feature which + * is enabled by default). */ + + if (update_utime) { + UNLOCK(&inode->lock); + GF_FREE(mdata); + return 0; + } + mdata->version = 1; mdata->flags = 0; mdata->ctime.tv_sec = time->tv_sec; @@ -410,36 +550,35 @@ posix_set_mdata_xattr(xlator_t *this, const char *real_path, int fd, mdata->mtime.tv_sec = time->tv_sec; mdata->mtime.tv_nsec = time->tv_nsec; - __inode_ctx_set1(inode, this, (uint64_t *)&mdata); + ctx = (uint64_t)(uintptr_t)mdata; + __inode_ctx_set1(inode, this, &ctx); } } - /* Earlier, mdata was updated only if the existing time is less - * than the time to be updated. This would fail the scenarios - * where mtime can be set to any time using the syscall. Hence - * just updating without comparison. But the ctime is not - * allowed to changed to older date. - */ - - if (flag->ctime && posix_compare_timespec(time, &mdata->ctime) > 0) { - mdata->ctime = *time; - } - /* In distributed systems, there could be races with fops * updating mtime/atime which could result in different * mtime/atime for same file. So this makes sure, only the * highest time is retained. If the mtime/atime update comes * from the explicit utime syscall, it is allowed to set to - * previous time + * previous or future time but the ctime is always set to + * current time. */ if (update_utime) { + if (flag->ctime && + posix_compare_timespec(time, &mdata->ctime) > 0) { + mdata->ctime = *time; + } if (flag->mtime) { - mdata->mtime = *time; + mdata->mtime = *u_mtime; } if (flag->atime) { - mdata->atime = *time; + mdata->atime = *u_atime; } } else { + if (flag->ctime && + posix_compare_timespec(time, &mdata->ctime) > 0) { + mdata->ctime = *time; + } if (flag->mtime && posix_compare_timespec(time, &mdata->mtime) > 0) { mdata->mtime = *time; @@ -492,15 +631,22 @@ out: */ void posix_update_utime_in_mdata(xlator_t *this, const char *real_path, int fd, - inode_t *inode, struct iatt *stbuf, int valid) + inode_t *inode, struct timespec *ctime, + struct iatt *stbuf, int valid) { int32_t ret = 0; #if defined(HAVE_UTIMENSAT) - struct timespec tv = { + struct timespec tv_atime = { + 0, + }; + struct timespec tv_mtime = { 0, }; #else - struct timeval tv = { + struct timeval tv_atime = { + 0, + }; + struct timeval tv_mtime = { 0, }; #endif @@ -512,37 +658,35 @@ posix_update_utime_in_mdata(xlator_t *this, const char *real_path, int fd, priv = this->private; + /* NOTE: + * This routine (utimes) is intentionally allowed for all internal and + * external clients even if ctime is not set. This is because AFR and + * WORM uses time attributes for it's internal operations + */ if (inode && priv->ctime) { if ((valid & GF_SET_ATTR_ATIME) == GF_SET_ATTR_ATIME) { - tv.tv_sec = stbuf->ia_atime; - SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv, stbuf->ia_atime_nsec); + tv_atime.tv_sec = stbuf->ia_atime; + SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv_atime, stbuf->ia_atime_nsec); - flag.ctime = 0; - flag.mtime = 0; + flag.ctime = 1; flag.atime = 1; - ret = posix_set_mdata_xattr(this, real_path, -1, inode, &tv, NULL, - &flag, _gf_true); - if (ret) { - gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED, - "posix set mdata atime failed on file:" - " %s gfid:%s", - real_path, uuid_utoa(inode->gfid)); - } } if ((valid & GF_SET_ATTR_MTIME) == GF_SET_ATTR_MTIME) { - tv.tv_sec = stbuf->ia_mtime; - SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv, stbuf->ia_mtime_nsec); + tv_mtime.tv_sec = stbuf->ia_mtime; + SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv_mtime, stbuf->ia_mtime_nsec); flag.ctime = 1; flag.mtime = 1; - flag.atime = 0; + } - ret = posix_set_mdata_xattr(this, real_path, -1, inode, &tv, NULL, - &flag, _gf_true); + if (flag.mtime || flag.atime) { + ret = posix_set_mdata_xattr(this, real_path, -1, inode, ctime, + &tv_atime, &tv_mtime, NULL, &flag, + _gf_true); if (ret) { gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED, - "posix set mdata mtime failed on file:" + "posix set mdata atime failed on file:" " %s gfid:%s", real_path, uuid_utoa(inode->gfid)); } @@ -551,6 +695,48 @@ posix_update_utime_in_mdata(xlator_t *this, const char *real_path, int fd, return; } +/* posix_update_ctime_in_mdata updates the posix_mdata_t when ctime needs + * to be modified + */ +void +posix_update_ctime_in_mdata(xlator_t *this, const char *real_path, int fd, + inode_t *inode, struct timespec *ctime, + struct iatt *stbuf, int valid) +{ + int32_t ret = 0; +#if defined(HAVE_UTIMENSAT) + struct timespec tv_ctime = { + 0, + }; +#else + struct timeval tv_ctime = { + 0, + }; +#endif + posix_mdata_flag_t flag = { + 0, + }; + + struct posix_private *priv = NULL; + priv = this->private; + + if (inode && priv->ctime) { + tv_ctime.tv_sec = stbuf->ia_ctime; + SET_TIMESPEC_NSEC_OR_TIMEVAL_USEC(tv_ctime, stbuf->ia_ctime_nsec); + flag.ctime = 1; + + ret = posix_set_mdata_xattr(this, real_path, -1, inode, &tv_ctime, NULL, + NULL, NULL, &flag, _gf_true); + if (ret) { + gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED, + "posix set mdata atime failed on file:" + " %s gfid:%s", + real_path, uuid_utoa(inode->gfid)); + } + } + return; +} + static void posix_get_mdata_flag(uint64_t flags, posix_mdata_flag_t *flag) { @@ -604,17 +790,9 @@ posix_set_ctime(call_frame_t *frame, xlator_t *this, const char *real_path, if ((flag.ctime == 0) && (flag.mtime == 0) && (flag.atime == 0)) { goto out; } - - if (frame->root->ctime.tv_sec == 0) { - gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED, - "posix set mdata failed, No ctime : %s gfid:%s", real_path, - inode ? uuid_utoa(inode->gfid) : "No inode"); - goto out; - } - ret = posix_set_mdata_xattr(this, real_path, fd, inode, - &frame->root->ctime, stbuf, &flag, - _gf_false); + &frame->root->ctime, NULL, NULL, stbuf, + &flag, _gf_false); if (ret) { gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED, "posix set mdata failed on file: %s gfid:%s", real_path, @@ -644,8 +822,8 @@ posix_set_parent_ctime(call_frame_t *frame, xlator_t *this, goto out; } ret = posix_set_mdata_xattr(this, real_path, fd, inode, - &frame->root->ctime, stbuf, &flag, - _gf_false); + &frame->root->ctime, NULL, NULL, stbuf, + &flag, _gf_false); if (ret) { gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED, "posix set mdata failed on file: %s gfid:%s", real_path, @@ -655,3 +833,84 @@ posix_set_parent_ctime(call_frame_t *frame, xlator_t *this, out: return; } + +void +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 *real_path_out, + int fd_out, inode_t *inode_out, struct iatt *stbuf_out) +{ + posix_mdata_flag_t flag = { + 0, + }; + posix_mdata_flag_t flag_dup = { + 0, + }; + int ret = 0; + struct posix_private *priv = NULL; + char in_uuid_str[64] = {0}, out_uuid_str[64] = {0}; + + priv = this->private; + + if (priv->ctime) { + (void)posix_get_mdata_flag(frame->root->flags, &flag); + if ((flag.ctime == 0) && (flag.mtime == 0) && (flag.atime == 0)) { + goto out; + } + + if (frame->root->ctime.tv_sec == 0) { + gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED, + "posix set mdata failed, No ctime : in: %s gfid_in:%s " + "out: %s gfid_out:%s", + real_path_in, + (inode_in ? uuid_utoa_r(inode_in->gfid, in_uuid_str) + : "No inode"), + real_path_out, + (inode_out ? uuid_utoa_r(inode_out->gfid, out_uuid_str) + : "No inode")); + goto out; + } + + flag_dup = flag; + + /* + * For the destination file, no need to update atime. + * It got modified. Hence the things that need to be + * changed are mtime and ctime (provided the utime + * xlator from the client has set those flags, which + * are just copied to flag_dup). + */ + if (flag.atime) + flag_dup.atime = 0; + + ret = posix_set_mdata_xattr(this, real_path_out, fd_out, inode_out, + &frame->root->ctime, NULL, NULL, stbuf_out, + &flag_dup, _gf_false); + if (ret) { + gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED, + "posix set mdata failed on file: %s gfid:%s", real_path_out, + inode_out ? uuid_utoa(inode_out->gfid) : "No inode"); + } + + /* + * For the source file, no need to change the mtime and ctime. + * For source file, it is only read operation. So, if at all + * anything needs to be updated, it is only the atime. + */ + if (flag.atime) + flag_dup.atime = flag.atime; + flag_dup.mtime = 0; + flag_dup.ctime = 0; + + ret = posix_set_mdata_xattr(this, real_path_in, fd_out, inode_out, + &frame->root->ctime, NULL, NULL, stbuf_out, + &flag_dup, _gf_false); + if (ret) { + gf_msg(this->name, GF_LOG_WARNING, errno, P_MSG_SETMDATA_FAILED, + "posix set mdata failed on file: %s gfid:%s", real_path_in, + inode_in ? uuid_utoa(inode_in->gfid) : "No inode"); + } + } +out: + return; +} |
