2018-07-13 20:20:32

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH 1/5] ceph: use timespec64 in for keepalive

ceph_con_keepalive_expired() is the last user of timespec_add() and some
of the last uses of ktime_get_real_ts(). Replacing this with timespec64
based interfaces lets us remove that deprecated API.

I'm introducing new ceph_encode_timespec64()/ceph_decode_timespec64()
here that take timespec64 structures and convert to/from ceph_timespec,
which is defined to have an unsigned 32-bit tv_sec member. This extends
the range of valid times to year 2106, avoiding the year 2038 overflow.

The ceph file system portion still uses the old functions for inode
timestamps, this will be done separately after the VFS layer is converted.

Signed-off-by: Arnd Bergmann <[email protected]>
---
include/linux/ceph/decode.h | 20 +++++++++++++++++++-
include/linux/ceph/messenger.h | 2 +-
net/ceph/auth_x.c | 14 +++++++-------
net/ceph/auth_x.h | 2 +-
net/ceph/cls_lock_client.c | 4 ++--
net/ceph/messenger.c | 20 ++++++++++----------
6 files changed, 40 insertions(+), 22 deletions(-)

diff --git a/include/linux/ceph/decode.h b/include/linux/ceph/decode.h
index d143ac8879c6..45efe09fb7b4 100644
--- a/include/linux/ceph/decode.h
+++ b/include/linux/ceph/decode.h
@@ -194,8 +194,26 @@ ceph_decode_skip_n(p, end, sizeof(u8), bad)
} while (0)

