nfs3xdr.c 29 KB

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