NFS: Shrink the struct nfs_fattr
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / fs / nfs / nfs3xdr.c
CommitLineData
1da177e4
LT
1/*
2 * linux/fs/nfs/nfs3xdr.c
3 *
4 * XDR functions to encode/decode NFSv3 RPC arguments and results.
5 *
6 * Copyright (C) 1996, 1997 Olaf Kirch
7 */
8
9#include <linux/param.h>
10#include <linux/time.h>
11#include <linux/mm.h>
12#include <linux/slab.h>
13#include <linux/utsname.h>
14#include <linux/errno.h>
15#include <linux/string.h>
16#include <linux/in.h>
17#include <linux/pagemap.h>
18#include <linux/proc_fs.h>
19#include <linux/kdev_t.h>
20#include <linux/sunrpc/clnt.h>
21#include <linux/nfs.h>
22#include <linux/nfs3.h>
23#include <linux/nfs_fs.h>
b7fa0554 24#include <linux/nfsacl.h>
f7b422b1 25#include "internal.h"
1da177e4
LT
26
27#define NFSDBG_FACILITY NFSDBG_XDR
28
29/* Mapping from NFS error code to "errno" error code. */
30#define errno_NFSERR_IO EIO
31
1da177e4
LT
32/*
33 * Declare the space requirements for NFS arguments and replies as
34 * number of 32bit-words
35 */
36#define NFS3_fhandle_sz (1+16)
37#define NFS3_fh_sz (NFS3_fhandle_sz) /* shorthand */
38#define NFS3_sattr_sz (15)
39#define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2))
40#define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2))
41#define NFS3_fattr_sz (21)
42#define NFS3_wcc_attr_sz (6)
43#define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz)
44#define NFS3_post_op_attr_sz (1+NFS3_fattr_sz)
45#define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
46#define NFS3_fsstat_sz
47#define NFS3_fsinfo_sz
48#define NFS3_pathconf_sz
49#define NFS3_entry_sz (NFS3_filename_sz+3)
50
51#define NFS3_sattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
52#define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
4fdc17b2 53#define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz)
1da177e4
LT
54#define NFS3_accessargs_sz (NFS3_fh_sz+1)
55#define NFS3_readlinkargs_sz (NFS3_fh_sz)
56#define NFS3_readargs_sz (NFS3_fh_sz+3)
57#define NFS3_writeargs_sz (NFS3_fh_sz+5)
58#define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
59#define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
94a6d753 60#define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz)
1da177e4
LT
61#define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz)
62#define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz)
63#define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
64#define NFS3_readdirargs_sz (NFS3_fh_sz+2)
65#define NFS3_commitargs_sz (NFS3_fh_sz+3)
66
67#define NFS3_attrstat_sz (1+NFS3_fattr_sz)
68#define NFS3_wccstat_sz (1+NFS3_wcc_data_sz)
4fdc17b2 69#define NFS3_removeres_sz (NFS3_wccstat_sz)
1da177e4
LT
70#define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
71#define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1)
72#define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1)
73#define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3)
74#define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4)
75#define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
76#define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz))
77#define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
78#define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2)
79#define NFS3_fsstatres_sz (1+NFS3_post_op_attr_sz+13)
80#define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12)
81#define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6)
82#define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
83
b7fa0554 84#define ACL3_getaclargs_sz (NFS3_fh_sz+1)
ae46141f
TM
85#define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \
86 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
87#define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \
88 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
b7fa0554
AG
89#define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
90
1da177e4
LT
91/*
92 * Map file type to S_IFMT bits
93 */
94static struct {
95 unsigned int mode;
96 unsigned int nfs2type;
97} nfs_type2fmt[] = {
98 { 0, NFNON },
99 { S_IFREG, NFREG },
100 { S_IFDIR, NFDIR },
101 { S_IFBLK, NFBLK },
102 { S_IFCHR, NFCHR },
103 { S_IFLNK, NFLNK },
104 { S_IFSOCK, NFSOCK },
105 { S_IFIFO, NFFIFO },
106 { 0, NFBAD }
107};
108
109/*
110 * Common NFS XDR functions as inlines
111 */
d61005a6 112static inline __be32 *
4fdc17b2 113xdr_encode_fhandle(__be32 *p, const struct nfs_fh *fh)
1da177e4
LT
114{
115 return xdr_encode_array(p, fh->data, fh->size);
116}
117
d61005a6
AV
118static inline __be32 *
119xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh)
1da177e4
LT
120{
121 if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
122 memcpy(fh->data, p, fh->size);
123 return p + XDR_QUADLEN(fh->size);
124 }
125 return NULL;
126}
127
128/*
129 * Encode/decode time.
130 */
d61005a6
AV
131static inline __be32 *
132xdr_encode_time3(__be32 *p, struct timespec *timep)
1da177e4
LT
133{
134 *p++ = htonl(timep->tv_sec);
135 *p++ = htonl(timep->tv_nsec);
136 return p;
137}
138
d61005a6
AV
139static inline __be32 *
140xdr_decode_time3(__be32 *p, struct timespec *timep)
1da177e4
LT
141{
142 timep->tv_sec = ntohl(*p++);
143 timep->tv_nsec = ntohl(*p++);
144 return p;
145}
146
d61005a6
AV
147static __be32 *
148xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
149{
150 unsigned int type, major, minor;
151 int fmode;
152
153 type = ntohl(*p++);
154 if (type >= NF3BAD)
155 type = NF3BAD;
156 fmode = nfs_type2fmt[type].mode;
157 fattr->type = nfs_type2fmt[type].nfs2type;
158 fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode;
159 fattr->nlink = ntohl(*p++);
160 fattr->uid = ntohl(*p++);
161 fattr->gid = ntohl(*p++);
162 p = xdr_decode_hyper(p, &fattr->size);
163 p = xdr_decode_hyper(p, &fattr->du.nfs3.used);
164
165 /* Turn remote device info into Linux-specific dev_t */
166 major = ntohl(*p++);
167 minor = ntohl(*p++);
168 fattr->rdev = MKDEV(major, minor);
169 if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
170 fattr->rdev = 0;
171
8b4bdcf8
TM
172 p = xdr_decode_hyper(p, &fattr->fsid.major);
173 fattr->fsid.minor = 0;
1da177e4
LT
174 p = xdr_decode_hyper(p, &fattr->fileid);
175 p = xdr_decode_time3(p, &fattr->atime);
176 p = xdr_decode_time3(p, &fattr->mtime);
177 p = xdr_decode_time3(p, &fattr->ctime);
178
179 /* Update the mode bits */
9e6e70f8 180 fattr->valid |= NFS_ATTR_FATTR_V3;
1da177e4
LT
181 return p;
182}
183
d61005a6
AV
184static inline __be32 *
185xdr_encode_sattr(__be32 *p, struct iattr *attr)
1da177e4
LT
186{
187 if (attr->ia_valid & ATTR_MODE) {
188 *p++ = xdr_one;
cf3fff54 189 *p++ = htonl(attr->ia_mode & S_IALLUGO);
1da177e4
LT
190 } else {
191 *p++ = xdr_zero;
192 }
193 if (attr->ia_valid & ATTR_UID) {
194 *p++ = xdr_one;
195 *p++ = htonl(attr->ia_uid);
196 } else {
197 *p++ = xdr_zero;
198 }
199 if (attr->ia_valid & ATTR_GID) {
200 *p++ = xdr_one;
201 *p++ = htonl(attr->ia_gid);
202 } else {
203 *p++ = xdr_zero;
204 }
205 if (attr->ia_valid & ATTR_SIZE) {
206 *p++ = xdr_one;
207 p = xdr_encode_hyper(p, (__u64) attr->ia_size);
208 } else {
209 *p++ = xdr_zero;
210 }
211 if (attr->ia_valid & ATTR_ATIME_SET) {
212 *p++ = xdr_two;
213 p = xdr_encode_time3(p, &attr->ia_atime);
214 } else if (attr->ia_valid & ATTR_ATIME) {
215 *p++ = xdr_one;
216 } else {
217 *p++ = xdr_zero;
218 }
219 if (attr->ia_valid & ATTR_MTIME_SET) {
220 *p++ = xdr_two;
221 p = xdr_encode_time3(p, &attr->ia_mtime);
222 } else if (attr->ia_valid & ATTR_MTIME) {
223 *p++ = xdr_one;
224 } else {
225 *p++ = xdr_zero;
226 }
227 return p;
228}
229
d61005a6
AV
230static inline __be32 *
231xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
232{
233 p = xdr_decode_hyper(p, &fattr->pre_size);
234 p = xdr_decode_time3(p, &fattr->pre_mtime);
235 p = xdr_decode_time3(p, &fattr->pre_ctime);
9e6e70f8
TM
236 fattr->valid |= NFS_ATTR_FATTR_PRESIZE
237 | NFS_ATTR_FATTR_PREMTIME
238 | NFS_ATTR_FATTR_PRECTIME;
1da177e4
LT
239 return p;
240}
241
d61005a6
AV
242static inline __be32 *
243xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
244{
245 if (*p++)
246 p = xdr_decode_fattr(p, fattr);
247 return p;
248}
249
d61005a6
AV
250static inline __be32 *
251xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
252{
253 if (*p++)
254 return xdr_decode_wcc_attr(p, fattr);
255 return p;
256}
257
258
d61005a6
AV
259static inline __be32 *
260xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
261{
262 p = xdr_decode_pre_op_attr(p, fattr);
263 return xdr_decode_post_op_attr(p, fattr);
264}
265
266/*
267 * NFS encode functions
268 */
269
270/*
271 * Encode file handle argument
272 */
273static int
d61005a6 274nfs3_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh)
1da177e4
LT
275{
276 p = xdr_encode_fhandle(p, fh);
277 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
278 return 0;
279}
280
281/*
282 * Encode SETATTR arguments
283 */
284static int
d61005a6 285nfs3_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs3_sattrargs *args)
1da177e4
LT
286{
287 p = xdr_encode_fhandle(p, args->fh);
288 p = xdr_encode_sattr(p, args->sattr);
289 *p++ = htonl(args->guard);
290 if (args->guard)
291 p = xdr_encode_time3(p, &args->guardtime);
292 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
293 return 0;
294}
295
296/*
297 * Encode directory ops argument
298 */
299static int
d61005a6 300nfs3_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs3_diropargs *args)
1da177e4
LT
301{
302 p = xdr_encode_fhandle(p, args->fh);
303 p = xdr_encode_array(p, args->name, args->len);
304 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
305 return 0;
306}
307
4fdc17b2
TM
308/*
309 * Encode REMOVE argument
310 */
311static int
312nfs3_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
313{
314 p = xdr_encode_fhandle(p, args->fh);
315 p = xdr_encode_array(p, args->name.name, args->name.len);
316 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
317 return 0;
318}
319
1da177e4
LT
320/*
321 * Encode access() argument
322 */
323static int
d61005a6 324nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *args)
1da177e4
LT
325{
326 p = xdr_encode_fhandle(p, args->fh);
327 *p++ = htonl(args->access);
328 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
329 return 0;
330}
331
332/*
333 * Arguments to a READ call. Since we read data directly into the page
334 * cache, we also set up the reply iovec here so that iov[1] points
335 * exactly to the page we want to fetch.
336 */
337static int
d61005a6 338nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
1da177e4 339{
1be27f36 340 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
1da177e4
LT
341 unsigned int replen;
342 u32 count = args->count;
343
344 p = xdr_encode_fhandle(p, args->fh);
345 p = xdr_encode_hyper(p, args->offset);
346 *p++ = htonl(count);
347 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
348
349 /* Inline the page array */
350 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2;
351 xdr_inline_pages(&req->rq_rcv_buf, replen,
352 args->pages, args->pgbase, count);
4f22ccc3 353 req->rq_rcv_buf.flags |= XDRBUF_READ;
1da177e4
LT
354 return 0;
355}
356
357/*
358 * Write arguments. Splice the buffer to be written into the iovec.
359 */
360static int
d61005a6 361nfs3_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
1da177e4
LT
362{
363 struct xdr_buf *sndbuf = &req->rq_snd_buf;
364 u32 count = args->count;
365
366 p = xdr_encode_fhandle(p, args->fh);
367 p = xdr_encode_hyper(p, args->offset);
368 *p++ = htonl(count);
369 *p++ = htonl(args->stable);
370 *p++ = htonl(count);
371 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
372
373 /* Copy the page array */
374 xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
4f22ccc3 375 sndbuf->flags |= XDRBUF_WRITE;
1da177e4
LT
376 return 0;
377}
378
379/*
380 * Encode CREATE arguments
381 */
382static int
d61005a6 383nfs3_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs3_createargs *args)
1da177e4
LT
384{
385 p = xdr_encode_fhandle(p, args->fh);
386 p = xdr_encode_array(p, args->name, args->len);
387
388 *p++ = htonl(args->createmode);
389 if (args->createmode == NFS3_CREATE_EXCLUSIVE) {
390 *p++ = args->verifier[0];
391 *p++ = args->verifier[1];
392 } else
393 p = xdr_encode_sattr(p, args->sattr);
394
395 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
396 return 0;
397}
398
399/*
400 * Encode MKDIR arguments
401 */
402static int
d61005a6 403nfs3_xdr_mkdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mkdirargs *args)
1da177e4
LT
404{
405 p = xdr_encode_fhandle(p, args->fh);
406 p = xdr_encode_array(p, args->name, args->len);
407 p = xdr_encode_sattr(p, args->sattr);
408 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
409 return 0;
410}
411
412/*
413 * Encode SYMLINK arguments
414 */
415static int
d61005a6 416nfs3_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_symlinkargs *args)
1da177e4
LT
417{
418 p = xdr_encode_fhandle(p, args->fromfh);
419 p = xdr_encode_array(p, args->fromname, args->fromlen);
420 p = xdr_encode_sattr(p, args->sattr);
94a6d753 421 *p++ = htonl(args->pathlen);
1da177e4 422 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
94a6d753
CL
423
424 /* Copy the page */
425 xdr_encode_pages(&req->rq_snd_buf, args->pages, 0, args->pathlen);
1da177e4
LT
426 return 0;
427}
428
429/*
430 * Encode MKNOD arguments
431 */
432static int
d61005a6 433nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args)
1da177e4
LT
434{
435 p = xdr_encode_fhandle(p, args->fh);
436 p = xdr_encode_array(p, args->name, args->len);
437 *p++ = htonl(args->type);
438 p = xdr_encode_sattr(p, args->sattr);
439 if (args->type == NF3CHR || args->type == NF3BLK) {
440 *p++ = htonl(MAJOR(args->rdev));
441 *p++ = htonl(MINOR(args->rdev));
442 }
443
444 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
445 return 0;
446}
447
448/*
449 * Encode RENAME arguments
450 */
451static int
d61005a6 452nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs3_renameargs *args)
1da177e4
LT
453{
454 p = xdr_encode_fhandle(p, args->fromfh);
455 p = xdr_encode_array(p, args->fromname, args->fromlen);
456 p = xdr_encode_fhandle(p, args->tofh);
457 p = xdr_encode_array(p, args->toname, args->tolen);
458 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
459 return 0;
460}
461
462/*
463 * Encode LINK arguments
464 */
465static int
d61005a6 466nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args)
1da177e4
LT
467{
468 p = xdr_encode_fhandle(p, args->fromfh);
469 p = xdr_encode_fhandle(p, args->tofh);
470 p = xdr_encode_array(p, args->toname, args->tolen);
471 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
472 return 0;
473}
474
475/*
476 * Encode arguments to readdir call
477 */
478static int
d61005a6 479nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args)
1da177e4 480{
1be27f36 481 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
1da177e4
LT
482 unsigned int replen;
483 u32 count = args->count;
484
485 p = xdr_encode_fhandle(p, args->fh);
486 p = xdr_encode_hyper(p, args->cookie);
487 *p++ = args->verf[0];
488 *p++ = args->verf[1];
489 if (args->plus) {
490 /* readdirplus: need dircount + buffer size.
491 * We just make sure we make dircount big enough */
492 *p++ = htonl(count >> 3);
493 }
494 *p++ = htonl(count);
495 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
496
497 /* Inline the page array */
498 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2;
499 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
500 return 0;
501}
502
503/*
504 * Decode the result of a readdir call.
505 * We just check for syntactical correctness.
506 */
507static int
d61005a6 508nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res)
1da177e4
LT
509{
510 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
511 struct kvec *iov = rcvbuf->head;
512 struct page **page;
c957c526
CL
513 size_t hdrlen;
514 u32 len, recvd, pglen;
643f8111 515 int status, nr = 0;
d61005a6 516 __be32 *entry, *end, *kaddr;
1da177e4
LT
517
518 status = ntohl(*p++);
519 /* Decode post_op_attrs */
520 p = xdr_decode_post_op_attr(p, res->dir_attr);
521 if (status)
856dff3d 522 return nfs_stat_to_errno(status);
1da177e4
LT
523 /* Decode verifier cookie */
524 if (res->verf) {
525 res->verf[0] = *p++;
526 res->verf[1] = *p++;
527 } else {
528 p += 2;
529 }
530
531 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
532 if (iov->iov_len < hdrlen) {
fe82a183 533 dprintk("NFS: READDIR reply header overflowed:"
c957c526 534 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1da177e4
LT
535 return -errno_NFSERR_IO;
536 } else if (iov->iov_len != hdrlen) {
537 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
538 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
539 }
540
541 pglen = rcvbuf->page_len;
542 recvd = rcvbuf->len - hdrlen;
543 if (pglen > recvd)
544 pglen = recvd;
545 page = rcvbuf->pages;
d61005a6
AV
546 kaddr = p = kmap_atomic(*page, KM_USER0);
547 end = (__be32 *)((char *)p + pglen);
1da177e4 548 entry = p;
643f8111
JL
549
550 /* Make sure the packet actually has a value_follows and EOF entry */
551 if ((entry + 1) > end)
552 goto short_pkt;
553
554 for (; *p++; nr++) {
1da177e4
LT
555 if (p + 3 > end)
556 goto short_pkt;
557 p += 2; /* inode # */
558 len = ntohl(*p++); /* string length */
559 p += XDR_QUADLEN(len) + 2; /* name + cookie */
560 if (len > NFS3_MAXNAMLEN) {
c957c526 561 dprintk("NFS: giant filename in readdir (len 0x%x)!\n",
1da177e4
LT
562 len);
563 goto err_unmap;
564 }
565
566 if (res->plus) {
567 /* post_op_attr */
568 if (p + 2 > end)
569 goto short_pkt;
570 if (*p++) {
571 p += 21;
572 if (p + 1 > end)
573 goto short_pkt;
574 }
575 /* post_op_fh3 */
576 if (*p++) {
577 if (p + 1 > end)
578 goto short_pkt;
579 len = ntohl(*p++);
580 if (len > NFS3_FHSIZE) {
fe82a183 581 dprintk("NFS: giant filehandle in "
c957c526 582 "readdir (len 0x%x)!\n", len);
1da177e4
LT
583 goto err_unmap;
584 }
585 p += XDR_QUADLEN(len);
586 }
587 }
588
589 if (p + 2 > end)
590 goto short_pkt;
591 entry = p;
592 }
643f8111
JL
593
594 /*
595 * Apparently some server sends responses that are a valid size, but
596 * contain no entries, and have value_follows==0 and EOF==0. For
597 * those, just set the EOF marker.
598 */
599 if (!nr && entry[1] == 0) {
600 dprintk("NFS: readdir reply truncated!\n");
601 entry[1] = 1;
602 }
1da177e4
LT
603 out:
604 kunmap_atomic(kaddr, KM_USER0);
605 return nr;
606 short_pkt:
643f8111
JL
607 /*
608 * When we get a short packet there are 2 possibilities. We can
609 * return an error, or fix up the response to look like a valid
610 * response and return what we have so far. If there are no
611 * entries and the packet was short, then return -EIO. If there
612 * are valid entries in the response, return them and pretend that
613 * the call was successful, but incomplete. The caller can retry the
614 * readdir starting at the last cookie.
615 */
1da177e4 616 entry[0] = entry[1] = 0;
643f8111
JL
617 if (!nr)
618 nr = -errno_NFSERR_IO;
1da177e4
LT
619 goto out;
620err_unmap:
621 nr = -errno_NFSERR_IO;
622 goto out;
623}
624
0dbb4c67
AV
625__be32 *
626nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
1da177e4
LT
627{
628 struct nfs_entry old = *entry;
629
630 if (!*p++) {
631 if (!*p)
632 return ERR_PTR(-EAGAIN);
633 entry->eof = 1;
634 return ERR_PTR(-EBADCOOKIE);
635 }
636
637 p = xdr_decode_hyper(p, &entry->ino);
638 entry->len = ntohl(*p++);
639 entry->name = (const char *) p;
640 p += XDR_QUADLEN(entry->len);
641 entry->prev_cookie = entry->cookie;
642 p = xdr_decode_hyper(p, &entry->cookie);
643
644 if (plus) {
645 entry->fattr->valid = 0;
646 p = xdr_decode_post_op_attr(p, entry->fattr);
647 /* In fact, a post_op_fh3: */
648 if (*p++) {
649 p = xdr_decode_fhandle(p, entry->fh);
650 /* Ugh -- server reply was truncated */
651 if (p == NULL) {
652 dprintk("NFS: FH truncated\n");
653 *entry = old;
654 return ERR_PTR(-EAGAIN);
655 }
656 } else
657 memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
658 }
659
660 entry->eof = !p[0] && p[1];
661 return p;
662}
663
664/*
665 * Encode COMMIT arguments
666 */
667static int
d61005a6 668nfs3_xdr_commitargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
1da177e4
LT
669{
670 p = xdr_encode_fhandle(p, args->fh);
671 p = xdr_encode_hyper(p, args->offset);
672 *p++ = htonl(args->count);
673 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
674 return 0;
675}
676
b7fa0554
AG
677#ifdef CONFIG_NFS_V3_ACL
678/*
679 * Encode GETACL arguments
680 */
681static int
d61005a6 682nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p,
b7fa0554
AG
683 struct nfs3_getaclargs *args)
684{
1be27f36 685 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
b7fa0554
AG
686 unsigned int replen;
687
688 p = xdr_encode_fhandle(p, args->fh);
689 *p++ = htonl(args->mask);
690 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
691
692 if (args->mask & (NFS_ACL | NFS_DFACL)) {
693 /* Inline the page array */
694 replen = (RPC_REPHDRSIZE + auth->au_rslack +
695 ACL3_getaclres_sz) << 2;
696 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0,
697 NFSACL_MAXPAGES << PAGE_SHIFT);
698 }
699 return 0;
700}
701
702/*
703 * Encode SETACL arguments
704 */
705static int
d61005a6 706nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p,
b7fa0554
AG
707 struct nfs3_setaclargs *args)
708{
709 struct xdr_buf *buf = &req->rq_snd_buf;
ae46141f
TM
710 unsigned int base;
711 int err;
b7fa0554
AG
712
713 p = xdr_encode_fhandle(p, NFS_FH(args->inode));
714 *p++ = htonl(args->mask);
ae46141f
TM
715 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
716 base = req->rq_slen;
717
718 if (args->npages != 0)
719 xdr_encode_pages(buf, args->pages, 0, args->len);
720 else
721 req->rq_slen += args->len;
b7fa0554
AG
722
723 err = nfsacl_encode(buf, base, args->inode,
724 (args->mask & NFS_ACL) ?
725 args->acl_access : NULL, 1, 0);
726 if (err > 0)
727 err = nfsacl_encode(buf, base + err, args->inode,
728 (args->mask & NFS_DFACL) ?
729 args->acl_default : NULL, 1,
730 NFS_ACL_DEFAULT);
731 return (err > 0) ? 0 : err;
732}
733#endif /* CONFIG_NFS_V3_ACL */
734
1da177e4
LT
735/*
736 * NFS XDR decode functions
737 */
738
739/*
740 * Decode attrstat reply.
741 */
742static int
d61005a6 743nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
744{
745 int status;
746
747 if ((status = ntohl(*p++)))
856dff3d 748 return nfs_stat_to_errno(status);
1da177e4
LT
749 xdr_decode_fattr(p, fattr);
750 return 0;
751}
752
753/*
754 * Decode status+wcc_data reply
755 * SATTR, REMOVE, RMDIR
756 */
757static int
d61005a6 758nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
759{
760 int status;
761
762 if ((status = ntohl(*p++)))
856dff3d 763 status = nfs_stat_to_errno(status);
1da177e4
LT
764 xdr_decode_wcc_data(p, fattr);
765 return status;
766}
767
4fdc17b2
TM
768static int
769nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res)
770{
771 return nfs3_xdr_wccstat(req, p, &res->dir_attr);
772}
773
1da177e4
LT
774/*
775 * Decode LOOKUP reply
776 */
777static int
d61005a6 778nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
1da177e4
LT
779{
780 int status;
781
782 if ((status = ntohl(*p++))) {
856dff3d 783 status = nfs_stat_to_errno(status);
1da177e4
LT
784 } else {
785 if (!(p = xdr_decode_fhandle(p, res->fh)))
786 return -errno_NFSERR_IO;
787 p = xdr_decode_post_op_attr(p, res->fattr);
788 }
789 xdr_decode_post_op_attr(p, res->dir_attr);
790 return status;
791}
792
793/*
794 * Decode ACCESS reply
795 */
796static int
d61005a6 797nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
1da177e4
LT
798{
799 int status = ntohl(*p++);
800
801 p = xdr_decode_post_op_attr(p, res->fattr);
802 if (status)
856dff3d 803 return nfs_stat_to_errno(status);
1da177e4
LT
804 res->access = ntohl(*p++);
805 return 0;
806}
807
808static int
d61005a6 809nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args)
1da177e4 810{
1be27f36 811 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
1da177e4
LT
812 unsigned int replen;
813
814 p = xdr_encode_fhandle(p, args->fh);
815 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
816
817 /* Inline the page array */
818 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
819 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
820 return 0;
821}
822
823/*
824 * Decode READLINK reply
825 */
826static int
d61005a6 827nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
828{
829 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
830 struct kvec *iov = rcvbuf->head;
c957c526
CL
831 size_t hdrlen;
832 u32 len, recvd;
1da177e4
LT
833 char *kaddr;
834 int status;
835
836 status = ntohl(*p++);
837 p = xdr_decode_post_op_attr(p, fattr);
838
839 if (status != 0)
856dff3d 840 return nfs_stat_to_errno(status);
1da177e4
LT
841
842 /* Convert length of symlink */
843 len = ntohl(*p++);
c957c526 844 if (len >= rcvbuf->page_len) {
fe82a183 845 dprintk("nfs: server returned giant symlink!\n");
1da177e4
LT
846 return -ENAMETOOLONG;
847 }
848
849 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
850 if (iov->iov_len < hdrlen) {
fe82a183 851 dprintk("NFS: READLINK reply header overflowed:"
c957c526 852 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1da177e4
LT
853 return -errno_NFSERR_IO;
854 } else if (iov->iov_len != hdrlen) {
fe82a183
CL
855 dprintk("NFS: READLINK header is short. "
856 "iovec will be shifted.\n");
1da177e4
LT
857 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
858 }
859 recvd = req->rq_rcv_buf.len - hdrlen;
860 if (recvd < len) {
fe82a183 861 dprintk("NFS: server cheating in readlink reply: "
1da177e4
LT
862 "count %u > recvd %u\n", len, recvd);
863 return -EIO;
864 }
865
866 /* NULL terminate the string we got */
867 kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
868 kaddr[len+rcvbuf->page_base] = '\0';
869 kunmap_atomic(kaddr, KM_USER0);
870 return 0;
871}
872
873/*
874 * Decode READ reply
875 */
876static int
d61005a6 877nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
1da177e4
LT
878{
879 struct kvec *iov = req->rq_rcv_buf.head;
c957c526
CL
880 size_t hdrlen;
881 u32 count, ocount, recvd;
882 int status;
1da177e4
LT
883
884 status = ntohl(*p++);
885 p = xdr_decode_post_op_attr(p, res->fattr);
886
887 if (status != 0)
856dff3d 888 return nfs_stat_to_errno(status);
1da177e4 889
c957c526 890 /* Decode reply count and EOF flag. NFSv3 is somewhat redundant
1da177e4
LT
891 * in that it puts the count both in the res struct and in the
892 * opaque data count. */
893 count = ntohl(*p++);
894 res->eof = ntohl(*p++);
895 ocount = ntohl(*p++);
896
897 if (ocount != count) {
fe82a183 898 dprintk("NFS: READ count doesn't match RPC opaque count.\n");
1da177e4
LT
899 return -errno_NFSERR_IO;
900 }
901
902 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
903 if (iov->iov_len < hdrlen) {
fe82a183 904 dprintk("NFS: READ reply header overflowed:"
c957c526 905 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1da177e4
LT
906 return -errno_NFSERR_IO;
907 } else if (iov->iov_len != hdrlen) {
908 dprintk("NFS: READ header is short. iovec will be shifted.\n");
909 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
910 }
911
912 recvd = req->rq_rcv_buf.len - hdrlen;
913 if (count > recvd) {
fe82a183 914 dprintk("NFS: server cheating in read reply: "
c957c526 915 "count %u > recvd %u\n", count, recvd);
1da177e4
LT
916 count = recvd;
917 res->eof = 0;
918 }
919
920 if (count < res->count)
921 res->count = count;
922
923 return count;
924}
925
926/*
927 * Decode WRITE response
928 */
929static int
d61005a6 930nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1da177e4
LT
931{
932 int status;
933
934 status = ntohl(*p++);
935 p = xdr_decode_wcc_data(p, res->fattr);
936
937 if (status != 0)
856dff3d 938 return nfs_stat_to_errno(status);
1da177e4
LT
939
940 res->count = ntohl(*p++);
941 res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
942 res->verf->verifier[0] = *p++;
943 res->verf->verifier[1] = *p++;
944
945 return res->count;
946}
947
948/*
949 * Decode a CREATE response
950 */
951static int
d61005a6 952nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
1da177e4
LT
953{
954 int status;
955
956 status = ntohl(*p++);
957 if (status == 0) {
958 if (*p++) {
959 if (!(p = xdr_decode_fhandle(p, res->fh)))
960 return -errno_NFSERR_IO;
961 p = xdr_decode_post_op_attr(p, res->fattr);
962 } else {
963 memset(res->fh, 0, sizeof(*res->fh));
964 /* Do decode post_op_attr but set it to NULL */
965 p = xdr_decode_post_op_attr(p, res->fattr);
966 res->fattr->valid = 0;
967 }
968 } else {
856dff3d 969 status = nfs_stat_to_errno(status);
1da177e4
LT
970 }
971 p = xdr_decode_wcc_data(p, res->dir_attr);
972 return status;
973}
974
975/*
976 * Decode RENAME reply
977 */
978static int
d61005a6 979nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res)
1da177e4
LT
980{
981 int status;
982
983 if ((status = ntohl(*p++)) != 0)
856dff3d 984 status = nfs_stat_to_errno(status);
1da177e4
LT
985 p = xdr_decode_wcc_data(p, res->fromattr);
986 p = xdr_decode_wcc_data(p, res->toattr);
987 return status;
988}
989
990/*
991 * Decode LINK reply
992 */
993static int
d61005a6 994nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
1da177e4
LT
995{
996 int status;
997
998 if ((status = ntohl(*p++)) != 0)
856dff3d 999 status = nfs_stat_to_errno(status);
1da177e4
LT
1000 p = xdr_decode_post_op_attr(p, res->fattr);
1001 p = xdr_decode_wcc_data(p, res->dir_attr);
1002 return status;
1003}
1004
1005/*
1006 * Decode FSSTAT reply
1007 */
1008static int
d61005a6 1009nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
1da177e4
LT
1010{
1011 int status;
1012
1013 status = ntohl(*p++);
1014
1015 p = xdr_decode_post_op_attr(p, res->fattr);
1016 if (status != 0)
856dff3d 1017 return nfs_stat_to_errno(status);
1da177e4
LT
1018
1019 p = xdr_decode_hyper(p, &res->tbytes);
1020 p = xdr_decode_hyper(p, &res->fbytes);
1021 p = xdr_decode_hyper(p, &res->abytes);
1022 p = xdr_decode_hyper(p, &res->tfiles);
1023 p = xdr_decode_hyper(p, &res->ffiles);
1024 p = xdr_decode_hyper(p, &res->afiles);
1025
1026 /* ignore invarsec */
1027 return 0;
1028}
1029
1030/*
1031 * Decode FSINFO reply
1032 */
1033static int
d61005a6 1034nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
1da177e4
LT
1035{
1036 int status;
1037
1038 status = ntohl(*p++);
1039
1040 p = xdr_decode_post_op_attr(p, res->fattr);
1041 if (status != 0)
856dff3d 1042 return nfs_stat_to_errno(status);
1da177e4
LT
1043
1044 res->rtmax = ntohl(*p++);
1045 res->rtpref = ntohl(*p++);
1046 res->rtmult = ntohl(*p++);
1047 res->wtmax = ntohl(*p++);
1048 res->wtpref = ntohl(*p++);
1049 res->wtmult = ntohl(*p++);
1050 res->dtpref = ntohl(*p++);
1051 p = xdr_decode_hyper(p, &res->maxfilesize);
1052
1053 /* ignore time_delta and properties */
1054 res->lease_time = 0;
1055 return 0;
1056}
1057
1058/*
1059 * Decode PATHCONF reply
1060 */
1061static int
d61005a6 1062nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
1da177e4
LT
1063{
1064 int status;
1065
1066 status = ntohl(*p++);
1067
1068 p = xdr_decode_post_op_attr(p, res->fattr);
1069 if (status != 0)
856dff3d 1070 return nfs_stat_to_errno(status);
1da177e4
LT
1071 res->max_link = ntohl(*p++);
1072 res->max_namelen = ntohl(*p++);
1073
1074 /* ignore remaining fields */
1075 return 0;
1076}
1077
1078/*
1079 * Decode COMMIT reply
1080 */
1081static int
d61005a6 1082nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1da177e4
LT
1083{
1084 int status;
1085
1086 status = ntohl(*p++);
1087 p = xdr_decode_wcc_data(p, res->fattr);
1088 if (status != 0)
856dff3d 1089 return nfs_stat_to_errno(status);
1da177e4
LT
1090
1091 res->verf->verifier[0] = *p++;
1092 res->verf->verifier[1] = *p++;
1093 return 0;
1094}
1095
b7fa0554
AG
1096#ifdef CONFIG_NFS_V3_ACL
1097/*
1098 * Decode GETACL reply
1099 */
1100static int
d61005a6 1101nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
b7fa0554
AG
1102 struct nfs3_getaclres *res)
1103{
1104 struct xdr_buf *buf = &req->rq_rcv_buf;
1105 int status = ntohl(*p++);
1106 struct posix_acl **acl;
1107 unsigned int *aclcnt;
1108 int err, base;
1109
1110 if (status != 0)
856dff3d 1111 return nfs_stat_to_errno(status);
b7fa0554
AG
1112 p = xdr_decode_post_op_attr(p, res->fattr);
1113 res->mask = ntohl(*p++);
1114 if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
1115 return -EINVAL;
1116 base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
1117
1118 acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
1119 aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
1120 err = nfsacl_decode(buf, base, aclcnt, acl);
1121
1122 acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
1123 aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
1124 if (err > 0)
1125 err = nfsacl_decode(buf, base + err, aclcnt, acl);
1126 return (err > 0) ? 0 : err;
1127}
1128
1129/*
1130 * Decode setacl reply.
1131 */
1132static int
d61005a6 1133nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
b7fa0554
AG
1134{
1135 int status = ntohl(*p++);
1136
1137 if (status)
856dff3d 1138 return nfs_stat_to_errno(status);
b7fa0554
AG
1139 xdr_decode_post_op_attr(p, fattr);
1140 return 0;
1141}
1142#endif /* CONFIG_NFS_V3_ACL */
1143
1da177e4
LT
1144#define PROC(proc, argtype, restype, timer) \
1145[NFS3PROC_##proc] = { \
1146 .p_proc = NFS3PROC_##proc, \
1147 .p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \
1148 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \
2bea90d4
CL
1149 .p_arglen = NFS3_##argtype##_sz, \
1150 .p_replen = NFS3_##restype##_sz, \
cc0175c1
CL
1151 .p_timer = timer, \
1152 .p_statidx = NFS3PROC_##proc, \
1153 .p_name = #proc, \
1da177e4
LT
1154 }
1155
1156struct rpc_procinfo nfs3_procedures[] = {
1157 PROC(GETATTR, fhandle, attrstat, 1),
1158 PROC(SETATTR, sattrargs, wccstat, 0),
1159 PROC(LOOKUP, diropargs, lookupres, 2),
1160 PROC(ACCESS, accessargs, accessres, 1),
1161 PROC(READLINK, readlinkargs, readlinkres, 3),
1162 PROC(READ, readargs, readres, 3),
1163 PROC(WRITE, writeargs, writeres, 4),
1164 PROC(CREATE, createargs, createres, 0),
1165 PROC(MKDIR, mkdirargs, createres, 0),
1166 PROC(SYMLINK, symlinkargs, createres, 0),
1167 PROC(MKNOD, mknodargs, createres, 0),
4fdc17b2 1168 PROC(REMOVE, removeargs, removeres, 0),
1da177e4
LT
1169 PROC(RMDIR, diropargs, wccstat, 0),
1170 PROC(RENAME, renameargs, renameres, 0),
1171 PROC(LINK, linkargs, linkres, 0),
1172 PROC(READDIR, readdirargs, readdirres, 3),
1173 PROC(READDIRPLUS, readdirargs, readdirres, 3),
1174 PROC(FSSTAT, fhandle, fsstatres, 0),
1175 PROC(FSINFO, fhandle, fsinfores, 0),
1176 PROC(PATHCONF, fhandle, pathconfres, 0),
1177 PROC(COMMIT, commitargs, commitres, 5),
1178};
1179
1180struct rpc_version nfs_version3 = {
1181 .number = 3,
e8c96f8c 1182 .nrprocs = ARRAY_SIZE(nfs3_procedures),
1da177e4
LT
1183 .procs = nfs3_procedures
1184};
1185
b7fa0554
AG
1186#ifdef CONFIG_NFS_V3_ACL
1187static struct rpc_procinfo nfs3_acl_procedures[] = {
1188 [ACLPROC3_GETACL] = {
1189 .p_proc = ACLPROC3_GETACL,
1190 .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,
1191 .p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
2bea90d4
CL
1192 .p_arglen = ACL3_getaclargs_sz,
1193 .p_replen = ACL3_getaclres_sz,
b7fa0554 1194 .p_timer = 1,
cc0175c1 1195 .p_name = "GETACL",
b7fa0554
AG
1196 },
1197 [ACLPROC3_SETACL] = {
1198 .p_proc = ACLPROC3_SETACL,
1199 .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
1200 .p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
2bea90d4
CL
1201 .p_arglen = ACL3_setaclargs_sz,
1202 .p_replen = ACL3_setaclres_sz,
b7fa0554 1203 .p_timer = 0,
cc0175c1 1204 .p_name = "SETACL",
b7fa0554
AG
1205 },
1206};
1207
1208struct rpc_version nfsacl_version3 = {
1209 .number = 3,
1210 .nrprocs = sizeof(nfs3_acl_procedures)/
1211 sizeof(nfs3_acl_procedures[0]),
1212 .procs = nfs3_acl_procedures,
1213};
1214#endif /* CONFIG_NFS_V3_ACL */