/*
- * struct ceph_timespec <-> struct timespec
+ * struct ceph_timespec <-> struct timespec64
*/
+static inline void ceph_decode_timespec64(struct timespec64 *ts,
+ const struct ceph_timespec *tv)
+{
+ /*
+ * this will still overflow in year 2106. We could extend
+ * the protocol to steal two more bits from tv_nsec to
+ * add three more 136 year epochs after that the way ext4
+ * does if necessary.
+ */
+ ts->tv_sec = (time64_t)le32_to_cpu(tv->tv_sec);
+ ts->tv_nsec = (long)le32_to_cpu(tv->tv_nsec);
+}
+static inline void ceph_encode_timespec64(struct ceph_timespec *tv,
+ const struct timespec64 *ts)
+{
+ tv->tv_sec = cpu_to_le32((u32)ts->tv_sec);
+ tv->tv_nsec = cpu_to_le32((u32)ts->tv_nsec);
+}
static inline void ceph_decode_timespec(struct timespec *ts,
const struct ceph_timespec *tv)
{
diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h
index c7dfcb8a1fb2..a718b877c597 100644
--- a/include/linux/ceph/messenger.h
+++ b/include/linux/ceph/messenger.h
@@ -330,7 +330,7 @@ struct ceph_connection {
int in_base_pos; /* bytes read */
__le64 in_temp_ack; /* for reading an ack */

- struct timespec last_keepalive_ack; /* keepalive2 ack stamp */
+ struct timespec64 last_keepalive_ack; /* keepalive2 ack stamp */

struct delayed_work work; /* send|recv work */
unsigned long delay; /* current delay interval */
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c
index 2f4a1baf5f52..b05c3a540a5a 100644
--- a/net/ceph/auth_x.c
+++ b/net/ceph/auth_x.c
@@ -149,12 +149,12 @@ static int process_one_ticket(struct ceph_auth_client *ac,
void *dp, *dend;
int dlen;
char is_enc;
- struct timespec validity;
+ struct timespec64 validity;
void *tp, *tpend;
void **ptp;
struct ceph_crypto_key new_session_key = { 0 };
struct ceph_buffer *new_ticket_blob;
- unsigned long new_expires, new_renew_after;
+ time64_t new_expires, new_renew_after;
u64 new_secret_id;
int ret;

@@ -189,11 +189,11 @@ static int process_one_ticket(struct ceph_auth_client *ac,
if (ret)
goto out;

- ceph_decode_timespec(&validity, dp);
+ ceph_decode_timespec64(&validity, dp);
dp += sizeof(struct ceph_timespec);
- new_expires = get_seconds() + validity.tv_sec;
+ new_expires = ktime_get_real_seconds() + validity.tv_sec;
new_renew_after = new_expires - (validity.tv_sec / 4);
- dout(" expires=%lu renew_after=%lu\n", new_expires,
+ dout(" expires=%llu renew_after=%llu\n", new_expires,
new_renew_after);

/* ticket blob for service */
@@ -385,13 +385,13 @@ static bool need_key(struct ceph_x_ticket_handler *th)
if (!th->have_key)
return true;

- return get_seconds() >= th->renew_after;
+ return ktime_get_real_seconds() >= th->renew_after;
}

static bool have_key(struct ceph_x_ticket_handler *th)
{
if (th->have_key) {
- if (get_seconds() >= th->expires)
+ if (ktime_get_real_seconds() >= th->expires)
th->have_key = false;
}

diff --git a/net/ceph/auth_x.h b/net/ceph/auth_x.h
index 454cb54568af..57ba99f7736f 100644
--- a/net/ceph/auth_x.h
+++ b/net/ceph/auth_x.h
@@ -22,7 +22,7 @@ struct ceph_x_ticket_handler {
u64 secret_id;
struct ceph_buffer *ticket_blob;

- unsigned long renew_after, expires;
+ time64_t renew_after, expires;
};

#define CEPHX_AU_ENC_BUF_LEN 128 /* big enough for encrypted blob */
diff --git a/net/ceph/cls_lock_client.c b/net/ceph/cls_lock_client.c
index 8d2032b2f225..2105a6eaa66c 100644
--- a/net/ceph/cls_lock_client.c
+++ b/net/ceph/cls_lock_client.c
@@ -32,7 +32,7 @@ int ceph_cls_lock(struct ceph_osd_client *osdc,
int desc_len = strlen(desc);
void *p, *end;
struct page *lock_op_page;
- struct timespec mtime;
+ struct timespec64 mtime;
int ret;

lock_op_buf_size = name_len + sizeof(__le32) +
@@ -63,7 +63,7 @@ int ceph_cls_lock(struct ceph_osd_client *osdc,
ceph_encode_string(&p, end, desc, desc_len);
/* only support infinite duration */
memset(&mtime, 0, sizeof(mtime));
- ceph_encode_timespec(p, &mtime);
+ ceph_encode_timespec64(p, &mtime);
p += sizeof(struct ceph_timespec);
ceph_encode_8(&p, flags);

diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index c6413c360771..3f6336248509 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -1417,11 +1417,11 @@ static void prepare_write_keepalive(struct ceph_connection *con)
dout("prepare_write_keepalive %p\n", con);
con_out_kvec_reset(con);
if (con->peer_features & CEPH_FEATURE_MSGR_KEEPALIVE2) {
- struct timespec now;
+ struct timespec64 now;

- ktime_get_real_ts(&now);
+ ktime_get_real_ts64(&now);
con_out_kvec_add(con, sizeof(tag_keepalive2), &tag_keepalive2);
- ceph_encode_timespec(&con->out_temp_keepalive2, &now);
+ ceph_encode_timespec64(&con->out_temp_keepalive2, &now);
con_out_kvec_add(con, sizeof(con->out_temp_keepalive2),
&con->out_temp_keepalive2);
} else {
@@ -2555,7 +2555,7 @@ static int read_keepalive_ack(struct ceph_connection *con)
int ret = read_partial(con, size, size, &ceph_ts);
if (ret <= 0)
return ret;
- ceph_decode_timespec(&con->last_keepalive_ack, &ceph_ts);
+ ceph_decode_timespec64(&con->last_keepalive_ack, &ceph_ts);
prepare_read_tag(con);
return 1;
}
@@ -3223,12 +3223,12 @@ bool ceph_con_keepalive_expired(struct ceph_connection *con,
{
if (interval > 0 &&
(con->peer_features & CEPH_FEATURE_MSGR_KEEPALIVE2)) {
- struct timespec now;
- struct timespec ts;
- ktime_get_real_ts(&now);
- jiffies_to_timespec(interval, &ts);
- ts = timespec_add(con->last_keepalive_ack, ts);
- return timespec_compare(&now, &ts) >= 0;
+ struct timespec64 now;
+ struct timespec64 ts;
+ ktime_get_real_ts64(&now);
+ jiffies_to_timespec64(interval, &ts);
+ ts = timespec64_add(con->last_keepalive_ack, ts);
+ return timespec64_compare(&now, &ts) >= 0;
}
return false;
}
--
2.9.0



2018-07-13 20:21:27

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH 2/5] ceph: stop using current_kernel_time()

ceph_mdsc_create_request() is one of the last callers of the
deprecated current_kernel_time() as well as timespec_trunc().

This changes it to use the timespec64 based interfaces instead,
though we still need to convert the result until we are ready to
change over req->r_stamp.

The output of the two functions, ktime_get_coarse_real_ts64() and
current_kernel_time() is the same coarse-granular timestamp,
the only difference here is that ktime_get_coarse_real_ts64()
doesn't overflow in 2038.

Signed-off-by: Arnd Bergmann <[email protected]>
---
v2: add clarification that this is the same timestamp
---
fs/ceph/mds_client.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index dc8bc664a871..69c839316a7a 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1779,6 +1779,7 @@ struct ceph_mds_request *
ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
{
struct ceph_mds_request *req = kzalloc(sizeof(*req), GFP_NOFS);
+ struct timespec64 ts;

if (!req)
return ERR_PTR(-ENOMEM);
@@ -1797,7 +1798,9 @@ 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);

- req->r_stamp = timespec_trunc(current_kernel_time(), mdsc->fsc->sb->s_time_gran);
+ ktime_get_coarse_real_ts64(&ts);
+ req->r_stamp = timespec64_to_timespec(timespec64_trunc(ts,
+ mdsc->fsc->sb->s_time_gran));

req->r_op = op;
req->r_direct_mode = mode;
--
2.9.0


2018-07-13 20:22:01

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH 4/5] ceph: use timespec64 for r_mtime

The request mtime field is used all over ceph, and is currently
represented as a 'timespec' structure in Linux. This changes it to
timespec64 to allow times beyond 2038, modifying all users at the
same time.

Signed-off-by: Arnd Bergmann <[email protected]>
---
v2: undo an unneeded change pointed out by Yan Zheng.
---
drivers/block/rbd.c | 2 +-
fs/ceph/addr.c | 12 ++++++------
fs/ceph/file.c | 8 ++++----
include/linux/ceph/osd_client.h | 6 +++---
net/ceph/osd_client.c | 8 ++++----
5 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index d81c653b9bf6..a9a11fe484e5 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -1452,7 +1452,7 @@ static void rbd_osd_req_format_write(struct rbd_obj_request *obj_request)
struct ceph_osd_request *osd_req = obj_request->osd_req;

osd_req->r_flags = CEPH_OSD_FLAG_WRITE;
- ktime_get_real_ts(&osd_req->r_mtime);
+ ktime_get_real_ts64(&osd_req->r_mtime);
osd_req->r_data_offset = obj_request->ex.oe_off;
}

diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 292b3d72d725..d44d51e69e76 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -574,7 +574,7 @@ static u64 get_writepages_data_length(struct inode *inode,
*/
static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
{
- struct timespec ts;
+ struct timespec64 ts;
struct inode *inode;
struct ceph_inode_info *ci;
struct ceph_fs_client *fsc;
@@ -625,7 +625,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
set_bdi_congested(inode_to_bdi(inode), BLK_RW_ASYNC);

set_page_writeback(page);
- ts = timespec64_to_timespec(inode->i_mtime);
+ ts = inode->i_mtime;
err = ceph_osdc_writepages(&fsc->client->osdc, ceph_vino(inode),
&ci->i_layout, snapc, page_off, len,
ceph_wbc.truncate_seq,
@@ -1134,7 +1134,7 @@ static int ceph_writepages_start(struct address_space *mapping,
pages = NULL;
}

- req->r_mtime = timespec64_to_timespec(inode->i_mtime);
+ req->r_mtime = inode->i_mtime;
rc = ceph_osdc_start_request(&fsc->client->osdc, req, true);
BUG_ON(rc);
req = NULL;
@@ -1734,7 +1734,7 @@ int ceph_uninline_data(struct file *filp, struct page *locked_page)
goto out;
}

- req->r_mtime = timespec64_to_timespec(inode->i_mtime);
+ req->r_mtime = inode->i_mtime;
err = ceph_osdc_start_request(&fsc->client->osdc, req, false);
if (!err)
err = ceph_osdc_wait_request(&fsc->client->osdc, req);
@@ -1776,7 +1776,7 @@ int ceph_uninline_data(struct file *filp, struct page *locked_page)
goto out_put;
}

- req->r_mtime = timespec64_to_timespec(inode->i_mtime);
+ req->r_mtime = inode->i_mtime;
err = ceph_osdc_start_request(&fsc->client->osdc, req, false);
if (!err)
err = ceph_osdc_wait_request(&fsc->client->osdc, req);
@@ -1937,7 +1937,7 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci,
0, false, true);
err = ceph_osdc_start_request(&fsc->client->osdc, rd_req, false);

- wr_req->r_mtime = timespec64_to_timespec(ci->vfs_inode.i_mtime);
+ wr_req->r_mtime = ci->vfs_inode.i_mtime;
err2 = ceph_osdc_start_request(&fsc->client->osdc, wr_req, false);

if (!err)
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index e2679e8a2535..732d14726e80 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -720,7 +720,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;
};

@@ -922,7 +922,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
int num_pages = 0;
int flags;
int ret;
- struct timespec mtime = timespec64_to_timespec(current_time(inode));
+ struct timespec64 mtime = current_time(inode);
size_t count = iov_iter_count(iter);
loff_t pos = iocb->ki_pos;
bool write = iov_iter_rw(iter) == WRITE;
@@ -1130,7 +1130,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
int flags;
int ret;
bool check_caps = false;
- struct timespec mtime = timespec64_to_timespec(current_time(inode));
+ struct timespec64 mtime = current_time(inode);
size_t count = iov_iter_count(from);

if (ceph_snap(file_inode(file)) != CEPH_NOSNAP)
@@ -1662,7 +1662,7 @@ static int ceph_zero_partial_object(struct inode *inode,
goto out;
}

- req->r_mtime = timespec64_to_timespec(inode->i_mtime);
+ req->r_mtime = inode->i_mtime;
ret = ceph_osdc_start_request(&fsc->client->osdc, req, false);
if (!ret) {
ret = ceph_osdc_wait_request(&fsc->client->osdc, req);
diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h
index 0d6ee04b4c41..2e6611c1e9a0 100644
--- a/include/linux/ceph/osd_client.h
+++ b/include/linux/ceph/osd_client.h
@@ -199,7 +199,7 @@ struct ceph_osd_request {
/* set by submitter */
u64 r_snapid; /* for reads, CEPH_NOSNAP o/w */
struct ceph_snap_context *r_snapc; /* for writes */
- struct timespec r_mtime; /* ditto */
+ struct timespec64 r_mtime; /* ditto */
u64 r_data_offset; /* ditto */
bool r_linger; /* don't resend on failure */

@@ -253,7 +253,7 @@ struct ceph_osd_linger_request {
struct ceph_osd_request_target t;
u32 map_dne_bound;

- struct timespec mtime;
+ struct timespec64 mtime;

struct kref kref;
struct mutex lock;
@@ -508,7 +508,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 */
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index a00c74f1154e..a87a021ca9d0 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -1978,7 +1978,7 @@ static void encode_request_partial(struct ceph_osd_request *req,
p += sizeof(struct ceph_blkin_trace_info);

ceph_encode_32(&p, 0); /* client_inc, always 0 */
- ceph_encode_timespec(p, &req->r_mtime);
+ ceph_encode_timespec64(p, &req->r_mtime);
p += sizeof(struct ceph_timespec);

encode_oloc(&p, end, &req->r_t.target_oloc);
@@ -4512,7 +4512,7 @@ ceph_osdc_watch(struct ceph_osd_client *osdc,
ceph_oid_copy(&lreq->t.base_oid, oid);
ceph_oloc_copy(&lreq->t.base_oloc, oloc);
lreq->t.flags = CEPH_OSD_FLAG_WRITE;
- ktime_get_real_ts(&lreq->mtime);
+ ktime_get_real_ts64(&lreq->mtime);

lreq->reg_req = alloc_linger_request(lreq);
if (!lreq->reg_req) {
@@ -4570,7 +4570,7 @@ int ceph_osdc_unwatch(struct ceph_osd_client *osdc,
ceph_oid_copy(&req->r_base_oid, &lreq->t.base_oid);
ceph_oloc_copy(&req->r_base_oloc, &lreq->t.base_oloc);
req->r_flags = CEPH_OSD_FLAG_WRITE;
- ktime_get_real_ts(&req->r_mtime);
+ ktime_get_real_ts64(&req->r_mtime);
osd_req_op_watch_init(req, 0, lreq->linger_id,
CEPH_OSD_WATCH_OP_UNWATCH);

@@ -5136,7 +5136,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;
--
2.9.0


2018-07-13 20:22:33

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH 3/5] 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 <[email protected]>
---
fs/ceph/cache.c | 11 +++++---
fs/ceph/caps.c | 26 +++++++++---------
fs/ceph/dir.c | 6 ++---
fs/ceph/inode.c | 76 +++++++++++++++++++++++++---------------------------
fs/ceph/mds_client.c | 7 ++---
fs/ceph/snap.c | 6 ++---
fs/ceph/super.h | 9 ++++---
fs/ceph/xattr.c | 4 +--
8 files changed, 71 insertions(+), 74 deletions(-)

diff --git a/fs/ceph/cache.c b/fs/ceph/cache.c
index 362900e42424..1bf3502bdd6f 100644
--- a/fs/ceph/cache.c
+++ b/fs/ceph/cache.c
@@ -25,8 +25,9 @@
#include "cache.h"

struct ceph_aux_inode {
- u64 version;
- struct timespec mtime;
+ u64 version;
+ u64 mtime_sec;
+ u64 mtime_nsec;
};

struct fscache_netfs ceph_cache_netfs = {
@@ -130,7 +131,8 @@ 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.mtime_sec = inode->i_mtime.tv_sec;
+ aux.mtime_nsec = inode->i_mtime.tv_nsec;

if (memcmp(data, &aux, sizeof(aux)) != 0)
return FSCACHE_CHECKAUX_OBSOLETE;
@@ -163,7 +165,8 @@ void ceph_fscache_register_inode_cookie(struct inode *inode)
if (!ci->fscache) {
memset(&aux, 0, sizeof(aux));
aux.version = ci->i_version;
- aux.mtime = timespec64_to_timespec(inode->i_mtime);
+ aux.mtime_sec = inode->i_mtime.tv_sec;
+ aux.mtime_nsec = inode->i_mtime.tv_nsec;
ci->fscache = fscache_acquire_cookie(fsc->fscache,
&ceph_fscache_inode_object_def,
&ci->i_vino, sizeof(ci->i_vino),
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 990258cbd836..f50cc008632a 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1125,7 +1125,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;
@@ -1146,7 +1146,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"
@@ -1186,9 +1186,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));
@@ -1237,7 +1237,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);

@@ -1360,9 +1360,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;
@@ -3148,11 +3148,11 @@ static void handle_cap_grant(struct inode *inode,
}

if (newcaps & CEPH_CAP_ANY_RD) {
- struct timespec mtime, atime, ctime;
+ 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);
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 036ac0f3a393..4c3961717e77 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -1393,7 +1393,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,
@@ -1401,8 +1401,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 >= dfi->dir_info_len)
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index a866be999216..715a6f2a4613 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -658,13 +658,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|
@@ -673,39 +670,39 @@ void ceph_fill_file_time(struct inode *inode, int issued,
CEPH_CAP_AUTH_EXCL|
CEPH_CAP_XATTR_EXCL)) {
if (ci->i_version == 0 ||
- timespec64_compare(&ctime64, &inode->i_ctime) > 0) {
+ timespec64_compare(ctime, &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,
- (long long)ctime->tv_sec, ctime->tv_nsec);
- inode->i_ctime = ctime64;
+ inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
+ ctime->tv_sec, ctime->tv_nsec);
+ inode->i_ctime = *ctime;
}
if (ci->i_version == 0 ||
ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) > 0) {
/* the MDS did a utimes() */
dout("mtime %lld.%09ld -> %lld.%09ld "
"tw %d -> %d\n",
- (long long)inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
- (long long)mtime->tv_sec, mtime->tv_nsec,
+ 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 = 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) {
+ if (timespec64_compare(mtime, &inode->i_mtime) > 0) {
dout("mtime %lld.%09ld -> %lld.%09ld inc\n",
- (long long)inode->i_mtime.tv_sec,
+ inode->i_mtime.tv_sec,
inode->i_mtime.tv_nsec,
- (long long)mtime->tv_sec, mtime->tv_nsec);
- inode->i_mtime = mtime64;
+ mtime->tv_sec, mtime->tv_nsec);
+ inode->i_mtime = *mtime;
}
- if (timespec64_compare(&atime64, &inode->i_atime) > 0) {
+ if (timespec64_compare(atime, &inode->i_atime) > 0) {
dout("atime %lld.%09ld -> %lld.%09ld inc\n",
- (long long)inode->i_atime.tv_sec,
+ inode->i_atime.tv_sec,
inode->i_atime.tv_nsec,
- (long long)atime->tv_sec, atime->tv_nsec);
- inode->i_atime = atime64;
+ atime->tv_sec, atime->tv_nsec);
+ inode->i_atime = *atime;
}
} else if (issued & CEPH_CAP_FILE_EXCL) {
/* we did a utimes(); ignore mds values */
@@ -715,9 +712,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;
@@ -743,7 +740,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, new_issued, info_caps;
- struct timespec mtime, atime, ctime;
+ struct timespec64 mtime, atime, ctime;
struct ceph_buffer *xattr_blob = NULL;
struct ceph_string *pool_ns = NULL;
struct ceph_cap *new_cap = NULL;
@@ -823,9 +820,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);
@@ -872,7 +869,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
ci->i_rbytes = le64_to_cpu(info->rbytes);
ci->i_rfiles = le64_to_cpu(info->rfiles);
ci->i_rsubdirs = le64_to_cpu(info->rsubdirs);
- ceph_decode_timespec(&ci->i_rctime, &info->rctime);
+ ceph_decode_timespec64(&ci->i_rctime, &info->rctime);
}
}

@@ -1954,7 +1951,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)
@@ -2030,8 +2026,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)

if (ia_valid & ATTR_ATIME) {
dout("setattr %p atime %lld.%ld -> %lld.%ld\n", inode,
- (long long)inode->i_atime.tv_sec, inode->i_atime.tv_nsec,
- (long long)attr->ia_atime.tv_sec, attr->ia_atime.tv_nsec);
+ inode->i_atime.tv_sec, inode->i_atime.tv_nsec,
+ attr->ia_atime.tv_sec, attr->ia_atime.tv_nsec);
if (issued & CEPH_CAP_FILE_EXCL) {
ci->i_time_warp_seq++;
inode->i_atime = attr->ia_atime;
@@ -2043,8 +2039,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_SHARED |
CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR;
@@ -2052,8 +2048,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
}
if (ia_valid & ATTR_MTIME) {
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);
+ inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
+ 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;
@@ -2065,8 +2061,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;
@@ -2097,8 +2093,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
bool only = (ia_valid & (ATTR_SIZE|ATTR_MTIME|ATTR_ATIME|
ATTR_MODE|ATTR_UID|ATTR_GID)) == 0;
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,
+ inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
+ attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec,
only ? "ctime only" : "ignored");
if (only) {
/*
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 69c839316a7a..580644b04737 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -2961,15 +2961,12 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap,
rec.v2.flock_len = (__force __le32)
((ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) ? 0 : 1);
} 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);
}
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index af81555c14fd..041c27ea8de1 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -594,9 +594,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;
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 971328b99ede..3361f17e0cf6 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -193,7 +193,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;
@@ -307,7 +307,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;

@@ -857,8 +857,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,
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 5bc8edb4c2a6..5cc8b94f8206 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -224,8 +224,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);
}

/* quotas */
--
2.9.0


2018-07-13 20:22:43

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH 5/5] ceph: use 64-bit timespec for r_stamp

The ceph_mds_request stamp still uses the deprecated timespec structure,
this converts it over as well.

Signed-off-by: Arnd Bergmann <[email protected]>
---
fs/ceph/inode.c | 2 +-
fs/ceph/mds_client.c | 7 +++----
fs/ceph/mds_client.h | 2 +-
3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 715a6f2a4613..d62f65f2875d 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -2136,7 +2136,7 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
req->r_inode_drop = release;
req->r_args.setattr.mask = cpu_to_le32(mask);
req->r_num_caps = 1;
- req->r_stamp = timespec64_to_timespec(attr->ia_ctime);
+ req->r_stamp = attr->ia_ctime;
err = ceph_mdsc_do_request(mdsc, NULL, req);
}
dout("setattr %p result=%d (%s locally, %d remote)\n", inode, err,
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 580644b04737..09142d309912 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1799,8 +1799,7 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
INIT_LIST_HEAD(&req->r_unsafe_item);

ktime_get_coarse_real_ts64(&ts);
- req->r_stamp = timespec64_to_timespec(timespec64_trunc(ts,
- mdsc->fsc->sb->s_time_gran));
+ req->r_stamp = timespec64_trunc(ts, mdsc->fsc->sb->s_time_gran);

req->r_op = op;
req->r_direct_mode = mode;
@@ -2097,7 +2096,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,
/* time stamp */
{
struct ceph_timespec ts;
- ceph_encode_timespec(&ts, &req->r_stamp);
+ ceph_encode_timespec64(&ts, &req->r_stamp);
ceph_encode_copy(&p, &ts, sizeof(ts));
}

@@ -2190,7 +2189,7 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc,
p = msg->front.iov_base + req->r_request_release_offset;
{
struct ceph_timespec ts;
- ceph_encode_timespec(&ts, &req->r_stamp);
+ ceph_encode_timespec64(&ts, &req->r_stamp);
ceph_encode_copy(&p, &ts, sizeof(ts));
}

diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index 2ec3b5b35067..80a7523e1523 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -229,7 +229,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;
--
2.9.0


2018-07-16 00:47:01

by Yan, Zheng

[permalink] [raw]
Subject: Re: [PATCH 2/5] ceph: stop using current_kernel_time()

The cephfs part (patch 2~5) looks good for me.

Regards
Yan, Zheng


On Sat, Jul 14, 2018 at 4:21 AM Arnd Bergmann <[email protected]> wrote:
>
> ceph_mdsc_create_request() is one of the last callers of the
> deprecated current_kernel_time() as well as timespec_trunc().
>
> This changes it to use the timespec64 based interfaces instead,
> though we still need to convert the result until we are ready to
> change over req->r_stamp.
>
> The output of the two functions, ktime_get_coarse_real_ts64() and
> current_kernel_time() is the same coarse-granular timestamp,
> the only difference here is that ktime_get_coarse_real_ts64()
> doesn't overflow in 2038.
>
> Signed-off-by: Arnd Bergmann <[email protected]>
> ---
> v2: add clarification that this is the same timestamp
> ---
> fs/ceph/mds_client.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
> index dc8bc664a871..69c839316a7a 100644
> --- a/fs/ceph/mds_client.c
> +++ b/fs/ceph/mds_client.c
> @@ -1779,6 +1779,7 @@ struct ceph_mds_request *
> ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
> {
> struct ceph_mds_request *req = kzalloc(sizeof(*req), GFP_NOFS);
> + struct timespec64 ts;
>
> if (!req)
> return ERR_PTR(-ENOMEM);
> @@ -1797,7 +1798,9 @@ 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);
>
> - req->r_stamp = timespec_trunc(current_kernel_time(), mdsc->fsc->sb->s_time_gran);
> + ktime_get_coarse_real_ts64(&ts);
> + req->r_stamp = timespec64_to_timespec(timespec64_trunc(ts,
> + mdsc->fsc->sb->s_time_gran));
>
> req->r_op = op;
> req->r_direct_mode = mode;
> --
> 2.9.0
>
> --
> To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html