diff options
author | David Howells <dhowells@redhat.com> | 2019-05-09 17:17:05 +0200 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2019-05-16 17:25:21 +0200 |
commit | 87182759cd6f94875d6aaaac74eaa52aa6aa6f98 (patch) | |
tree | 3a143ae4a411fd26b1d98bffff3f66770e027901 /fs/afs/yfsclient.c | |
parent | afs: Get rid of afs_call::reply[] (diff) | |
download | linux-87182759cd6f94875d6aaaac74eaa52aa6aa6f98.tar.xz linux-87182759cd6f94875d6aaaac74eaa52aa6aa6f98.zip |
afs: Fix order-1 allocation in afs_do_lookup()
afs_do_lookup() will do an order-1 allocation to allocate status records if
there are more than 39 vnodes to stat.
Fix this by allocating an array of {status,callback} records for each vnode
we want to examine using vmalloc() if larger than a page.
This not only gets rid of the order-1 allocation, but makes it easier to
grow beyond 50 records for YFS servers. It also allows us to move to
{status,callback} tuples for other calls too and makes it easier to lock
across the application of the status and the callback to the vnode.
Fixes: 5cf9dd55a0ec ("afs: Prospectively look up extra files when doing a single lookup")
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/afs/yfsclient.c')
-rw-r--r-- | fs/afs/yfsclient.c | 20 |
1 files changed, 9 insertions, 11 deletions
diff --git a/fs/afs/yfsclient.c b/fs/afs/yfsclient.c index a815d22f62f1..1f1ccf7b7822 100644 --- a/fs/afs/yfsclient.c +++ b/fs/afs/yfsclient.c @@ -338,7 +338,7 @@ static void xdr_decode_YFSCallBack(struct afs_call *call, struct afs_callback cb; xdr_decode_YFSCallBack_raw(call, &cb, _bp); - + write_seqlock(&vnode->cb_lock); if (!afs_cb_is_broken(call->cb_break, vnode, cbi)) { @@ -2032,8 +2032,7 @@ int yfs_fs_fetch_status(struct afs_fs_cursor *fc, */ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call) { - struct afs_file_status *statuses; - struct afs_callback *callbacks; + struct afs_status_cb *scb; const __be32 *bp; u32 tmp; int ret; @@ -2072,8 +2071,8 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call) return ret; bp = call->buffer; - statuses = call->out_extra_status; - ret = yfs_decode_status(call, &bp, &statuses[call->count], + scb = &call->out_scb[call->count]; + ret = yfs_decode_status(call, &bp, &scb->status, NULL, NULL, NULL); if (ret < 0) return ret; @@ -2113,8 +2112,9 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call) _debug("unmarshall CB array"); bp = call->buffer; - callbacks = call->out_cb; - xdr_decode_YFSCallBack_raw(call, &callbacks[call->count], &bp); + scb = &call->out_scb[call->count]; + xdr_decode_YFSCallBack_raw(call, &scb->callback, &bp); + scb->have_cb = true; call->count++; if (call->count < call->count2) goto more_cbs; @@ -2158,8 +2158,7 @@ static const struct afs_call_type yfs_RXYFSInlineBulkStatus = { int yfs_fs_inline_bulk_status(struct afs_fs_cursor *fc, struct afs_net *net, struct afs_fid *fids, - struct afs_file_status *statuses, - struct afs_callback *callbacks, + struct afs_status_cb *statuses, unsigned int nr_fids, struct afs_volsync *volsync) { @@ -2182,8 +2181,7 @@ int yfs_fs_inline_bulk_status(struct afs_fs_cursor *fc, } call->key = fc->key; - call->out_extra_status = statuses; - call->out_cb = callbacks; + call->out_scb = statuses; call->out_volsync = volsync; call->count2 = nr_fids; |