Skip to content

Commit

Permalink
afs: Fix AFSFetchStatus decoder to provide OpenAFS compatibility
Browse files Browse the repository at this point in the history
The OpenAFS server's RXAFS_InlineBulkStatus implementation has a bug
whereby if an error occurs on one of the vnodes being queried, then the
errorCode field is set correctly in the corresponding status, but the
interfaceVersion field is left unset.

Fix kAFS to deal with this by evaluating the AFSFetchStatus blob against
the following cases when called from FS.InlineBulkStatus delivery:

 (1) If InterfaceVersion == 0 then:

     (a) If errorCode != 0 then it indicates the abort code for the
         corresponding vnode.

     (b) If errorCode == 0 then the status record is invalid.

 (2) If InterfaceVersion == 1 then:

     (a) If errorCode != 0 then it indicates the abort code for the
         corresponding vnode.

     (b) If errorCode == 0 then the status record is valid and can be
     	 parsed.

 (3) If InterfaceVersion is anything else then the status record is
     invalid.

Fixes: dd9fbcb ("afs: Rearrange status mapping")
Reported-by: Jeffrey Altman <jaltman@auristor.com>
Signed-off-by: David Howells <dhowells@redhat.com>
  • Loading branch information
David Howells committed May 14, 2018
1 parent ec5a3b4 commit 684b0f6
Showing 1 changed file with 21 additions and 8 deletions.
29 changes: 21 additions & 8 deletions fs/afs/fsclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
struct afs_read *read_req)
{
const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp;
bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus);
u64 data_version, size;
u32 type, abort_code;
u8 flags = 0;
Expand All @@ -142,13 +143,32 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
if (vnode)
write_seqlock(&vnode->cb_lock);

abort_code = ntohl(xdr->abort_code);

if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) {
if (xdr->if_version == htonl(0) &&
abort_code != 0 &&
inline_error) {
/* The OpenAFS fileserver has a bug in FS.InlineBulkStatus
* whereby it doesn't set the interface version in the error
* case.
*/
status->abort_code = abort_code;
ret = 0;
goto out;
}

pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
goto bad;
}

if (abort_code != 0 && inline_error) {
status->abort_code = abort_code;
ret = 0;
goto out;
}

type = ntohl(xdr->type);
abort_code = ntohl(xdr->abort_code);
switch (type) {
case AFS_FTYPE_FILE:
case AFS_FTYPE_DIR:
Expand All @@ -165,13 +185,6 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
}
status->type = type;
break;
case AFS_FTYPE_INVALID:
if (abort_code != 0) {
status->abort_code = abort_code;
ret = 0;
goto out;
}
/* Fall through */
default:
goto bad;
}
Expand Down

0 comments on commit 684b0f6

Please sign in to comment.