nfs3xdr.c 29 KB

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