diff mbox

[RFC,v2c,7/8] fs: ceph: Use vfs timestamp abstraction helpers

Message ID 1455270773-3249-8-git-send-email-deepa.kernel@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Deepa Dinamani Feb. 12, 2016, 9:52 a.m. UTC
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 timespec64 and conversion functions here to
access inode times.

All the timestamps are converted to use struct timespec64 data
type. And, all the vfs timestamps are converted to timespec64
at the boundary of vfs.

Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
---
 fs/ceph/addr.c                  | 20 ++++++---
 fs/ceph/cache.c                 |  6 +--
 fs/ceph/caps.c                  | 10 ++---
 fs/ceph/dir.c                   |  4 +-
 fs/ceph/file.c                  | 14 +++++--
 fs/ceph/inode.c                 | 91 +++++++++++++++++++++++------------------
 fs/ceph/mds_client.c            |  9 ++--
 fs/ceph/mds_client.h            |  2 +-
 fs/ceph/snap.c                  |  6 +--
 fs/ceph/super.h                 |  9 ++--
 fs/ceph/xattr.c                 |  2 +-
 include/linux/ceph/decode.h     |  9 ++--
 include/linux/ceph/osd_client.h |  4 +-
 net/ceph/osd_client.c           |  4 +-
 14 files changed, 110 insertions(+), 80 deletions(-)
diff mbox

Patch

diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index c222137..09a97b5 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 timespec64 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_timespec64(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 timespec64 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_timespec64(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 timespec64 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_timespec64(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 timespec64 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_timespec64(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..a773543 100644
--- a/fs/ceph/cache.c
+++ b/fs/ceph/cache.c
@@ -25,7 +25,7 @@ 
 #include "cache.h"
 
 struct ceph_aux_inode {
-	struct timespec	mtime;
+	struct timespec64	mtime;
 	loff_t          size;
 };
 
@@ -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_timespec64(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_timespec64(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..ab186a1 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -990,7 +990,7 @@  static int send_cap_msg(struct ceph_mds_session *session,
 			int caps, int wanted, int dirty,
 			u32 seq, u64 flush_tid, u64 oldest_flush_tid,
 			u32 issue_seq, u32 mseq, u64 size, u64 max_size,
-			struct timespec *mtime, struct timespec *atime,
+			struct timespec64 *mtime, struct timespec64 *atime,
 			u64 time_warp_seq,
 			kuid_t uid, kgid_t gid, umode_t mode,
 			u64 xattr_version,
@@ -1116,7 +1116,7 @@  static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
 	int held, revoking, dropping, keep;
 	u64 seq, issue_seq, mseq, time_warp_seq, follows;
 	u64 size, max_size;
-	struct timespec mtime, atime;
+	struct timespec64 mtime, atime;
 	int wake = 0;
 	umode_t mode;
 	kuid_t uid;
@@ -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_timespec64(inode->i_mtime);
+	atime = vfs_time_to_timespec64(inode->i_atime);
 	time_warp_seq = ci->i_time_warp_seq;
 	uid = inode->i_uid;
 	gid = inode->i_gid;
@@ -2764,7 +2764,7 @@  static void handle_cap_grant(struct ceph_mds_client *mdsc,
 	int used, wanted, dirty;
 	u64 size = le64_to_cpu(grant->size);
 	u64 max_size = le64_to_cpu(grant->max_size);
-	struct timespec mtime, atime, ctime;
+	struct timespec64 mtime, atime, ctime;
 	int check_caps = 0;
 	bool wake = false;
 	bool writeback = false;
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index fd11fb2..83e6602 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -1210,7 +1210,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,
@@ -1218,7 +1218,7 @@  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 long)ci->i_rctime.tv_sec,
 				(long)ci->i_rctime.tv_nsec);
 	}
 
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 9b338ff..ec77278 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -555,7 +555,7 @@  struct ceph_aio_request {
 	struct list_head osd_reqs;
 	unsigned num_reqs;
 	atomic_t pending_reqs;
-	struct timespec mtime;
+	struct timespec64 mtime;
 	struct ceph_cap_flush *prealloc_cf;
 };
 
@@ -783,11 +783,13 @@  ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
 	int num_pages = 0;
 	int flags;
 	int ret;
-	struct timespec mtime = current_fs_time(inode->i_sb);
+	struct timespec64 mtime;
 	size_t count = iov_iter_count(iter);
 	loff_t pos = iocb->ki_pos;
 	bool write = iov_iter_rw(iter) == WRITE;
 
+	mtime = vfs_time_to_timespec64(current_fs_time(inode->i_sb));
+
 	if (write && ceph_snap(file_inode(file)) != CEPH_NOSNAP)
 		return -EROFS;
 
@@ -988,9 +990,11 @@  ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
 	int flags;
 	int check_caps = 0;
 	int ret;
-	struct timespec mtime = current_fs_time(inode->i_sb);
+	struct timespec64 mtime;
 	size_t count = iov_iter_count(from);
 
+	mtime = vfs_time_to_timespec64(current_fs_time(inode->i_sb));
+
 	if (ceph_snap(file_inode(file)) != CEPH_NOSNAP)
 		return -EROFS;
 
@@ -1497,6 +1501,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 timespec64 ts;
 	int ret = 0;
 	loff_t zero = 0;
 	int op;
@@ -1520,8 +1525,9 @@  static int ceph_zero_partial_object(struct inode *inode,
 		goto out;
 	}
 
+	ts = vfs_time_to_timespec64(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..ecfdbe5 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -590,10 +590,11 @@  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 vfs_time vfs_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) {
-			dout("ctime %ld.%09ld -> %ld.%09ld inc w/ cap\n",
-			     inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
+		vfs_ts = timespec64_to_vfs_time(*ctime);
+		if (vfs_time_compare(&vfs_ts, &inode->i_ctime) > 0) {
+			dout("ctime %lld.%09ld -> %lld.%09ld inc w/ cap\n",
+			     (long long)inode->i_ctime.tv_sec,
+			     inode->i_ctime.tv_nsec,
 			     ctime->tv_sec, ctime->tv_nsec);
-			inode->i_ctime = *ctime;
+			inode->i_ctime = vfs_ts;
 		}
 		if (ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) > 0) {
 			/* the MDS did a utimes() */
-			dout("mtime %ld.%09ld -> %ld.%09ld "
+			dout("mtime %lld.%09ld -> %lld.%09ld "
 			     "tw %d -> %d\n",
-			     inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
+			     (long long)inode->i_mtime.tv_sec,
+			     inode->i_mtime.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 = timespec64_to_vfs_time(*mtime);
+			inode->i_atime = timespec64_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) {
-				dout("mtime %ld.%09ld -> %ld.%09ld inc\n",
-				     inode->i_mtime.tv_sec,
-				     inode->i_mtime.tv_nsec,
-				     mtime->tv_sec, mtime->tv_nsec);
-				inode->i_mtime = *mtime;
+			vfs_ts = timespec64_to_vfs_time(*mtime);
+			if (vfs_time_compare(&vfs_ts, &inode->i_mtime) > 0) {
+				dout("mtime %lld.%09ld -> %lld.%09ld inc\n",
+					(long long)inode->i_mtime.tv_sec,
+					inode->i_mtime.tv_nsec,
+					mtime->tv_sec, mtime->tv_nsec);
+				inode->i_mtime = vfs_ts;
 			}
-			if (timespec_compare(atime, &inode->i_atime) > 0) {
-				dout("atime %ld.%09ld -> %ld.%09ld inc\n",
-				     inode->i_atime.tv_sec,
+			vfs_ts = timespec64_to_vfs_time(*atime);
+			if (vfs_time_compare(&vfs_ts, &inode->i_atime) > 0) {
+				dout("atime %lld.%09ld -> %lld.%09ld inc\n",
+				     (long long)inode->i_atime.tv_sec,
 				     inode->i_atime.tv_nsec,
 				     atime->tv_sec, atime->tv_nsec);
-				inode->i_atime = *atime;
+				inode->i_atime = vfs_ts;
 			}
 		} 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 = timespec64_to_vfs_time(*ctime);
+			inode->i_mtime = timespec64_to_vfs_time(*mtime);
+			inode->i_atime = timespec64_to_vfs_time(*atime);
 			ci->i_time_warp_seq = time_warp_seq;
 		} else {
 			warn = 1;
@@ -670,7 +675,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_cap *new_cap = NULL;
 	int err = 0;
@@ -1776,6 +1781,7 @@  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 timespec64 iattr_ts;
 	int issued;
 	int release = 0, dirtied = 0;
 	int mask = 0;
@@ -1863,44 +1869,46 @@  int ceph_setattr(struct dentry *dentry, struct iattr *attr)
 	}
 
 	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);
+		dout("setattr %p atime %lld.%ld -> %lld.%ld\n", inode,
+			(long long)inode->i_mtime.tv_sec,
+			inode->i_mtime.tv_nsec,
+		    (long long)attr->ia_mtime.tv_sec, attr->ia_mtime.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,
+			   vfs_time_compare(&inode->i_atime,
 					    &attr->ia_atime) < 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)) {
+			   !vfs_time_equal(&inode->i_atime, &attr->ia_atime)) {
+			iattr_ts = vfs_time_to_timespec64(attr->ia_atime);
 			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;
 		}
 	}
 	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);
+		dout("setattr %p mtime %lld.%ld -> %lld.%ld\n", inode,
+		   (long long)inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
+		   (long long)attr->ia_mtime.tv_sec, attr->ia_mtime.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,
+			   vfs_time_compare(&inode->i_mtime,
 					    &attr->ia_mtime) < 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)) {
+			   !vfs_time_equal(&inode->i_mtime, &attr->ia_mtime)) {
 			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;
@@ -1932,9 +1940,12 @@  int ceph_setattr(struct dentry *dentry, struct iattr *attr)
 	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,
+		dout("setattr %p ctime %lld.%ld -> %lld.%ld (%s)\n", inode,
+				 (long long)inode->i_ctime.tv_sec,
+				 inode->i_ctime.tv_nsec,
+				 (long long)attr->ia_ctime.tv_sec,
+				 attr->ia_ctime.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..bdf77065 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1721,7 +1721,7 @@  ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
 	init_completion(&req->r_safe_completion);
 	INIT_LIST_HEAD(&req->r_unsafe_item);
 
-	ktime_get_real_ts(&req->r_stamp);
+	getnstimeofday64(&req->r_stamp);
 
 	req->r_op = op;
 	req->r_direct_mode = mode;
@@ -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 timespec64 ts;
 	char *path;
 	int pathlen, err;
 	u64 pathbase;
@@ -2839,8 +2840,10 @@  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);
-		ceph_encode_timespec(&rec.v1.atime, &inode->i_atime);
+		ts = vfs_time_to_timespec64(inode->i_mtime);
+		ceph_encode_timespec(&rec.v1.mtime, &ts);
+		ts = vfs_time_to_timespec64(inode->i_atime);
+		ceph_encode_timespec(&rec.v1.atime, &ts);
 		rec.v1.snaprealm = cpu_to_le64(ci->i_snap_realm->ino);
 		rec.v1.pathbase = cpu_to_le64(pathbase);
 		reclen = sizeof(rec.v1);
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index ccf11ef..6fb8568 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -202,7 +202,7 @@  struct ceph_mds_request {
 	int r_fmode;        /* file mode, if expecting cap */
 	kuid_t r_uid;
 	kgid_t r_gid;
-	struct timespec r_stamp;
+	struct timespec64 r_stamp;
 
 	/* for choosing which mds to send this request to */
 	int r_direct_mode;
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index 4aa7122..312cdc2 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_timespec64(inode->i_mtime);
+	capsnap->atime = vfs_time_to_timespec64(inode->i_atime);
+	capsnap->ctime = vfs_time_to_timespec64(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 "
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 75b7d12..19c31ba 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -169,7 +169,7 @@  struct ceph_cap_snap {
 	u64 xattr_version;
 
 	u64 size;
-	struct timespec mtime, atime, ctime;
+	struct timespec64 mtime, atime, ctime;
 	u64 time_warp_seq;
 	int writing;   /* a sync write is still in progress */
 	int dirty_pages;     /* dirty pages awaiting writeback */
@@ -290,7 +290,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;
 
@@ -764,8 +764,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,
 			   struct ceph_mds_session *session);
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 1e1c00a..db5328d 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -198,7 +198,7 @@  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,
+	return snprintf(val, size, "%lld.09%ld", (long long)ci->i_rctime.tv_sec,
 			(long)ci->i_rctime.tv_nsec);
 }
 
diff --git a/include/linux/ceph/decode.h b/include/linux/ceph/decode.h
index 633a130..b68edf5 100644
--- a/include/linux/ceph/decode.h
+++ b/include/linux/ceph/decode.h
@@ -4,6 +4,7 @@ 
 #include <linux/err.h>
 #include <linux/bug.h>
 #include <linux/time.h>
+#include <linux/fs.h>
 #include <asm/unaligned.h>
 
 #include <linux/ceph/types.h>
@@ -132,16 +133,16 @@  bad:
 }
 
 /*
- * struct ceph_timespec <-> struct timespec
+ * struct ceph_timespec <-> struct timespec64
  */
-static inline void ceph_decode_timespec(struct timespec *ts,
+static inline void ceph_decode_timespec(struct timespec64 *ts,
 					const struct ceph_timespec *tv)
 {
-	ts->tv_sec = (__kernel_time_t)le32_to_cpu(tv->tv_sec);
+	ts->tv_sec = (s64)le32_to_cpu(tv->tv_sec);
 	ts->tv_nsec = (long)le32_to_cpu(tv->tv_nsec);
 }
 static inline void ceph_encode_timespec(struct ceph_timespec *tv,
-					const struct timespec *ts)
+					const struct timespec64 *ts)
 {
 	tv->tv_sec = cpu_to_le32((u32)ts->tv_sec);
 	tv->tv_nsec = cpu_to_le32((u32)ts->tv_nsec);
diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h
index 7506b48..f4fdd97 100644
--- a/include/linux/ceph/osd_client.h
+++ b/include/linux/ceph/osd_client.h
@@ -322,7 +322,7 @@  extern struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *
 extern void ceph_osdc_build_request(struct ceph_osd_request *req, u64 off,
 				    struct ceph_snap_context *snapc,
 				    u64 snap_id,
-				    struct timespec *mtime);
+				    struct timespec64 *mtime);
 
 extern struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *,
 				      struct ceph_file_layout *layout,
@@ -364,7 +364,7 @@  extern int ceph_osdc_writepages(struct ceph_osd_client *osdc,
 				struct ceph_snap_context *sc,
 				u64 off, u64 len,
 				u32 truncate_seq, u64 truncate_size,
-				struct timespec *mtime,
+				struct timespec64 *mtime,
 				struct page **pages, int nr_pages);
 
 /* watch/notify events */
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index f8f2359..af1692a 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -2401,7 +2401,7 @@  bad:
  */
 void ceph_osdc_build_request(struct ceph_osd_request *req, u64 off,
 				struct ceph_snap_context *snapc, u64 snap_id,
-				struct timespec *mtime)
+				struct timespec64 *mtime)
 {
 	struct ceph_msg *msg = req->r_request;
 	void *p;
@@ -2735,7 +2735,7 @@  int ceph_osdc_writepages(struct ceph_osd_client *osdc, struct ceph_vino vino,
 			 struct ceph_snap_context *snapc,
 			 u64 off, u64 len,
 			 u32 truncate_seq, u64 truncate_size,
-			 struct timespec *mtime,
+			 struct timespec64 *mtime,
 			 struct page **pages, int num_pages)
 {
 	struct ceph_osd_request *req;