BACKPORT: ceph: use timespec64 for inode timestamp
Since the vfs structures are all using timespec64, we can now change the internal representation, using ceph_encode_timespec64 and ceph_decode_timespec64. In case of ceph_aux_inode however, we need to avoid doing a memcmp() on uninitialized padding data, so the members of the i_mtime field get copied individually into 64-bit integers. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Reviewed-by: "Yan, Zheng" <zyan@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com> Change-Id: Ia1a10ea74dc07ce95bfc8ad6ddb5080d5ec41db7
This commit is contained in:
committed by
theshaenix
parent
923454e0d4
commit
04a3953c4a
@@ -25,9 +25,10 @@
|
||||
#include "cache.h"
|
||||
|
||||
struct ceph_aux_inode {
|
||||
u64 version;
|
||||
struct timespec mtime;
|
||||
loff_t size;
|
||||
u64 version;
|
||||
u64 mtime_sec;
|
||||
u64 mtime_nsec;
|
||||
loff_t size;
|
||||
};
|
||||
|
||||
struct fscache_netfs ceph_cache_netfs = {
|
||||
@@ -184,8 +185,9 @@ static enum fscache_checkaux ceph_fscache_inode_check_aux(
|
||||
|
||||
memset(&aux, 0, sizeof(aux));
|
||||
aux.version = ci->i_version;
|
||||
aux.mtime = timespec64_to_timespec(inode->i_mtime);
|
||||
aux.size = i_size_read(inode);
|
||||
aux.mtime_sec = inode->i_mtime.tv_sec;
|
||||
aux.mtime_nsec = inode->i_mtime.tv_nsec;
|
||||
aux.size = i_size_read(inode);
|
||||
|
||||
if (memcmp(data, &aux, sizeof(aux)) != 0)
|
||||
return FSCACHE_CHECKAUX_OBSOLETE;
|
||||
|
||||
@@ -1002,7 +1002,7 @@ struct cap_msg_args {
|
||||
u64 flush_tid, oldest_flush_tid, size, max_size;
|
||||
u64 xattr_version;
|
||||
struct ceph_buffer *xattr_buf;
|
||||
struct timespec atime, mtime, ctime;
|
||||
struct timespec64 atime, mtime, ctime;
|
||||
int op, caps, wanted, dirty;
|
||||
u32 seq, issue_seq, mseq, time_warp_seq;
|
||||
u32 flags;
|
||||
@@ -1023,7 +1023,7 @@ static int send_cap_msg(struct cap_msg_args *arg)
|
||||
struct ceph_msg *msg;
|
||||
void *p;
|
||||
size_t extra_len;
|
||||
struct timespec zerotime = {0};
|
||||
struct timespec64 zerotime = {0};
|
||||
struct ceph_osd_client *osdc = &arg->session->s_mdsc->fsc->client->osdc;
|
||||
|
||||
dout("send_cap_msg %s %llx %llx caps %s wanted %s dirty %s"
|
||||
@@ -1063,9 +1063,9 @@ static int send_cap_msg(struct cap_msg_args *arg)
|
||||
|
||||
fc->size = cpu_to_le64(arg->size);
|
||||
fc->max_size = cpu_to_le64(arg->max_size);
|
||||
ceph_encode_timespec(&fc->mtime, &arg->mtime);
|
||||
ceph_encode_timespec(&fc->atime, &arg->atime);
|
||||
ceph_encode_timespec(&fc->ctime, &arg->ctime);
|
||||
ceph_encode_timespec64(&fc->mtime, &arg->mtime);
|
||||
ceph_encode_timespec64(&fc->atime, &arg->atime);
|
||||
ceph_encode_timespec64(&fc->ctime, &arg->ctime);
|
||||
fc->time_warp_seq = cpu_to_le32(arg->time_warp_seq);
|
||||
|
||||
fc->uid = cpu_to_le32(from_kuid(&init_user_ns, arg->uid));
|
||||
@@ -1114,7 +1114,7 @@ static int send_cap_msg(struct cap_msg_args *arg)
|
||||
* We just zero these out for now, as the MDS ignores them unless
|
||||
* the requisite feature flags are set (which we don't do yet).
|
||||
*/
|
||||
ceph_encode_timespec(p, &zerotime);
|
||||
ceph_encode_timespec64(p, &zerotime);
|
||||
p += sizeof(struct ceph_timespec);
|
||||
ceph_encode_64(&p, 0);
|
||||
|
||||
@@ -1242,9 +1242,9 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
|
||||
arg.xattr_buf = NULL;
|
||||
}
|
||||
|
||||
arg.mtime = timespec64_to_timespec(inode->i_mtime);
|
||||
arg.atime = timespec64_to_timespec(inode->i_atime);
|
||||
arg.ctime = timespec64_to_timespec(inode->i_ctime);
|
||||
arg.mtime = inode->i_mtime;
|
||||
arg.atime = inode->i_atime;
|
||||
arg.ctime = inode->i_ctime;
|
||||
|
||||
arg.op = op;
|
||||
arg.caps = cap->implemented;
|
||||
@@ -3069,10 +3069,11 @@ static void handle_cap_grant(struct inode *inode,
|
||||
}
|
||||
|
||||
if (newcaps & CEPH_CAP_ANY_RD) {
|
||||
struct timespec64 mtime, atime, ctime;
|
||||
/* ctime/mtime/atime? */
|
||||
ceph_decode_timespec(&mtime, &grant->mtime);
|
||||
ceph_decode_timespec(&atime, &grant->atime);
|
||||
ceph_decode_timespec(&ctime, &grant->ctime);
|
||||
ceph_decode_timespec64(&mtime, &grant->mtime);
|
||||
ceph_decode_timespec64(&atime, &grant->atime);
|
||||
ceph_decode_timespec64(&ctime, &grant->ctime);
|
||||
ceph_fill_file_time(inode, extra_info->issued,
|
||||
le32_to_cpu(grant->time_warp_seq),
|
||||
&ctime, &mtime, &atime);
|
||||
|
||||
@@ -1381,7 +1381,7 @@ static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size,
|
||||
" rfiles: %20lld\n"
|
||||
" rsubdirs: %20lld\n"
|
||||
"rbytes: %20lld\n"
|
||||
"rctime: %10ld.%09ld\n",
|
||||
"rctime: %10lld.%09ld\n",
|
||||
ci->i_files + ci->i_subdirs,
|
||||
ci->i_files,
|
||||
ci->i_subdirs,
|
||||
@@ -1389,8 +1389,8 @@ static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size,
|
||||
ci->i_rfiles,
|
||||
ci->i_rsubdirs,
|
||||
ci->i_rbytes,
|
||||
(long)ci->i_rctime.tv_sec,
|
||||
(long)ci->i_rctime.tv_nsec);
|
||||
ci->i_rctime.tv_sec,
|
||||
ci->i_rctime.tv_nsec);
|
||||
}
|
||||
|
||||
if (*ppos >= cf->dir_info_len)
|
||||
|
||||
@@ -646,13 +646,10 @@ int ceph_fill_file_size(struct inode *inode, int issued,
|
||||
}
|
||||
|
||||
void ceph_fill_file_time(struct inode *inode, int issued,
|
||||
u64 time_warp_seq, struct timespec *ctime,
|
||||
struct timespec *mtime, struct timespec *atime)
|
||||
u64 time_warp_seq, struct timespec64 *ctime,
|
||||
struct timespec64 *mtime, struct timespec64 *atime)
|
||||
{
|
||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||
struct timespec64 ctime64 = timespec_to_timespec64(*ctime);
|
||||
struct timespec64 mtime64 = timespec_to_timespec64(*mtime);
|
||||
struct timespec64 atime64 = timespec_to_timespec64(*atime);
|
||||
int warn = 0;
|
||||
|
||||
if (issued & (CEPH_CAP_FILE_EXCL|
|
||||
@@ -660,10 +657,11 @@ void ceph_fill_file_time(struct inode *inode, int issued,
|
||||
CEPH_CAP_FILE_BUFFER|
|
||||
CEPH_CAP_AUTH_EXCL|
|
||||
CEPH_CAP_XATTR_EXCL)) {
|
||||
if (timespec64_compare(&ctime64, &inode->i_ctime) > 0) {
|
||||
if (timespec64_compare(ctime, &inode->i_ctime) > 0) {
|
||||
dout("ctime %ld.%09ld -> %ld.%09ld inc w/ cap\n",
|
||||
inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
|
||||
ctime->tv_sec, ctime->tv_nsec);
|
||||
inode->i_ctime = *ctime;
|
||||
inode->i_ctime = ctime64;
|
||||
}
|
||||
if (ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) > 0) {
|
||||
@@ -674,24 +672,24 @@ void ceph_fill_file_time(struct inode *inode, int issued,
|
||||
mtime->tv_sec, mtime->tv_nsec,
|
||||
ci->i_time_warp_seq, (int)time_warp_seq);
|
||||
|
||||
inode->i_mtime = mtime64;
|
||||
inode->i_atime = atime64;
|
||||
inode->i_mtime = *mtime;
|
||||
inode->i_atime = *atime;
|
||||
ci->i_time_warp_seq = time_warp_seq;
|
||||
} else if (time_warp_seq == ci->i_time_warp_seq) {
|
||||
/* nobody did utimes(); take the max */
|
||||
if (timespec64_compare(&mtime64, &inode->i_mtime) > 0) {
|
||||
dout("mtime %ld.%09ld -> %ld.%09ld inc\n",
|
||||
if (timespec64_compare(mtime, &inode->i_mtime) > 0) {
|
||||
dout("mtime %ld.%09ld -> %lld.%09ld inc\n",
|
||||
inode->i_mtime.tv_sec,
|
||||
inode->i_mtime.tv_nsec,
|
||||
mtime->tv_sec, mtime->tv_nsec);
|
||||
inode->i_mtime = mtime64;
|
||||
inode->i_mtime = *mtime;
|
||||
}
|
||||
if (timespec64_compare(&atime64, &inode->i_atime) > 0) {
|
||||
dout("atime %ld.%09ld -> %ld.%09ld inc\n",
|
||||
if (timespec64_compare(atime, &inode->i_atime) > 0) {
|
||||
dout("atime %ld.%09ld -> %lld.%09ld inc\n",
|
||||
inode->i_atime.tv_sec,
|
||||
inode->i_atime.tv_nsec,
|
||||
atime->tv_sec, atime->tv_nsec);
|
||||
inode->i_atime = atime64;
|
||||
inode->i_atime = *atime;
|
||||
}
|
||||
} else if (issued & CEPH_CAP_FILE_EXCL) {
|
||||
/* we did a utimes(); ignore mds values */
|
||||
@@ -701,9 +699,9 @@ void ceph_fill_file_time(struct inode *inode, int issued,
|
||||
} else {
|
||||
/* we have no write|excl caps; whatever the MDS says is true */
|
||||
if (ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) >= 0) {
|
||||
inode->i_ctime = ctime64;
|
||||
inode->i_mtime = mtime64;
|
||||
inode->i_atime = atime64;
|
||||
inode->i_ctime = *ctime;
|
||||
inode->i_mtime = *mtime;
|
||||
inode->i_atime = *atime;
|
||||
ci->i_time_warp_seq = time_warp_seq;
|
||||
} else {
|
||||
warn = 1;
|
||||
@@ -729,7 +727,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
|
||||
struct ceph_mds_reply_inode *info = iinfo->in;
|
||||
struct ceph_inode_info *ci = ceph_inode(inode);
|
||||
int issued = 0, implemented, new_issued;
|
||||
struct timespec mtime, atime, ctime;
|
||||
struct timespec64 mtime, atime, ctime;
|
||||
struct ceph_buffer *xattr_blob = NULL;
|
||||
struct ceph_buffer *old_blob = NULL;
|
||||
struct ceph_string *pool_ns = NULL;
|
||||
@@ -813,9 +811,9 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
|
||||
|
||||
if (new_version || (new_issued & CEPH_CAP_ANY_RD)) {
|
||||
/* be careful with mtime, atime, size */
|
||||
ceph_decode_timespec(&atime, &info->atime);
|
||||
ceph_decode_timespec(&mtime, &info->mtime);
|
||||
ceph_decode_timespec(&ctime, &info->ctime);
|
||||
ceph_decode_timespec64(&atime, &info->atime);
|
||||
ceph_decode_timespec64(&mtime, &info->mtime);
|
||||
ceph_decode_timespec64(&ctime, &info->ctime);
|
||||
ceph_fill_file_time(inode, issued,
|
||||
le32_to_cpu(info->time_warp_seq),
|
||||
&ctime, &mtime, &atime);
|
||||
@@ -1917,7 +1915,6 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
|
||||
int err = 0;
|
||||
int inode_dirty_flags = 0;
|
||||
bool lock_snap_rwsem = false;
|
||||
struct timespec ts;
|
||||
|
||||
prealloc_cf = ceph_alloc_cap_flush();
|
||||
if (!prealloc_cf)
|
||||
@@ -2006,8 +2003,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
|
||||
dirtied |= CEPH_CAP_FILE_WR;
|
||||
} else if ((issued & CEPH_CAP_FILE_SHARED) == 0 ||
|
||||
!timespec64_equal(&inode->i_atime, &attr->ia_atime)) {
|
||||
ts = timespec64_to_timespec(attr->ia_atime);
|
||||
ceph_encode_timespec(&req->r_args.setattr.atime, &ts);
|
||||
ceph_encode_timespec64(&req->r_args.setattr.atime,
|
||||
&attr->ia_atime);
|
||||
mask |= CEPH_SETATTR_ATIME;
|
||||
release |= CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_RD |
|
||||
CEPH_CAP_FILE_WR;
|
||||
@@ -2028,8 +2025,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
|
||||
dirtied |= CEPH_CAP_FILE_WR;
|
||||
} else if ((issued & CEPH_CAP_FILE_SHARED) == 0 ||
|
||||
!timespec64_equal(&inode->i_mtime, &attr->ia_mtime)) {
|
||||
ts = timespec64_to_timespec(attr->ia_mtime);
|
||||
ceph_encode_timespec(&req->r_args.setattr.mtime, &ts);
|
||||
ceph_encode_timespec64(&req->r_args.setattr.mtime,
|
||||
&attr->ia_mtime);
|
||||
mask |= CEPH_SETATTR_MTIME;
|
||||
release |= CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_RD |
|
||||
CEPH_CAP_FILE_WR;
|
||||
|
||||
@@ -2953,15 +2953,12 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap,
|
||||
rec.v2.pathbase = cpu_to_le64(pathbase);
|
||||
rec.v2.flock_len = 0;
|
||||
} else {
|
||||
struct timespec ts;
|
||||
rec.v1.cap_id = cpu_to_le64(cap->cap_id);
|
||||
rec.v1.wanted = cpu_to_le32(__ceph_caps_wanted(ci));
|
||||
rec.v1.issued = cpu_to_le32(cap->issued);
|
||||
rec.v1.size = cpu_to_le64(inode->i_size);
|
||||
ts = timespec64_to_timespec(inode->i_mtime);
|
||||
ceph_encode_timespec(&rec.v1.mtime, &ts);
|
||||
ts = timespec64_to_timespec(inode->i_atime);
|
||||
ceph_encode_timespec(&rec.v1.atime, &ts);
|
||||
ceph_encode_timespec64(&rec.v1.mtime, &inode->i_mtime);
|
||||
ceph_encode_timespec64(&rec.v1.atime, &inode->i_atime);
|
||||
rec.v1.snaprealm = cpu_to_le64(ci->i_snap_realm->ino);
|
||||
rec.v1.pathbase = cpu_to_le64(pathbase);
|
||||
}
|
||||
|
||||
@@ -601,9 +601,9 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
|
||||
|
||||
BUG_ON(capsnap->writing);
|
||||
capsnap->size = inode->i_size;
|
||||
capsnap->mtime = timespec64_to_timespec(inode->i_mtime);
|
||||
capsnap->atime = timespec64_to_timespec(inode->i_atime);
|
||||
capsnap->ctime = timespec64_to_timespec(inode->i_ctime);
|
||||
capsnap->mtime = inode->i_mtime;
|
||||
capsnap->atime = inode->i_atime;
|
||||
capsnap->ctime = inode->i_ctime;
|
||||
capsnap->time_warp_seq = ci->i_time_warp_seq;
|
||||
capsnap->truncate_size = ci->i_truncate_size;
|
||||
capsnap->truncate_seq = ci->i_truncate_seq;
|
||||
|
||||
@@ -192,7 +192,7 @@ struct ceph_cap_snap {
|
||||
u64 xattr_version;
|
||||
|
||||
u64 size;
|
||||
struct timespec mtime, atime, ctime;
|
||||
struct timespec64 mtime, atime, ctime;
|
||||
u64 time_warp_seq;
|
||||
u64 truncate_size;
|
||||
u32 truncate_seq;
|
||||
@@ -305,7 +305,7 @@ struct ceph_inode_info {
|
||||
char *i_symlink;
|
||||
|
||||
/* for dirs */
|
||||
struct timespec i_rctime;
|
||||
struct timespec64 i_rctime;
|
||||
u64 i_rbytes, i_rfiles, i_rsubdirs;
|
||||
u64 i_files, i_subdirs;
|
||||
|
||||
@@ -803,8 +803,9 @@ extern struct inode *ceph_get_snapdir(struct inode *parent);
|
||||
extern int ceph_fill_file_size(struct inode *inode, int issued,
|
||||
u32 truncate_seq, u64 truncate_size, u64 size);
|
||||
extern void ceph_fill_file_time(struct inode *inode, int issued,
|
||||
u64 time_warp_seq, struct timespec *ctime,
|
||||
struct timespec *mtime, struct timespec *atime);
|
||||
u64 time_warp_seq, struct timespec64 *ctime,
|
||||
struct timespec64 *mtime,
|
||||
struct timespec64 *atime);
|
||||
extern int ceph_fill_trace(struct super_block *sb,
|
||||
struct ceph_mds_request *req);
|
||||
extern int ceph_readdir_prepopulate(struct ceph_mds_request *req,
|
||||
|
||||
@@ -217,8 +217,8 @@ static size_t ceph_vxattrcb_dir_rbytes(struct ceph_inode_info *ci, char *val,
|
||||
static size_t ceph_vxattrcb_dir_rctime(struct ceph_inode_info *ci, char *val,
|
||||
size_t size)
|
||||
{
|
||||
return snprintf(val, size, "%ld.09%ld", (long)ci->i_rctime.tv_sec,
|
||||
(long)ci->i_rctime.tv_nsec);
|
||||
return snprintf(val, size, "%lld.09%ld", ci->i_rctime.tv_sec,
|
||||
ci->i_rctime.tv_nsec);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user