This is in preparation for changing VFS inode timestamps to use 64 bit time. The VFS inode timestamps are not y2038 safe as they use struct timespec. These will be changed to use struct timespec64 instead and that is y2038 safe. But, since the above data type conversion will break the end file systems, use vfs_time functions to access inode times.
Signed-off-by: Deepa Dinamani deepa.kernel@gmail.com --- fs/ceph/addr.c | 20 +++++++++----- fs/ceph/cache.c | 4 +-- fs/ceph/caps.c | 4 +-- fs/ceph/file.c | 4 ++- fs/ceph/inode.c | 75 ++++++++++++++++++++++++++++++---------------------- fs/ceph/mds_client.c | 5 +++- fs/ceph/snap.c | 6 ++--- 7 files changed, 72 insertions(+), 46 deletions(-)
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index c222137..30d72e6 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -479,6 +479,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) struct ceph_fs_client *fsc; struct ceph_osd_client *osdc; struct ceph_snap_context *snapc, *oldest; + struct timespec ts; loff_t page_off = page_offset(page); loff_t snap_size = -1; long writeback_stat; @@ -540,11 +541,12 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) ceph_readpage_to_fscache(inode, page);
set_page_writeback(page); + ts = vfs_time_to_timespec(inode->i_mtime); err = ceph_osdc_writepages(osdc, ceph_vino(inode), &ci->i_layout, snapc, page_off, len, truncate_seq, truncate_size, - &inode->i_mtime, &page, 1); + &ts, &page, 1); if (err < 0) { dout("writepage setting page/mapping error %d %p\n", err, page); SetPageError(page); @@ -699,6 +701,7 @@ static int ceph_writepages_start(struct address_space *mapping, int rc = 0; unsigned wsize = 1 << inode->i_blkbits; struct ceph_osd_request *req = NULL; + struct timespec ts; int do_sync = 0; loff_t snap_size, i_size; u64 truncate_size; @@ -978,8 +981,9 @@ get_more_pages: osd_req_op_extent_update(req, 0, len);
vino = ceph_vino(inode); + ts = vfs_time_to_timespec(inode->i_mtime); ceph_osdc_build_request(req, offset, snapc, vino.snap, - &inode->i_mtime); + &ts);
rc = ceph_osdc_start_request(&fsc->client->osdc, req, true); BUG_ON(rc); @@ -1465,6 +1469,7 @@ int ceph_uninline_data(struct file *filp, struct page *locked_page) struct ceph_fs_client *fsc = ceph_inode_to_client(inode); struct ceph_osd_request *req; struct page *page = NULL; + struct timespec ts; u64 len, inline_version; int err = 0; bool from_pagecache = false; @@ -1528,7 +1533,8 @@ int ceph_uninline_data(struct file *filp, struct page *locked_page) goto out; }
- ceph_osdc_build_request(req, 0, NULL, CEPH_NOSNAP, &inode->i_mtime); + ts = vfs_time_to_timespec(inode->i_mtime); + ceph_osdc_build_request(req, 0, NULL, CEPH_NOSNAP, &ts); err = ceph_osdc_start_request(&fsc->client->osdc, req, false); if (!err) err = ceph_osdc_wait_request(&fsc->client->osdc, req); @@ -1572,7 +1578,7 @@ int ceph_uninline_data(struct file *filp, struct page *locked_page) goto out_put; }
- ceph_osdc_build_request(req, 0, NULL, CEPH_NOSNAP, &inode->i_mtime); + ceph_osdc_build_request(req, 0, NULL, CEPH_NOSNAP, &ts); err = ceph_osdc_start_request(&fsc->client->osdc, req, false); if (!err) err = ceph_osdc_wait_request(&fsc->client->osdc, req); @@ -1622,6 +1628,7 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci, u32 pool) struct ceph_osd_request *rd_req = NULL, *wr_req = NULL; struct rb_node **p, *parent; struct ceph_pool_perm *perm; + struct timespec ts; struct page **pages; int err = 0, err2 = 0, have = 0;
@@ -1701,12 +1708,13 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci, u32 pool)
osd_req_op_raw_data_in_pages(rd_req, 0, pages, PAGE_SIZE, 0, false, true); + ts = vfs_time_to_timespec(ci->vfs_inode.i_mtime); ceph_osdc_build_request(rd_req, 0, NULL, CEPH_NOSNAP, - &ci->vfs_inode.i_mtime); + &ts); err = ceph_osdc_start_request(&fsc->client->osdc, rd_req, false);
ceph_osdc_build_request(wr_req, 0, NULL, CEPH_NOSNAP, - &ci->vfs_inode.i_mtime); + &ts); err2 = ceph_osdc_start_request(&fsc->client->osdc, wr_req, false);
if (!err) diff --git a/fs/ceph/cache.c b/fs/ceph/cache.c index a351480..789121c 100644 --- a/fs/ceph/cache.c +++ b/fs/ceph/cache.c @@ -105,7 +105,7 @@ static uint16_t ceph_fscache_inode_get_aux(const void *cookie_netfs_data, const struct inode* inode = &ci->vfs_inode;
memset(&aux, 0, sizeof(aux)); - aux.mtime = inode->i_mtime; + aux.mtime = vfs_time_to_timespec(inode->i_mtime); aux.size = i_size_read(inode);
memcpy(buffer, &aux, sizeof(aux)); @@ -131,7 +131,7 @@ static enum fscache_checkaux ceph_fscache_inode_check_aux( return FSCACHE_CHECKAUX_OBSOLETE;
memset(&aux, 0, sizeof(aux)); - aux.mtime = inode->i_mtime; + aux.mtime = vfs_time_to_timespec(inode->i_mtime); aux.size = i_size_read(inode);
if (memcmp(data, &aux, sizeof(aux)) != 0) diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index cdbf8cf..03b7212 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -1178,8 +1178,8 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap, ci->i_reported_size = size; max_size = ci->i_wanted_max_size; ci->i_requested_max_size = max_size; - mtime = inode->i_mtime; - atime = inode->i_atime; + mtime = vfs_time_to_timespec(inode->i_mtime); + atime = vfs_time_to_timespec(inode->i_atime); time_warp_seq = ci->i_time_warp_seq; uid = inode->i_uid; gid = inode->i_gid; diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 9b338ff..0b782c6 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -1497,6 +1497,7 @@ static int ceph_zero_partial_object(struct inode *inode, struct ceph_inode_info *ci = ceph_inode(inode); struct ceph_fs_client *fsc = ceph_inode_to_client(inode); struct ceph_osd_request *req; + struct timespec ts; int ret = 0; loff_t zero = 0; int op; @@ -1520,8 +1521,9 @@ static int ceph_zero_partial_object(struct inode *inode, goto out; }
+ ts = vfs_time_to_timespec(inode->i_mtime); ceph_osdc_build_request(req, offset, NULL, ceph_vino(inode).snap, - &inode->i_mtime); + &ts);
ret = ceph_osdc_start_request(&fsc->client->osdc, req, false); if (!ret) { diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 63d0198..7e560bf 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -594,6 +594,7 @@ void ceph_fill_file_time(struct inode *inode, int issued, struct timespec *mtime, struct timespec *atime) { struct ceph_inode_info *ci = ceph_inode(inode); + struct timespec ts; int warn = 0;
if (issued & (CEPH_CAP_FILE_EXCL| @@ -601,38 +602,42 @@ void ceph_fill_file_time(struct inode *inode, int issued, CEPH_CAP_FILE_BUFFER| CEPH_CAP_AUTH_EXCL| CEPH_CAP_XATTR_EXCL)) { - if (timespec_compare(ctime, &inode->i_ctime) > 0) { + ts = vfs_time_to_timespec(inode->i_ctime); + if (timespec_compare(ctime, &ts) > 0) { dout("ctime %ld.%09ld -> %ld.%09ld inc w/ cap\n", - inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec, + ts.tv_sec, ts.tv_nsec, ctime->tv_sec, ctime->tv_nsec); - inode->i_ctime = *ctime; + inode->i_ctime = timespec_to_vfs_time(*ctime); } if (ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) > 0) { /* the MDS did a utimes() */ + ts = vfs_time_to_timespec(inode->i_mtime); dout("mtime %ld.%09ld -> %ld.%09ld " "tw %d -> %d\n", - inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec, + ts.tv_sec, ts.tv_nsec, mtime->tv_sec, mtime->tv_nsec, ci->i_time_warp_seq, (int)time_warp_seq);
- inode->i_mtime = *mtime; - inode->i_atime = *atime; + inode->i_mtime = timespec_to_vfs_time(*mtime); + inode->i_atime = timespec_to_vfs_time(*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 (timespec_compare(mtime, &inode->i_mtime) > 0) { + ts = vfs_time_to_timespec(inode->i_mtime); + if (timespec_compare(mtime, &ts) > 0) { dout("mtime %ld.%09ld -> %ld.%09ld inc\n", - inode->i_mtime.tv_sec, - inode->i_mtime.tv_nsec, + ts.tv_sec, + ts.tv_nsec, mtime->tv_sec, mtime->tv_nsec); - inode->i_mtime = *mtime; + inode->i_mtime = timespec_to_vfs_time(*mtime); } - if (timespec_compare(atime, &inode->i_atime) > 0) { + ts = vfs_time_to_timespec(inode->i_atime); + if (timespec_compare(atime, &ts) > 0) { dout("atime %ld.%09ld -> %ld.%09ld inc\n", - inode->i_atime.tv_sec, - inode->i_atime.tv_nsec, + ts.tv_sec, + ts.tv_nsec, atime->tv_sec, atime->tv_nsec); - inode->i_atime = *atime; + inode->i_atime = timespec_to_vfs_time(*atime); } } else if (issued & CEPH_CAP_FILE_EXCL) { /* we did a utimes(); ignore mds values */ @@ -642,9 +647,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 = *ctime; - inode->i_mtime = *mtime; - inode->i_atime = *atime; + inode->i_ctime = timespec_to_vfs_time(*ctime); + inode->i_mtime = timespec_to_vfs_time(*mtime); + inode->i_atime = timespec_to_vfs_time(*atime); ci->i_time_warp_seq = time_warp_seq; } else { warn = 1; @@ -1776,6 +1781,8 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) struct ceph_mds_request *req; struct ceph_mds_client *mdsc = ceph_sb_to_client(dentry->d_sb)->mdsc; struct ceph_cap_flush *prealloc_cf; + struct timespec inode_ts; + struct timespec iattr_ts; int issued; int release = 0, dirtied = 0; int mask = 0; @@ -1862,45 +1869,49 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) } }
+ inode_ts = vfs_time_to_timespec(inode->i_atime); + iattr_ts = vfs_time_to_timespec(attr->ia_atime); if (ia_valid & ATTR_ATIME) { dout("setattr %p atime %ld.%ld -> %ld.%ld\n", inode, - inode->i_atime.tv_sec, inode->i_atime.tv_nsec, - attr->ia_atime.tv_sec, attr->ia_atime.tv_nsec); + inode_ts.tv_sec, inode_ts.tv_nsec, + iattr_ts.tv_sec, iattr_ts.tv_nsec); if (issued & CEPH_CAP_FILE_EXCL) { ci->i_time_warp_seq++; inode->i_atime = attr->ia_atime; dirtied |= CEPH_CAP_FILE_EXCL; } else if ((issued & CEPH_CAP_FILE_WR) && - timespec_compare(&inode->i_atime, - &attr->ia_atime) < 0) { + timespec_compare(&inode_ts, + &iattr_ts) < 0) { inode->i_atime = attr->ia_atime; dirtied |= CEPH_CAP_FILE_WR; } else if ((issued & CEPH_CAP_FILE_SHARED) == 0 || - !timespec_equal(&inode->i_atime, &attr->ia_atime)) { + !timespec_equal(&inode_ts, &iattr_ts)) { ceph_encode_timespec(&req->r_args.setattr.atime, - &attr->ia_atime); + &iattr_ts); mask |= CEPH_SETATTR_ATIME; release |= CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR; } } + inode_ts = vfs_time_to_timespec(inode->i_mtime); + iattr_ts = vfs_time_to_timespec(attr->ia_mtime); if (ia_valid & ATTR_MTIME) { dout("setattr %p mtime %ld.%ld -> %ld.%ld\n", inode, - inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec, - attr->ia_mtime.tv_sec, attr->ia_mtime.tv_nsec); + inode_ts.tv_sec, inode_ts.tv_nsec, + iattr_ts.tv_sec, iattr_ts.tv_nsec); if (issued & CEPH_CAP_FILE_EXCL) { ci->i_time_warp_seq++; inode->i_mtime = attr->ia_mtime; dirtied |= CEPH_CAP_FILE_EXCL; } else if ((issued & CEPH_CAP_FILE_WR) && - timespec_compare(&inode->i_mtime, - &attr->ia_mtime) < 0) { + timespec_compare(&inode_ts, + &iattr_ts) < 0) { inode->i_mtime = attr->ia_mtime; dirtied |= CEPH_CAP_FILE_WR; } else if ((issued & CEPH_CAP_FILE_SHARED) == 0 || - !timespec_equal(&inode->i_mtime, &attr->ia_mtime)) { + !timespec_equal(&inode_ts, &iattr_ts)) { ceph_encode_timespec(&req->r_args.setattr.mtime, - &attr->ia_mtime); + &iattr_ts); mask |= CEPH_SETATTR_MTIME; release |= CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR; @@ -1929,12 +1940,14 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) }
/* these do nothing */ + inode_ts = vfs_time_to_timespec(inode->i_ctime); + iattr_ts = vfs_time_to_timespec(attr->ia_ctime); if (ia_valid & ATTR_CTIME) { bool only = (ia_valid & (ATTR_SIZE|ATTR_MTIME|ATTR_ATIME| ATTR_MODE|ATTR_UID|ATTR_GID)) == 0; dout("setattr %p ctime %ld.%ld -> %ld.%ld (%s)\n", inode, - inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec, - attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec, + inode_ts.tv_sec, inode_ts.tv_nsec, + iattr_ts.tv_sec, iattr_ts.tv_nsec, only ? "ctime only" : "ignored"); inode->i_ctime = attr->ia_ctime; if (only) { diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 348b22e..01811f9 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -2791,6 +2791,7 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap, struct ceph_inode_info *ci; struct ceph_reconnect_state *recon_state = arg; struct ceph_pagelist *pagelist = recon_state->pagelist; + struct timespec ts; char *path; int pathlen, err; u64 pathbase; @@ -2839,7 +2840,9 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap, 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); - ceph_encode_timespec(&rec.v1.mtime, &inode->i_mtime); + ts = vfs_time_to_timespec(inode->i_mtime); + ceph_encode_timespec(&rec.v1.mtime, &ts); + ts = vfs_time_to_timespec(inode->i_atime); ceph_encode_timespec(&rec.v1.atime, &inode->i_atime); rec.v1.snaprealm = cpu_to_le64(ci->i_snap_realm->ino); rec.v1.pathbase = cpu_to_le64(pathbase); diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index 4aa7122..aea3344 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c @@ -593,9 +593,9 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
BUG_ON(capsnap->writing); capsnap->size = inode->i_size; - capsnap->mtime = inode->i_mtime; - capsnap->atime = inode->i_atime; - capsnap->ctime = inode->i_ctime; + capsnap->mtime = vfs_time_to_timespec(inode->i_mtime); + capsnap->atime = vfs_time_to_timespec(inode->i_atime); + capsnap->ctime = vfs_time_to_timespec(inode->i_ctime); capsnap->time_warp_seq = ci->i_time_warp_seq; if (capsnap->dirty_pages) { dout("finish_cap_snap %p cap_snap %p snapc %p %llu %s s=%llu "