Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

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: 781070551c26 ("afs: Fix calculation of callback expiry time")
Fixes: 2070a3e44962 ("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>

+5 -12
+1 -1
fs/afs/flock.c
··· 76 76 if (call->error == 0) { 77 77 spin_lock(&vnode->lock); 78 78 trace_afs_flock_ev(vnode, NULL, afs_flock_timestamp, 0); 79 - vnode->locked_at = call->reply_time; 79 + vnode->locked_at = call->issue_time; 80 80 afs_schedule_lock_extension(vnode); 81 81 spin_unlock(&vnode->lock); 82 82 }
+1 -1
fs/afs/fsclient.c
··· 131 131 132 132 static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry) 133 133 { 134 - return ktime_divns(call->reply_time, NSEC_PER_SEC) + expiry; 134 + return ktime_divns(call->issue_time, NSEC_PER_SEC) + expiry; 135 135 } 136 136 137 137 static void xdr_decode_AFSCallBack(const __be32 **_bp,
+1 -2
fs/afs/internal.h
··· 137 137 bool need_attention; /* T if RxRPC poked us */ 138 138 bool async; /* T if asynchronous */ 139 139 bool upgrade; /* T to request service upgrade */ 140 - bool have_reply_time; /* T if have got reply_time */ 141 140 bool intr; /* T if interruptible */ 142 141 bool unmarshalling_error; /* T if an unmarshalling error occurred */ 143 142 u16 service_id; /* Actual service ID (after upgrade) */ ··· 150 151 } __attribute__((packed)); 151 152 __be64 tmp64; 152 153 }; 153 - ktime_t reply_time; /* Time of first reply packet */ 154 + ktime_t issue_time; /* Time of issue of operation */ 154 155 }; 155 156 156 157 struct afs_call_type {
+1 -6
fs/afs/rxrpc.c
··· 351 351 if (call->max_lifespan) 352 352 rxrpc_kernel_set_max_life(call->net->socket, rxcall, 353 353 call->max_lifespan); 354 + call->issue_time = ktime_get_real(); 354 355 355 356 /* send the request */ 356 357 iov[0].iov_base = call->request; ··· 501 500 } 502 501 return; 503 502 } 504 - 505 - if (!call->have_reply_time && 506 - rxrpc_kernel_get_reply_time(call->net->socket, 507 - call->rxcall, 508 - &call->reply_time)) 509 - call->have_reply_time = true; 510 503 511 504 ret = call->type->deliver(call); 512 505 state = READ_ONCE(call->state);
+1 -2
fs/afs/yfsclient.c
··· 232 232 struct afs_callback *cb = &scb->callback; 233 233 ktime_t cb_expiry; 234 234 235 - cb_expiry = call->reply_time; 236 - cb_expiry = ktime_add(cb_expiry, xdr_to_u64(x->expiration_time) * 100); 235 + cb_expiry = ktime_add(call->issue_time, xdr_to_u64(x->expiration_time) * 100); 237 236 cb->expires_at = ktime_divns(cb_expiry, NSEC_PER_SEC); 238 237 scb->have_cb = true; 239 238 *_bp += xdr_size(x);