lkml.org 
[lkml]   [2020]   [Jun]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 272/314] afs: Set error flag rather than return error from file status decode
    Date
    From: David Howells <dhowells@redhat.com>

    [ Upstream commit 38355eec6a7d2b8f2f313f9174736dc877744e59 ]

    Set a flag in the call struct to indicate an unmarshalling error rather
    than return and handle an error from the decoding of file statuses. This
    flag is checked on a successful return from the delivery function.

    Signed-off-by: David Howells <dhowells@redhat.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/afs/fsclient.c | 88 +++++++++++++---------------------------------
    fs/afs/internal.h | 1 +
    fs/afs/rxrpc.c | 4 +++
    fs/afs/yfsclient.c | 85 +++++++++++++-------------------------------
    4 files changed, 55 insertions(+), 123 deletions(-)

    diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
    index 0a4fed9e706b7..5c2729fc07e52 100644
    --- a/fs/afs/fsclient.c
    +++ b/fs/afs/fsclient.c
    @@ -56,16 +56,15 @@ static void xdr_dump_bad(const __be32 *bp)
    /*
    * decode an AFSFetchStatus block
    */
    -static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
    - struct afs_call *call,
    - struct afs_status_cb *scb)
    +static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
    + struct afs_call *call,
    + struct afs_status_cb *scb)
    {
    const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp;
    struct afs_file_status *status = &scb->status;
    bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus);
    u64 data_version, size;
    u32 type, abort_code;
    - int ret;

    abort_code = ntohl(xdr->abort_code);

    @@ -79,7 +78,7 @@ static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
    */
    status->abort_code = abort_code;
    scb->have_error = true;
    - goto good;
    + goto advance;
    }

    pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
    @@ -89,7 +88,7 @@ static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
    if (abort_code != 0 && inline_error) {
    status->abort_code = abort_code;
    scb->have_error = true;
    - goto good;
    + goto advance;
    }

    type = ntohl(xdr->type);
    @@ -125,15 +124,13 @@ static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
    data_version |= (u64)ntohl(xdr->data_version_hi) << 32;
    status->data_version = data_version;
    scb->have_status = true;
    -good:
    - ret = 0;
    advance:
    *_bp = (const void *)*_bp + sizeof(*xdr);
    - return ret;
    + return;

    bad:
    xdr_dump_bad(*_bp);
    - ret = afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
    + afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
    goto advance;
    }

    @@ -254,9 +251,7 @@ static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call)

    /* unmarshall the reply once we've received all of it */
    bp = call->buffer;
    - ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    xdr_decode_AFSCallBack(&bp, call, call->out_scb);
    xdr_decode_AFSVolSync(&bp, call->out_volsync);

    @@ -419,9 +414,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
    return ret;

    bp = call->buffer;
    - ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    xdr_decode_AFSCallBack(&bp, call, call->out_scb);
    xdr_decode_AFSVolSync(&bp, call->out_volsync);

    @@ -579,12 +572,8 @@ static int afs_deliver_fs_create_vnode(struct afs_call *call)
    /* unmarshall the reply once we've received all of it */
    bp = call->buffer;
    xdr_decode_AFSFid(&bp, call->out_fid);
    - ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    - ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    + xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
    xdr_decode_AFSCallBack(&bp, call, call->out_scb);
    xdr_decode_AFSVolSync(&bp, call->out_volsync);

    @@ -693,9 +682,7 @@ static int afs_deliver_fs_dir_status_and_vol(struct afs_call *call)

    /* unmarshall the reply once we've received all of it */
    bp = call->buffer;
    - ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
    xdr_decode_AFSVolSync(&bp, call->out_volsync);

    _leave(" = 0 [done]");
    @@ -786,12 +773,8 @@ static int afs_deliver_fs_link(struct afs_call *call)

    /* unmarshall the reply once we've received all of it */
    bp = call->buffer;
    - ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    - ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    + xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
    xdr_decode_AFSVolSync(&bp, call->out_volsync);

    _leave(" = 0 [done]");
    @@ -880,12 +863,8 @@ static int afs_deliver_fs_symlink(struct afs_call *call)
    /* unmarshall the reply once we've received all of it */
    bp = call->buffer;
    xdr_decode_AFSFid(&bp, call->out_fid);
    - ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    - ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    + xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
    xdr_decode_AFSVolSync(&bp, call->out_volsync);

    _leave(" = 0 [done]");
    @@ -988,16 +967,12 @@ static int afs_deliver_fs_rename(struct afs_call *call)
    if (ret < 0)
    return ret;

    + bp = call->buffer;
    /* If the two dirs are the same, we have two copies of the same status
    * report, so we just decode it twice.
    */
    - bp = call->buffer;
    - ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
    - if (ret < 0)
    - return ret;
    - ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb);
    + xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    xdr_decode_AFSVolSync(&bp, call->out_volsync);

    _leave(" = 0 [done]");
    @@ -1105,9 +1080,7 @@ static int afs_deliver_fs_store_data(struct afs_call *call)

    /* unmarshall the reply once we've received all of it */
    bp = call->buffer;
    - ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    xdr_decode_AFSVolSync(&bp, call->out_volsync);

    _leave(" = 0 [done]");
    @@ -1285,9 +1258,7 @@ static int afs_deliver_fs_store_status(struct afs_call *call)

    /* unmarshall the reply once we've received all of it */
    bp = call->buffer;
    - ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    xdr_decode_AFSVolSync(&bp, call->out_volsync);

    _leave(" = 0 [done]");
    @@ -1956,9 +1927,7 @@ static int afs_deliver_fs_fetch_status(struct afs_call *call)

    /* unmarshall the reply once we've received all of it */
    bp = call->buffer;
    - ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    xdr_decode_AFSCallBack(&bp, call, call->out_scb);
    xdr_decode_AFSVolSync(&bp, call->out_volsync);

    @@ -2064,10 +2033,7 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)

    bp = call->buffer;
    scb = &call->out_scb[call->count];
    - ret = xdr_decode_AFSFetchStatus(&bp, call, scb);
    - if (ret < 0)
    - return ret;
    -
    + xdr_decode_AFSFetchStatus(&bp, call, scb);
    call->count++;
    if (call->count < call->count2)
    goto more_counts;
    @@ -2245,9 +2211,7 @@ static int afs_deliver_fs_fetch_acl(struct afs_call *call)
    return ret;

    bp = call->buffer;
    - ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    xdr_decode_AFSVolSync(&bp, call->out_volsync);

    call->unmarshall++;
    @@ -2328,9 +2292,7 @@ static int afs_deliver_fs_file_status_and_vol(struct afs_call *call)
    return ret;

    bp = call->buffer;
    - ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_AFSFetchStatus(&bp, call, call->out_scb);
    xdr_decode_AFSVolSync(&bp, call->out_volsync);

    _leave(" = 0 [done]");
    diff --git a/fs/afs/internal.h b/fs/afs/internal.h
    index 485cc3b2aaa8a..555ad7c9afcb6 100644
    --- a/fs/afs/internal.h
    +++ b/fs/afs/internal.h
    @@ -161,6 +161,7 @@ struct afs_call {
    bool upgrade; /* T to request service upgrade */
    bool have_reply_time; /* T if have got reply_time */
    bool intr; /* T if interruptible */
    + bool unmarshalling_error; /* T if an unmarshalling error occurred */
    u16 service_id; /* Actual service ID (after upgrade) */
    unsigned int debug_id; /* Trace ID */
    u32 operation_ID; /* operation ID for an incoming call */
    diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
    index 52aa90fb4fbd9..6adab30a83993 100644
    --- a/fs/afs/rxrpc.c
    +++ b/fs/afs/rxrpc.c
    @@ -540,6 +540,8 @@ static void afs_deliver_to_call(struct afs_call *call)

    ret = call->type->deliver(call);
    state = READ_ONCE(call->state);
    + if (ret == 0 && call->unmarshalling_error)
    + ret = -EBADMSG;
    switch (ret) {
    case 0:
    afs_queue_call_work(call);
    @@ -963,5 +965,7 @@ noinline int afs_protocol_error(struct afs_call *call, int error,
    enum afs_eproto_cause cause)
    {
    trace_afs_protocol_error(call, error, cause);
    + if (call)
    + call->unmarshalling_error = true;
    return error;
    }
    diff --git a/fs/afs/yfsclient.c b/fs/afs/yfsclient.c
    index 8af7f093305d8..d21cf61d86b9f 100644
    --- a/fs/afs/yfsclient.c
    +++ b/fs/afs/yfsclient.c
    @@ -179,21 +179,20 @@ static void xdr_dump_bad(const __be32 *bp)
    /*
    * Decode a YFSFetchStatus block
    */
    -static int xdr_decode_YFSFetchStatus(const __be32 **_bp,
    - struct afs_call *call,
    - struct afs_status_cb *scb)
    +static void xdr_decode_YFSFetchStatus(const __be32 **_bp,
    + struct afs_call *call,
    + struct afs_status_cb *scb)
    {
    const struct yfs_xdr_YFSFetchStatus *xdr = (const void *)*_bp;
    struct afs_file_status *status = &scb->status;
    u32 type;
    - int ret;

    status->abort_code = ntohl(xdr->abort_code);
    if (status->abort_code != 0) {
    if (status->abort_code == VNOVNODE)
    status->nlink = 0;
    scb->have_error = true;
    - goto good;
    + goto advance;
    }

    type = ntohl(xdr->type);
    @@ -221,15 +220,13 @@ static int xdr_decode_YFSFetchStatus(const __be32 **_bp,
    status->size = xdr_to_u64(xdr->size);
    status->data_version = xdr_to_u64(xdr->data_version);
    scb->have_status = true;
    -good:
    - ret = 0;
    advance:
    *_bp += xdr_size(xdr);
    - return ret;
    + return;

    bad:
    xdr_dump_bad(*_bp);
    - ret = afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
    + afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status);
    goto advance;
    }

    @@ -348,9 +345,7 @@ static int yfs_deliver_fs_status_cb_and_volsync(struct afs_call *call)

    /* unmarshall the reply once we've received all of it */
    bp = call->buffer;
    - ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    xdr_decode_YFSCallBack(&bp, call, call->out_scb);
    xdr_decode_YFSVolSync(&bp, call->out_volsync);

    @@ -372,9 +367,7 @@ static int yfs_deliver_status_and_volsync(struct afs_call *call)
    return ret;

    bp = call->buffer;
    - ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    xdr_decode_YFSVolSync(&bp, call->out_volsync);

    _leave(" = 0 [done]");
    @@ -534,9 +527,7 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
    return ret;

    bp = call->buffer;
    - ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    xdr_decode_YFSCallBack(&bp, call, call->out_scb);
    xdr_decode_YFSVolSync(&bp, call->out_volsync);

    @@ -645,12 +636,8 @@ static int yfs_deliver_fs_create_vnode(struct afs_call *call)
    /* unmarshall the reply once we've received all of it */
    bp = call->buffer;
    xdr_decode_YFSFid(&bp, call->out_fid);
    - ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    - ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    + xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
    xdr_decode_YFSCallBack(&bp, call, call->out_scb);
    xdr_decode_YFSVolSync(&bp, call->out_volsync);

    @@ -803,14 +790,9 @@ static int yfs_deliver_fs_remove_file2(struct afs_call *call)
    return ret;

    bp = call->buffer;
    - ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
    - if (ret < 0)
    - return ret;
    -
    + xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
    xdr_decode_YFSFid(&bp, &fid);
    - ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    /* Was deleted if vnode->status.abort_code == VNOVNODE. */

    xdr_decode_YFSVolSync(&bp, call->out_volsync);
    @@ -890,10 +872,7 @@ static int yfs_deliver_fs_remove(struct afs_call *call)
    return ret;

    bp = call->buffer;
    - ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
    - if (ret < 0)
    - return ret;
    -
    + xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
    xdr_decode_YFSVolSync(&bp, call->out_volsync);
    return 0;
    }
    @@ -975,12 +954,8 @@ static int yfs_deliver_fs_link(struct afs_call *call)
    return ret;

    bp = call->buffer;
    - ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    - ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    + xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
    xdr_decode_YFSVolSync(&bp, call->out_volsync);
    _leave(" = 0 [done]");
    return 0;
    @@ -1062,12 +1037,8 @@ static int yfs_deliver_fs_symlink(struct afs_call *call)
    /* unmarshall the reply once we've received all of it */
    bp = call->buffer;
    xdr_decode_YFSFid(&bp, call->out_fid);
    - ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    - ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    + xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
    xdr_decode_YFSVolSync(&bp, call->out_volsync);

    _leave(" = 0 [done]");
    @@ -1155,13 +1126,11 @@ static int yfs_deliver_fs_rename(struct afs_call *call)
    return ret;

    bp = call->buffer;
    - ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
    - if (ret < 0)
    - return ret;
    - ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    -
    + /* If the two dirs are the same, we have two copies of the same status
    + * report, so we just decode it twice.
    + */
    + xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb);
    + xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    xdr_decode_YFSVolSync(&bp, call->out_volsync);
    _leave(" = 0 [done]");
    return 0;
    @@ -1846,9 +1815,7 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call)

    bp = call->buffer;
    scb = &call->out_scb[call->count];
    - ret = xdr_decode_YFSFetchStatus(&bp, call, scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_YFSFetchStatus(&bp, call, scb);

    call->count++;
    if (call->count < call->count2)
    @@ -2068,9 +2035,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call)
    bp = call->buffer;
    yacl->inherit_flag = ntohl(*bp++);
    yacl->num_cleaned = ntohl(*bp++);
    - ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    - if (ret < 0)
    - return ret;
    + xdr_decode_YFSFetchStatus(&bp, call, call->out_scb);
    xdr_decode_YFSVolSync(&bp, call->out_volsync);

    call->unmarshall++;
    --
    2.25.1


    \
     
     \ /
      Last update: 2020-06-23 23:12    [W:4.824 / U:0.864 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site