afs: Use the operation issue time instead of the reply time for callbacks

[ Upstream commit 7903192c4b4a82d792cb0dc5e2779a2efe60d45b ]

rxrpc and kafs between them try to use the receive timestamp on the first
data packet (ie. the one with sequence number 1) as a base from which to
calculate the time at which callback promise and lock expiration occurs.

However, we don't know how long it took for the server to send us the reply
from it having completed the basic part of the operation - it might then,
for instance, have to send a bunch of a callback breaks, depending on the
particular operation.

Fix this by using the time at which the operation is issued on the client
as a base instead.  That should never be longer than the server's idea of
the expiry time.

Fixes: 781070551c ("afs: Fix calculation of callback expiry time")
Fixes: 2070a3e449 ("rxrpc: Allow the reply time to be obtained on a client call")
Suggested-by: Jeffrey E Altman <jaltman@auristor.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
David Howells 2022-08-31 13:16:42 +01:00 committed by Greg Kroah-Hartman
parent 8077a50c8c
commit a2f0ff5bee
5 changed files with 5 additions and 12 deletions

View File

@ -75,7 +75,7 @@ void afs_lock_op_done(struct afs_call *call)
if (call->error == 0) { if (call->error == 0) {
spin_lock(&vnode->lock); spin_lock(&vnode->lock);
trace_afs_flock_ev(vnode, NULL, afs_flock_timestamp, 0); trace_afs_flock_ev(vnode, NULL, afs_flock_timestamp, 0);
vnode->locked_at = call->reply_time; vnode->locked_at = call->issue_time;
afs_schedule_lock_extension(vnode); afs_schedule_lock_extension(vnode);
spin_unlock(&vnode->lock); spin_unlock(&vnode->lock);
} }

View File

@ -136,7 +136,7 @@ bad:
static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry) static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry)
{ {
return ktime_divns(call->reply_time, NSEC_PER_SEC) + expiry; return ktime_divns(call->issue_time, NSEC_PER_SEC) + expiry;
} }
static void xdr_decode_AFSCallBack(const __be32 **_bp, static void xdr_decode_AFSCallBack(const __be32 **_bp,

View File

@ -159,7 +159,6 @@ struct afs_call {
bool need_attention; /* T if RxRPC poked us */ bool need_attention; /* T if RxRPC poked us */
bool async; /* T if asynchronous */ bool async; /* T if asynchronous */
bool upgrade; /* T to request service upgrade */ bool upgrade; /* T to request service upgrade */
bool have_reply_time; /* T if have got reply_time */
bool intr; /* T if interruptible */ bool intr; /* T if interruptible */
bool unmarshalling_error; /* T if an unmarshalling error occurred */ bool unmarshalling_error; /* T if an unmarshalling error occurred */
u16 service_id; /* Actual service ID (after upgrade) */ u16 service_id; /* Actual service ID (after upgrade) */
@ -173,7 +172,7 @@ struct afs_call {
} __attribute__((packed)); } __attribute__((packed));
__be64 tmp64; __be64 tmp64;
}; };
ktime_t reply_time; /* Time of first reply packet */ ktime_t issue_time; /* Time of issue of operation */
}; };
struct afs_call_type { struct afs_call_type {

View File

@ -428,6 +428,7 @@ void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp)
if (call->max_lifespan) if (call->max_lifespan)
rxrpc_kernel_set_max_life(call->net->socket, rxcall, rxrpc_kernel_set_max_life(call->net->socket, rxcall,
call->max_lifespan); call->max_lifespan);
call->issue_time = ktime_get_real();
/* send the request */ /* send the request */
iov[0].iov_base = call->request; iov[0].iov_base = call->request;
@ -532,12 +533,6 @@ static void afs_deliver_to_call(struct afs_call *call)
return; return;
} }
if (!call->have_reply_time &&
rxrpc_kernel_get_reply_time(call->net->socket,
call->rxcall,
&call->reply_time))
call->have_reply_time = true;
ret = call->type->deliver(call); ret = call->type->deliver(call);
state = READ_ONCE(call->state); state = READ_ONCE(call->state);
if (ret == 0 && call->unmarshalling_error) if (ret == 0 && call->unmarshalling_error)

View File

@ -241,8 +241,7 @@ static void xdr_decode_YFSCallBack(const __be32 **_bp,
struct afs_callback *cb = &scb->callback; struct afs_callback *cb = &scb->callback;
ktime_t cb_expiry; ktime_t cb_expiry;
cb_expiry = call->reply_time; cb_expiry = ktime_add(call->issue_time, xdr_to_u64(x->expiration_time) * 100);
cb_expiry = ktime_add(cb_expiry, xdr_to_u64(x->expiration_time) * 100);
cb->expires_at = ktime_divns(cb_expiry, NSEC_PER_SEC); cb->expires_at = ktime_divns(cb_expiry, NSEC_PER_SEC);
scb->have_cb = true; scb->have_cb = true;
*_bp += xdr_size(x); *_bp += xdr_size(x);