Commit 38355eec authored by David Howells's avatar David Howells
Browse files

afs: Set error flag rather than return error from file status decode



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: default avatarDavid Howells <dhowells@redhat.com>
parent 8230fd82
Loading
Loading
Loading
Loading
+25 −63
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ static void xdr_dump_bad(const __be32 *bp)
/*
 * decode an AFSFetchStatus block
 */
static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
				      struct afs_call *call,
				      struct afs_status_cb *scb)
{
@@ -65,7 +65,6 @@ static int xdr_decode_AFSFetchStatus(const __be32 **_bp,
	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);

@@ -577,12 +570,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);

@@ -691,9 +680,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]");
@@ -784,12 +771,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]");
@@ -878,12 +861,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]");
@@ -986,16 +965,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]");
@@ -1103,9 +1078,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]");
@@ -1283,9 +1256,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]");
@@ -1952,9 +1923,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);

@@ -2060,10 +2029,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;
@@ -2241,9 +2207,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++;
@@ -2324,9 +2288,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]");
+1 −0
Original line number Diff line number Diff line
@@ -160,6 +160,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 */
+4 −0
Original line number Diff line number Diff line
@@ -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;
}
+25 −60
Original line number Diff line number Diff line
@@ -179,21 +179,20 @@ static void xdr_dump_bad(const __be32 *bp)
/*
 * Decode a YFSFetchStatus block
 */
static int xdr_decode_YFSFetchStatus(const __be32 **_bp,
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);

@@ -644,12 +635,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);

@@ -802,14 +789,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);
@@ -889,10 +871,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;
}
@@ -974,12 +953,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;
@@ -1061,12 +1036,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]");
@@ -1154,13 +1125,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;
@@ -1845,9 +1814,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)
@@ -2067,9 +2034,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++;