提交 684b0f68 编写于 作者: D David Howells

afs: Fix AFSFetchStatus decoder to provide OpenAFS compatibility

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: dd9fbcb8 ("afs: Rearrange status mapping")
Reported-by: NJeffrey Altman <jaltman@auristor.com>
Signed-off-by: NDavid Howells <dhowells@redhat.com>
上级 ec5a3b4b
......@@ -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;
......@@ -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:
......@@ -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;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册