diff options
author | David Howells <dhowells@redhat.com> | 2018-10-20 01:57:58 +0200 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2018-10-24 01:41:08 +0200 |
commit | 12d8e95a911eb3921a1fecf1e4d913654f6f4fb5 (patch) | |
tree | fc9823c56bfaac4b746c3d3f84bd7470b07b7ee4 /fs/afs | |
parent | afs: Fix FS.FetchStatus delivery from updating wrong vnode (diff) | |
download | linux-12d8e95a911eb3921a1fecf1e4d913654f6f4fb5.tar.xz linux-12d8e95a911eb3921a1fecf1e4d913654f6f4fb5.zip |
afs: Calc callback expiry in op reply delivery
Calculate the callback expiration time at the point of operation reply
delivery, using the reply time queried from AF_RXRPC on that call as a
base.
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/afs')
-rw-r--r-- | fs/afs/afs.h | 2 | ||||
-rw-r--r-- | fs/afs/fsclient.c | 22 | ||||
-rw-r--r-- | fs/afs/inode.c | 4 | ||||
-rw-r--r-- | fs/afs/internal.h | 2 | ||||
-rw-r--r-- | fs/afs/rxrpc.c | 6 |
5 files changed, 28 insertions, 8 deletions
diff --git a/fs/afs/afs.h b/fs/afs/afs.h index fb9bcb8758ea..417cd23529c5 100644 --- a/fs/afs/afs.h +++ b/fs/afs/afs.h @@ -68,8 +68,8 @@ typedef enum { } afs_callback_type_t; struct afs_callback { + time64_t expires_at; /* Time at which expires */ unsigned version; /* Callback version */ - unsigned expiry; /* Time at which expires */ afs_callback_type_t type; /* Type of callback */ }; diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index f758750e81d8..6105cdb17163 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c @@ -287,13 +287,19 @@ static void xdr_decode_AFSCallBack(struct afs_call *call, *_bp = bp; } -static void xdr_decode_AFSCallBack_raw(const __be32 **_bp, +static ktime_t xdr_decode_expiry(struct afs_call *call, u32 expiry) +{ + return ktime_add_ns(call->reply_time, expiry * NSEC_PER_SEC); +} + +static void xdr_decode_AFSCallBack_raw(struct afs_call *call, + const __be32 **_bp, struct afs_callback *cb) { const __be32 *bp = *_bp; cb->version = ntohl(*bp++); - cb->expiry = ntohl(*bp++); + cb->expires_at = xdr_decode_expiry(call, ntohl(*bp++)); cb->type = ntohl(*bp++); *_bp = bp; } @@ -440,6 +446,7 @@ int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy call->reply[0] = vnode; call->reply[1] = volsync; call->expected_version = new_inode ? 1 : vnode->status.data_version; + call->want_reply_time = true; /* marshall the parameters */ bp = call->request; @@ -627,6 +634,7 @@ static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req) call->reply[1] = NULL; /* volsync */ call->reply[2] = req; call->expected_version = vnode->status.data_version; + call->want_reply_time = true; /* marshall the parameters */ bp = call->request; @@ -672,6 +680,7 @@ int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req) call->reply[1] = NULL; /* volsync */ call->reply[2] = req; call->expected_version = vnode->status.data_version; + call->want_reply_time = true; /* marshall the parameters */ bp = call->request; @@ -714,7 +723,7 @@ static int afs_deliver_fs_create_vnode(struct afs_call *call) &call->expected_version, NULL); if (ret < 0) return ret; - xdr_decode_AFSCallBack_raw(&bp, call->reply[3]); + xdr_decode_AFSCallBack_raw(call, &bp, call->reply[3]); /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ _leave(" = 0 [done]"); @@ -773,6 +782,7 @@ int afs_fs_create(struct afs_fs_cursor *fc, call->reply[2] = newstatus; call->reply[3] = newcb; call->expected_version = current_data_version + 1; + call->want_reply_time = true; /* marshall the parameters */ bp = call->request; @@ -2042,7 +2052,7 @@ static int afs_deliver_fs_fetch_status(struct afs_call *call) &call->expected_version, NULL); if (ret < 0) return ret; - xdr_decode_AFSCallBack_raw(&bp, callback); + xdr_decode_AFSCallBack_raw(call, &bp, callback); if (volsync) xdr_decode_AFSVolSync(&bp, volsync); @@ -2088,6 +2098,7 @@ int afs_fs_fetch_status(struct afs_fs_cursor *fc, call->reply[2] = callback; call->reply[3] = volsync; call->expected_version = 1; /* vnode->status.data_version */ + call->want_reply_time = true; /* marshall the parameters */ bp = call->request; @@ -2188,7 +2199,7 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) bp = call->buffer; callbacks = call->reply[2]; callbacks[call->count].version = ntohl(bp[0]); - callbacks[call->count].expiry = ntohl(bp[1]); + callbacks[call->count].expires_at = xdr_decode_expiry(call, ntohl(bp[1])); callbacks[call->count].type = ntohl(bp[2]); statuses = call->reply[1]; if (call->count == 0 && vnode && statuses[0].abort_code == 0) @@ -2261,6 +2272,7 @@ int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc, call->reply[2] = callbacks; call->reply[3] = volsync; call->count2 = nr_fids; + call->want_reply_time = true; /* marshall the parameters */ bp = call->request; diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 4ba47efe9668..4c6d8e1112c2 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -317,11 +317,11 @@ struct inode *afs_iget(struct super_block *sb, struct key *key, * didn't give us a callback) */ vnode->cb_version = 0; vnode->cb_type = 0; - vnode->cb_expires_at = 0; + vnode->cb_expires_at = ktime_get(); } else { vnode->cb_version = cb->version; vnode->cb_type = cb->type; - vnode->cb_expires_at = cb->expiry; + vnode->cb_expires_at = cb->expires_at; vnode->cb_interest = afs_get_cb_interest(cbi); set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); } diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 28d08aac515d..78065af05153 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -131,6 +131,7 @@ struct afs_call { bool async; /* T if asynchronous */ bool ret_reply0; /* T if should return reply[0] on success */ bool upgrade; /* T to request service upgrade */ + bool want_reply_time; /* T if want reply_time */ u16 service_id; /* Actual service ID (after upgrade) */ unsigned int debug_id; /* Trace ID */ u32 operation_ID; /* operation ID for an incoming call */ @@ -144,6 +145,7 @@ struct afs_call { }; afs_dataversion_t expected_version; /* Updated version expected from store */ afs_dataversion_t expected_version_2; /* 2nd updated version expected from store */ + ktime_t reply_time; /* Time of first reply packet */ }; struct afs_call_type { diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index ce98e133caa6..444ba0d511ef 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -499,6 +499,12 @@ static void afs_deliver_to_call(struct afs_call *call) return; } + if (call->want_reply_time && + rxrpc_kernel_get_reply_time(call->net->socket, + call->rxcall, + &call->reply_time)) + call->want_reply_time = false; + ret = call->type->deliver(call); state = READ_ONCE(call->state); switch (ret) { |