summaryrefslogtreecommitdiffstats
path: root/fs/afs/fsclient.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-05-09 16:17:05 +0100
committerDavid Howells <dhowells@redhat.com>2019-05-16 16:25:21 +0100
commit87182759cd6f94875d6aaaac74eaa52aa6aa6f98 (patch)
tree3a143ae4a411fd26b1d98bffff3f66770e027901 /fs/afs/fsclient.c
parentffba718e935402e7f42b8cd5d1e00e4a3907d361 (diff)
downloadlinux-stable-87182759cd6f94875d6aaaac74eaa52aa6aa6f98.tar.gz
linux-stable-87182759cd6f94875d6aaaac74eaa52aa6aa6f98.tar.bz2
linux-stable-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/fsclient.c')
-rw-r--r--fs/afs/fsclient.c21
1 files changed, 9 insertions, 12 deletions
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 16bcc578e3b2..eeba2a359fb4 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -2209,8 +2209,7 @@ int afs_fs_fetch_status(struct afs_fs_cursor *fc,
*/
static int afs_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;
@@ -2249,8 +2248,8 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
return ret;
bp = call->buffer;
- statuses = call->out_extra_status;
- ret = afs_decode_status(call, &bp, &statuses[call->count],
+ scb = &call->out_scb[call->count];
+ ret = afs_decode_status(call, &bp, &scb->status,
NULL, NULL, NULL);
if (ret < 0)
return ret;
@@ -2290,9 +2289,9 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
_debug("unmarshall CB array");
bp = call->buffer;
- callbacks = call->out_cb;
- xdr_decode_AFSCallBack_raw(call, &callbacks[call->count], &bp);
- statuses = call->out_extra_status;
+ scb = &call->out_scb[call->count];
+ xdr_decode_AFSCallBack_raw(call, &scb->callback, &bp);
+ scb->have_cb = true;
call->count++;
if (call->count < call->count2)
goto more_cbs;
@@ -2335,8 +2334,7 @@ static const struct afs_call_type afs_RXFSInlineBulkStatus = {
int afs_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)
{
@@ -2345,7 +2343,7 @@ int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
int i;
if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
- return yfs_fs_inline_bulk_status(fc, net, fids, statuses, callbacks,
+ return yfs_fs_inline_bulk_status(fc, net, fids, statuses,
nr_fids, volsync);
_enter(",%x,{%llx:%llu},%u",
@@ -2360,8 +2358,7 @@ int afs_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;
call->want_reply_time = true;