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