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