]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/3.10.30/nfsv4-open-must-handle-the-nfs4err_io-return-code-correctly.patch
5.1-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.10.30 / nfsv4-open-must-handle-the-nfs4err_io-return-code-correctly.patch
CommitLineData
53d66ca4
GKH
1From c7848f69ec4a8c03732cde5c949bd2aa711a9f4b Mon Sep 17 00:00:00 2001
2From: Trond Myklebust <Trond.Myklebust@netapp.com>
3Date: Wed, 4 Dec 2013 17:39:23 -0500
4Subject: NFSv4: OPEN must handle the NFS4ERR_IO return code correctly
5
6From: Trond Myklebust <Trond.Myklebust@netapp.com>
7
8commit c7848f69ec4a8c03732cde5c949bd2aa711a9f4b upstream.
9
10decode_op_hdr() cannot distinguish between an XDR decoding error and
11the perfectly valid errorcode NFS4ERR_IO. This is normally not a
12problem, but for the particular case of OPEN, we need to be able
13to increment the NFSv4 open sequence id when the server returns
14a valid response.
15
16Reported-by: J Bruce Fields <bfields@fieldses.org>
17Link: http://lkml.kernel.org/r/20131204210356.GA19452@fieldses.org
18Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
19Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
20
21---
22 fs/nfs/nfs4xdr.c | 47 +++++++++++++++++++++++++++++++----------------
23 1 file changed, 31 insertions(+), 16 deletions(-)
24
25--- a/fs/nfs/nfs4xdr.c
26+++ b/fs/nfs/nfs4xdr.c
27@@ -3002,7 +3002,8 @@ out_overflow:
28 return -EIO;
29 }
30
31-static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
32+static bool __decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected,
33+ int *nfs_retval)
34 {
35 __be32 *p;
36 uint32_t opnum;
37@@ -3012,19 +3013,32 @@ static int decode_op_hdr(struct xdr_stre
38 if (unlikely(!p))
39 goto out_overflow;
40 opnum = be32_to_cpup(p++);
41- if (opnum != expected) {
42- dprintk("nfs: Server returned operation"
43- " %d but we issued a request for %d\n",
44- opnum, expected);
45- return -EIO;
46- }
47+ if (unlikely(opnum != expected))
48+ goto out_bad_operation;
49 nfserr = be32_to_cpup(p);
50- if (nfserr != NFS_OK)
51- return nfs4_stat_to_errno(nfserr);
52- return 0;
53+ if (nfserr == NFS_OK)
54+ *nfs_retval = 0;
55+ else
56+ *nfs_retval = nfs4_stat_to_errno(nfserr);
57+ return true;
58+out_bad_operation:
59+ dprintk("nfs: Server returned operation"
60+ " %d but we issued a request for %d\n",
61+ opnum, expected);
62+ *nfs_retval = -EREMOTEIO;
63+ return false;
64 out_overflow:
65 print_overflow_msg(__func__, xdr);
66- return -EIO;
67+ *nfs_retval = -EIO;
68+ return false;
69+}
70+
71+static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
72+{
73+ int retval;
74+
75+ __decode_op_hdr(xdr, expected, &retval);
76+ return retval;
77 }
78
79 /* Dummy routine */
80@@ -4842,11 +4856,12 @@ static int decode_open(struct xdr_stream
81 uint32_t savewords, bmlen, i;
82 int status;
83
84- status = decode_op_hdr(xdr, OP_OPEN);
85- if (status != -EIO)
86- nfs_increment_open_seqid(status, res->seqid);
87- if (!status)
88- status = decode_stateid(xdr, &res->stateid);
89+ if (!__decode_op_hdr(xdr, OP_OPEN, &status))
90+ return status;
91+ nfs_increment_open_seqid(status, res->seqid);
92+ if (status)
93+ return status;
94+ status = decode_stateid(xdr, &res->stateid);
95 if (unlikely(status))
96 return status;
97