nfs3xdr.c 29 KB

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