aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2009-06-17 21:02:12 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2009-06-17 21:02:12 -0400
commitfb12529577541aa02f9c3d9e325329f9568dfb58 (patch)
tree96d9c7e9f95b830679e211e92841a6ac0c42f1b8 /fs
parent99835db430904e90c0640ebc6b91cd2a90a118f7 (diff)
NFS: Add separate mountd status code decoders for each mountd version
Introduce data structures and xdr_stream-based decoding functions for unmarshalling mountd status codes properly. Mountd version 3 uses specific standard error return codes that are not errno values and not NFS3ERR_ values. These have a well-defined standard mapping to local errno values. Introduce data structures and a decoder function that map these status codes to local errno values properly. This is new functionality (but not used yet). Version 1 mountd status values are defined by RFC 1094 as UNIX error values (errno values). Errno values on heterogeneous systems do not necessarily match each other. To avoid exposing possibly incorrect errno values to upper layers, the current XDR decoder converts all non-zero MNT version 1 status codes to -EACCES. The OpenGroup XNFS standard provides a mapping similar to but smaller than the version 3 error codes. Implement a decoder that uses the XNFS error codes, replacing the current decoder. For both mountd protocol versions, map unrecognized errors to -EACCES. Finally we introduce a replacement data structure for mnt_fhstatus at this time, which is used by the new XDR decoders. In addition to documenting that the status value returned by the XDR decoders is always an errno, this new structure will be expanded in subsequent patches. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/mount_clnt.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index 79b5954b8a1b..8429885bc729 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -29,6 +29,8 @@
29 * XDR data type sizes 29 * XDR data type sizes
30 */ 30 */
31#define encode_dirpath_sz (1 + XDR_QUADLEN(MNTPATHLEN)) 31#define encode_dirpath_sz (1 + XDR_QUADLEN(MNTPATHLEN))
32#define MNT_status_sz (1)
33#define MNT_fhs_status_sz (1)
32 34
33/* 35/*
34 * XDR argument and result sizes 36 * XDR argument and result sizes
@@ -61,6 +63,65 @@ enum {
61 63
62static struct rpc_program mnt_program; 64static struct rpc_program mnt_program;
63 65
66/*
67 * Defined by OpenGroup XNFS Version 3W, chapter 8
68 */
69enum mountstat {
70 MNT_OK = 0,
71 MNT_EPERM = 1,
72 MNT_ENOENT = 2,
73 MNT_EACCES = 13,
74 MNT_EINVAL = 22,
75};
76
77static struct {
78 u32 status;
79 int errno;
80} mnt_errtbl[] = {
81 { .status = MNT_OK, .errno = 0, },
82 { .status = MNT_EPERM, .errno = -EPERM, },
83 { .status = MNT_ENOENT, .errno = -ENOENT, },
84 { .status = MNT_EACCES, .errno = -EACCES, },
85 { .status = MNT_EINVAL, .errno = -EINVAL, },
86};
87
88/*
89 * Defined by RFC 1813, section 5.1.5
90 */
91enum mountstat3 {
92 MNT3_OK = 0, /* no error */
93 MNT3ERR_PERM = 1, /* Not owner */
94 MNT3ERR_NOENT = 2, /* No such file or directory */
95 MNT3ERR_IO = 5, /* I/O error */
96 MNT3ERR_ACCES = 13, /* Permission denied */
97 MNT3ERR_NOTDIR = 20, /* Not a directory */
98 MNT3ERR_INVAL = 22, /* Invalid argument */
99 MNT3ERR_NAMETOOLONG = 63, /* Filename too long */
100 MNT3ERR_NOTSUPP = 10004, /* Operation not supported */
101 MNT3ERR_SERVERFAULT = 10006, /* A failure on the server */
102};
103
104static struct {
105 u32 status;
106 int errno;
107} mnt3_errtbl[] = {
108 { .status = MNT3_OK, .errno = 0, },
109 { .status = MNT3ERR_PERM, .errno = -EPERM, },
110 { .status = MNT3ERR_NOENT, .errno = -ENOENT, },
111 { .status = MNT3ERR_IO, .errno = -EIO, },
112 { .status = MNT3ERR_ACCES, .errno = -EACCES, },
113 { .status = MNT3ERR_NOTDIR, .errno = -ENOTDIR, },
114 { .status = MNT3ERR_INVAL, .errno = -EINVAL, },
115 { .status = MNT3ERR_NAMETOOLONG, .errno = -ENAMETOOLONG, },
116 { .status = MNT3ERR_NOTSUPP, .errno = -ENOTSUPP, },
117 { .status = MNT3ERR_SERVERFAULT, .errno = -ESERVERFAULT, },
118};
119
120struct mountres {
121 int errno;
122 struct nfs_fh *fh;
123};
124
64struct mnt_fhstatus { 125struct mnt_fhstatus {
65 u32 status; 126 u32 status;
66 struct nfs_fh *fh; 127 struct nfs_fh *fh;
@@ -179,6 +240,61 @@ static int xdr_decode_fhstatus(struct rpc_rqst *req, __be32 *p,
179 return 0; 240 return 0;
180} 241}
181 242
243/*
244 * RFC 1094: "A non-zero status indicates some sort of error. In this
245 * case, the status is a UNIX error number." This can be problematic
246 * if the server and client use different errno values for the same
247 * error.
248 *
249 * However, the OpenGroup XNFS spec provides a simple mapping that is
250 * independent of local errno values on the server and the client.
251 */
252static int decode_status(struct xdr_stream *xdr, struct mountres *res)
253{
254 unsigned int i;
255 u32 status;
256 __be32 *p;
257
258 p = xdr_inline_decode(xdr, sizeof(status));
259 if (unlikely(p == NULL))
260 return -EIO;
261 status = ntohl(*p);
262
263 for (i = 0; i <= ARRAY_SIZE(mnt_errtbl); i++) {
264 if (mnt_errtbl[i].status == status) {
265 res->errno = mnt_errtbl[i].errno;
266 return 0;
267 }
268 }
269
270 dprintk("NFS: unrecognized MNT status code: %u\n", status);
271 res->errno = -EACCES;
272 return 0;
273}
274
275static int decode_fhs_status(struct xdr_stream *xdr, struct mountres *res)
276{
277 unsigned int i;
278 u32 status;
279 __be32 *p;
280
281 p = xdr_inline_decode(xdr, sizeof(status));
282 if (unlikely(p == NULL))
283 return -EIO;
284 status = ntohl(*p);
285
286 for (i = 0; i <= ARRAY_SIZE(mnt3_errtbl); i++) {
287 if (mnt3_errtbl[i].status == status) {
288 res->errno = mnt3_errtbl[i].errno;
289 return 0;
290 }
291 }
292
293 dprintk("NFS: unrecognized MNT3 status code: %u\n", status);
294 res->errno = -EACCES;
295 return 0;
296}
297
182static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p, 298static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p,
183 struct mnt_fhstatus *res) 299 struct mnt_fhstatus *res)
184{ 300{