nfs3xdr.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170
  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. #define NFSDBG_FACILITY NFSDBG_XDR
  25. /* Mapping from NFS error code to "errno" error code. */
  26. #define errno_NFSERR_IO EIO
  27. extern int nfs_stat_to_errno(int);
  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+NFS3_path_sz+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 u32 *
  100. xdr_encode_fhandle(u32 *p, struct nfs_fh *fh)
  101. {
  102. return xdr_encode_array(p, fh->data, fh->size);
  103. }
  104. static inline u32 *
  105. xdr_decode_fhandle(u32 *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 u32 *
  117. xdr_encode_time3(u32 *p, struct timespec *timep)
  118. {
  119. *p++ = htonl(timep->tv_sec);
  120. *p++ = htonl(timep->tv_nsec);
  121. return p;
  122. }
  123. static inline u32 *
  124. xdr_decode_time3(u32 *p, struct timespec *timep)
  125. {
  126. timep->tv_sec = ntohl(*p++);
  127. timep->tv_nsec = ntohl(*p++);
  128. return p;
  129. }
  130. static u32 *
  131. xdr_decode_fattr(u32 *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_u.nfs3);
  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 | NFS_ATTR_FATTR_V3);
  159. fattr->timestamp = jiffies;
  160. return p;
  161. }
  162. static inline u32 *
  163. xdr_encode_sattr(u32 *p, struct iattr *attr)
  164. {
  165. if (attr->ia_valid & ATTR_MODE) {
  166. *p++ = xdr_one;
  167. *p++ = htonl(attr->ia_mode);
  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 u32 *
  208. xdr_decode_wcc_attr(u32 *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 u32 *
  217. xdr_decode_post_op_attr(u32 *p, struct nfs_fattr *fattr)
  218. {
  219. if (*p++)
  220. p = xdr_decode_fattr(p, fattr);
  221. return p;
  222. }
  223. static inline u32 *
  224. xdr_decode_pre_op_attr(u32 *p, struct nfs_fattr *fattr)
  225. {
  226. if (*p++)
  227. return xdr_decode_wcc_attr(p, fattr);
  228. return p;
  229. }
  230. static inline u32 *
  231. xdr_decode_wcc_data(u32 *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, u32 *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, u32 *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, u32 *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, u32 *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, u32 *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, u32 *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, u32 *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, u32 *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, u32 *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 = xdr_encode_array(p, args->topath, args->tolen);
  363. req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
  364. return 0;
  365. }
  366. /*
  367. * Encode MKNOD arguments
  368. */
  369. static int
  370. nfs3_xdr_mknodargs(struct rpc_rqst *req, u32 *p, struct nfs3_mknodargs *args)
  371. {
  372. p = xdr_encode_fhandle(p, args->fh);
  373. p = xdr_encode_array(p, args->name, args->len);
  374. *p++ = htonl(args->type);
  375. p = xdr_encode_sattr(p, args->sattr);
  376. if (args->type == NF3CHR || args->type == NF3BLK) {
  377. *p++ = htonl(MAJOR(args->rdev));
  378. *p++ = htonl(MINOR(args->rdev));
  379. }
  380. req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
  381. return 0;
  382. }
  383. /*
  384. * Encode RENAME arguments
  385. */
  386. static int
  387. nfs3_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs3_renameargs *args)
  388. {
  389. p = xdr_encode_fhandle(p, args->fromfh);
  390. p = xdr_encode_array(p, args->fromname, args->fromlen);
  391. p = xdr_encode_fhandle(p, args->tofh);
  392. p = xdr_encode_array(p, args->toname, args->tolen);
  393. req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
  394. return 0;
  395. }
  396. /*
  397. * Encode LINK arguments
  398. */
  399. static int
  400. nfs3_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs3_linkargs *args)
  401. {
  402. p = xdr_encode_fhandle(p, args->fromfh);
  403. p = xdr_encode_fhandle(p, args->tofh);
  404. p = xdr_encode_array(p, args->toname, args->tolen);
  405. req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
  406. return 0;
  407. }
  408. /*
  409. * Encode arguments to readdir call
  410. */
  411. static int
  412. nfs3_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_readdirargs *args)
  413. {
  414. struct rpc_auth *auth = req->rq_task->tk_auth;
  415. unsigned int replen;
  416. u32 count = args->count;
  417. p = xdr_encode_fhandle(p, args->fh);
  418. p = xdr_encode_hyper(p, args->cookie);
  419. *p++ = args->verf[0];
  420. *p++ = args->verf[1];
  421. if (args->plus) {
  422. /* readdirplus: need dircount + buffer size.
  423. * We just make sure we make dircount big enough */
  424. *p++ = htonl(count >> 3);
  425. }
  426. *p++ = htonl(count);
  427. req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
  428. /* Inline the page array */
  429. replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2;
  430. xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
  431. return 0;
  432. }
  433. /*
  434. * Decode the result of a readdir call.
  435. * We just check for syntactical correctness.
  436. */
  437. static int
  438. nfs3_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs3_readdirres *res)
  439. {
  440. struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
  441. struct kvec *iov = rcvbuf->head;
  442. struct page **page;
  443. int hdrlen, recvd;
  444. int status, nr;
  445. unsigned int len, pglen;
  446. u32 *entry, *end, *kaddr;
  447. status = ntohl(*p++);
  448. /* Decode post_op_attrs */
  449. p = xdr_decode_post_op_attr(p, res->dir_attr);
  450. if (status)
  451. return -nfs_stat_to_errno(status);
  452. /* Decode verifier cookie */
  453. if (res->verf) {
  454. res->verf[0] = *p++;
  455. res->verf[1] = *p++;
  456. } else {
  457. p += 2;
  458. }
  459. hdrlen = (u8 *) p - (u8 *) iov->iov_base;
  460. if (iov->iov_len < hdrlen) {
  461. printk(KERN_WARNING "NFS: READDIR reply header overflowed:"
  462. "length %d > %Zu\n", hdrlen, iov->iov_len);
  463. return -errno_NFSERR_IO;
  464. } else if (iov->iov_len != hdrlen) {
  465. dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
  466. xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
  467. }
  468. pglen = rcvbuf->page_len;
  469. recvd = rcvbuf->len - hdrlen;
  470. if (pglen > recvd)
  471. pglen = recvd;
  472. page = rcvbuf->pages;
  473. kaddr = p = (u32 *)kmap_atomic(*page, KM_USER0);
  474. end = (u32 *)((char *)p + pglen);
  475. entry = p;
  476. for (nr = 0; *p++; nr++) {
  477. if (p + 3 > end)
  478. goto short_pkt;
  479. p += 2; /* inode # */
  480. len = ntohl(*p++); /* string length */
  481. p += XDR_QUADLEN(len) + 2; /* name + cookie */
  482. if (len > NFS3_MAXNAMLEN) {
  483. printk(KERN_WARNING "NFS: giant filename in readdir (len %x)!\n",
  484. len);
  485. goto err_unmap;
  486. }
  487. if (res->plus) {
  488. /* post_op_attr */
  489. if (p + 2 > end)
  490. goto short_pkt;
  491. if (*p++) {
  492. p += 21;
  493. if (p + 1 > end)
  494. goto short_pkt;
  495. }
  496. /* post_op_fh3 */
  497. if (*p++) {
  498. if (p + 1 > end)
  499. goto short_pkt;
  500. len = ntohl(*p++);
  501. if (len > NFS3_FHSIZE) {
  502. printk(KERN_WARNING "NFS: giant filehandle in "
  503. "readdir (len %x)!\n", len);
  504. goto err_unmap;
  505. }
  506. p += XDR_QUADLEN(len);
  507. }
  508. }
  509. if (p + 2 > end)
  510. goto short_pkt;
  511. entry = p;
  512. }
  513. if (!nr && (entry[0] != 0 || entry[1] == 0))
  514. goto short_pkt;
  515. out:
  516. kunmap_atomic(kaddr, KM_USER0);
  517. return nr;
  518. short_pkt:
  519. entry[0] = entry[1] = 0;
  520. /* truncate listing ? */
  521. if (!nr) {
  522. printk(KERN_NOTICE "NFS: readdir reply truncated!\n");
  523. entry[1] = 1;
  524. }
  525. goto out;
  526. err_unmap:
  527. nr = -errno_NFSERR_IO;
  528. goto out;
  529. }
  530. u32 *
  531. nfs3_decode_dirent(u32 *p, struct nfs_entry *entry, int plus)
  532. {
  533. struct nfs_entry old = *entry;
  534. if (!*p++) {
  535. if (!*p)
  536. return ERR_PTR(-EAGAIN);
  537. entry->eof = 1;
  538. return ERR_PTR(-EBADCOOKIE);
  539. }
  540. p = xdr_decode_hyper(p, &entry->ino);
  541. entry->len = ntohl(*p++);
  542. entry->name = (const char *) p;
  543. p += XDR_QUADLEN(entry->len);
  544. entry->prev_cookie = entry->cookie;
  545. p = xdr_decode_hyper(p, &entry->cookie);
  546. if (plus) {
  547. entry->fattr->valid = 0;
  548. p = xdr_decode_post_op_attr(p, entry->fattr);
  549. /* In fact, a post_op_fh3: */
  550. if (*p++) {
  551. p = xdr_decode_fhandle(p, entry->fh);
  552. /* Ugh -- server reply was truncated */
  553. if (p == NULL) {
  554. dprintk("NFS: FH truncated\n");
  555. *entry = old;
  556. return ERR_PTR(-EAGAIN);
  557. }
  558. } else
  559. memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
  560. }
  561. entry->eof = !p[0] && p[1];
  562. return p;
  563. }
  564. /*
  565. * Encode COMMIT arguments
  566. */
  567. static int
  568. nfs3_xdr_commitargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
  569. {
  570. p = xdr_encode_fhandle(p, args->fh);
  571. p = xdr_encode_hyper(p, args->offset);
  572. *p++ = htonl(args->count);
  573. req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
  574. return 0;
  575. }
  576. #ifdef CONFIG_NFS_V3_ACL
  577. /*
  578. * Encode GETACL arguments
  579. */
  580. static int
  581. nfs3_xdr_getaclargs(struct rpc_rqst *req, u32 *p,
  582. struct nfs3_getaclargs *args)
  583. {
  584. struct rpc_auth *auth = req->rq_task->tk_auth;
  585. unsigned int replen;
  586. p = xdr_encode_fhandle(p, args->fh);
  587. *p++ = htonl(args->mask);
  588. req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
  589. if (args->mask & (NFS_ACL | NFS_DFACL)) {
  590. /* Inline the page array */
  591. replen = (RPC_REPHDRSIZE + auth->au_rslack +
  592. ACL3_getaclres_sz) << 2;
  593. xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0,
  594. NFSACL_MAXPAGES << PAGE_SHIFT);
  595. }
  596. return 0;
  597. }
  598. /*
  599. * Encode SETACL arguments
  600. */
  601. static int
  602. nfs3_xdr_setaclargs(struct rpc_rqst *req, u32 *p,
  603. struct nfs3_setaclargs *args)
  604. {
  605. struct xdr_buf *buf = &req->rq_snd_buf;
  606. unsigned int base, len_in_head, len = nfsacl_size(
  607. (args->mask & NFS_ACL) ? args->acl_access : NULL,
  608. (args->mask & NFS_DFACL) ? args->acl_default : NULL);
  609. int count, err;
  610. p = xdr_encode_fhandle(p, NFS_FH(args->inode));
  611. *p++ = htonl(args->mask);
  612. base = (char *)p - (char *)buf->head->iov_base;
  613. /* put as much of the acls into head as possible. */
  614. len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);
  615. len -= len_in_head;
  616. req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2));
  617. for (count = 0; (count << PAGE_SHIFT) < len; count++) {
  618. args->pages[count] = alloc_page(GFP_KERNEL);
  619. if (!args->pages[count]) {
  620. while (count)
  621. __free_page(args->pages[--count]);
  622. return -ENOMEM;
  623. }
  624. }
  625. xdr_encode_pages(buf, args->pages, 0, len);
  626. err = nfsacl_encode(buf, base, args->inode,
  627. (args->mask & NFS_ACL) ?
  628. args->acl_access : NULL, 1, 0);
  629. if (err > 0)
  630. err = nfsacl_encode(buf, base + err, args->inode,
  631. (args->mask & NFS_DFACL) ?
  632. args->acl_default : NULL, 1,
  633. NFS_ACL_DEFAULT);
  634. return (err > 0) ? 0 : err;
  635. }
  636. #endif /* CONFIG_NFS_V3_ACL */
  637. /*
  638. * NFS XDR decode functions
  639. */
  640. /*
  641. * Decode attrstat reply.
  642. */
  643. static int
  644. nfs3_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
  645. {
  646. int status;
  647. if ((status = ntohl(*p++)))
  648. return -nfs_stat_to_errno(status);
  649. xdr_decode_fattr(p, fattr);
  650. return 0;
  651. }
  652. /*
  653. * Decode status+wcc_data reply
  654. * SATTR, REMOVE, RMDIR
  655. */
  656. static int
  657. nfs3_xdr_wccstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
  658. {
  659. int status;
  660. if ((status = ntohl(*p++)))
  661. status = -nfs_stat_to_errno(status);
  662. xdr_decode_wcc_data(p, fattr);
  663. return status;
  664. }
  665. /*
  666. * Decode LOOKUP reply
  667. */
  668. static int
  669. nfs3_xdr_lookupres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
  670. {
  671. int status;
  672. if ((status = ntohl(*p++))) {
  673. status = -nfs_stat_to_errno(status);
  674. } else {
  675. if (!(p = xdr_decode_fhandle(p, res->fh)))
  676. return -errno_NFSERR_IO;
  677. p = xdr_decode_post_op_attr(p, res->fattr);
  678. }
  679. xdr_decode_post_op_attr(p, res->dir_attr);
  680. return status;
  681. }
  682. /*
  683. * Decode ACCESS reply
  684. */
  685. static int
  686. nfs3_xdr_accessres(struct rpc_rqst *req, u32 *p, struct nfs3_accessres *res)
  687. {
  688. int status = ntohl(*p++);
  689. p = xdr_decode_post_op_attr(p, res->fattr);
  690. if (status)
  691. return -nfs_stat_to_errno(status);
  692. res->access = ntohl(*p++);
  693. return 0;
  694. }
  695. static int
  696. nfs3_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkargs *args)
  697. {
  698. struct rpc_auth *auth = req->rq_task->tk_auth;
  699. unsigned int replen;
  700. p = xdr_encode_fhandle(p, args->fh);
  701. req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
  702. /* Inline the page array */
  703. replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
  704. xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
  705. return 0;
  706. }
  707. /*
  708. * Decode READLINK reply
  709. */
  710. static int
  711. nfs3_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
  712. {
  713. struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
  714. struct kvec *iov = rcvbuf->head;
  715. int hdrlen, len, recvd;
  716. char *kaddr;
  717. int status;
  718. status = ntohl(*p++);
  719. p = xdr_decode_post_op_attr(p, fattr);
  720. if (status != 0)
  721. return -nfs_stat_to_errno(status);
  722. /* Convert length of symlink */
  723. len = ntohl(*p++);
  724. if (len >= rcvbuf->page_len || len <= 0) {
  725. dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
  726. return -ENAMETOOLONG;
  727. }
  728. hdrlen = (u8 *) p - (u8 *) iov->iov_base;
  729. if (iov->iov_len < hdrlen) {
  730. printk(KERN_WARNING "NFS: READLINK reply header overflowed:"
  731. "length %d > %Zu\n", hdrlen, iov->iov_len);
  732. return -errno_NFSERR_IO;
  733. } else if (iov->iov_len != hdrlen) {
  734. dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
  735. xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
  736. }
  737. recvd = req->rq_rcv_buf.len - hdrlen;
  738. if (recvd < len) {
  739. printk(KERN_WARNING "NFS: server cheating in readlink reply: "
  740. "count %u > recvd %u\n", len, recvd);
  741. return -EIO;
  742. }
  743. /* NULL terminate the string we got */
  744. kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
  745. kaddr[len+rcvbuf->page_base] = '\0';
  746. kunmap_atomic(kaddr, KM_USER0);
  747. return 0;
  748. }
  749. /*
  750. * Decode READ reply
  751. */
  752. static int
  753. nfs3_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res)
  754. {
  755. struct kvec *iov = req->rq_rcv_buf.head;
  756. int status, count, ocount, recvd, hdrlen;
  757. status = ntohl(*p++);
  758. p = xdr_decode_post_op_attr(p, res->fattr);
  759. if (status != 0)
  760. return -nfs_stat_to_errno(status);
  761. /* Decode reply could and EOF flag. NFSv3 is somewhat redundant
  762. * in that it puts the count both in the res struct and in the
  763. * opaque data count. */
  764. count = ntohl(*p++);
  765. res->eof = ntohl(*p++);
  766. ocount = ntohl(*p++);
  767. if (ocount != count) {
  768. printk(KERN_WARNING "NFS: READ count doesn't match RPC opaque count.\n");
  769. return -errno_NFSERR_IO;
  770. }
  771. hdrlen = (u8 *) p - (u8 *) iov->iov_base;
  772. if (iov->iov_len < hdrlen) {
  773. printk(KERN_WARNING "NFS: READ reply header overflowed:"
  774. "length %d > %Zu\n", hdrlen, iov->iov_len);
  775. return -errno_NFSERR_IO;
  776. } else if (iov->iov_len != hdrlen) {
  777. dprintk("NFS: READ header is short. iovec will be shifted.\n");
  778. xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
  779. }
  780. recvd = req->rq_rcv_buf.len - hdrlen;
  781. if (count > recvd) {
  782. printk(KERN_WARNING "NFS: server cheating in read reply: "
  783. "count %d > recvd %d\n", count, recvd);
  784. count = recvd;
  785. res->eof = 0;
  786. }
  787. if (count < res->count)
  788. res->count = count;
  789. return count;
  790. }
  791. /*
  792. * Decode WRITE response
  793. */
  794. static int
  795. nfs3_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
  796. {
  797. int status;
  798. status = ntohl(*p++);
  799. p = xdr_decode_wcc_data(p, res->fattr);
  800. if (status != 0)
  801. return -nfs_stat_to_errno(status);
  802. res->count = ntohl(*p++);
  803. res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
  804. res->verf->verifier[0] = *p++;
  805. res->verf->verifier[1] = *p++;
  806. return res->count;
  807. }
  808. /*
  809. * Decode a CREATE response
  810. */
  811. static int
  812. nfs3_xdr_createres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
  813. {
  814. int status;
  815. status = ntohl(*p++);
  816. if (status == 0) {
  817. if (*p++) {
  818. if (!(p = xdr_decode_fhandle(p, res->fh)))
  819. return -errno_NFSERR_IO;
  820. p = xdr_decode_post_op_attr(p, res->fattr);
  821. } else {
  822. memset(res->fh, 0, sizeof(*res->fh));
  823. /* Do decode post_op_attr but set it to NULL */
  824. p = xdr_decode_post_op_attr(p, res->fattr);
  825. res->fattr->valid = 0;
  826. }
  827. } else {
  828. status = -nfs_stat_to_errno(status);
  829. }
  830. p = xdr_decode_wcc_data(p, res->dir_attr);
  831. return status;
  832. }
  833. /*
  834. * Decode RENAME reply
  835. */
  836. static int
  837. nfs3_xdr_renameres(struct rpc_rqst *req, u32 *p, struct nfs3_renameres *res)
  838. {
  839. int status;
  840. if ((status = ntohl(*p++)) != 0)
  841. status = -nfs_stat_to_errno(status);
  842. p = xdr_decode_wcc_data(p, res->fromattr);
  843. p = xdr_decode_wcc_data(p, res->toattr);
  844. return status;
  845. }
  846. /*
  847. * Decode LINK reply
  848. */
  849. static int
  850. nfs3_xdr_linkres(struct rpc_rqst *req, u32 *p, struct nfs3_linkres *res)
  851. {
  852. int status;
  853. if ((status = ntohl(*p++)) != 0)
  854. status = -nfs_stat_to_errno(status);
  855. p = xdr_decode_post_op_attr(p, res->fattr);
  856. p = xdr_decode_wcc_data(p, res->dir_attr);
  857. return status;
  858. }
  859. /*
  860. * Decode FSSTAT reply
  861. */
  862. static int
  863. nfs3_xdr_fsstatres(struct rpc_rqst *req, u32 *p, struct nfs_fsstat *res)
  864. {
  865. int status;
  866. status = ntohl(*p++);
  867. p = xdr_decode_post_op_attr(p, res->fattr);
  868. if (status != 0)
  869. return -nfs_stat_to_errno(status);
  870. p = xdr_decode_hyper(p, &res->tbytes);
  871. p = xdr_decode_hyper(p, &res->fbytes);
  872. p = xdr_decode_hyper(p, &res->abytes);
  873. p = xdr_decode_hyper(p, &res->tfiles);
  874. p = xdr_decode_hyper(p, &res->ffiles);
  875. p = xdr_decode_hyper(p, &res->afiles);
  876. /* ignore invarsec */
  877. return 0;
  878. }
  879. /*
  880. * Decode FSINFO reply
  881. */
  882. static int
  883. nfs3_xdr_fsinfores(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
  884. {
  885. int status;
  886. status = ntohl(*p++);
  887. p = xdr_decode_post_op_attr(p, res->fattr);
  888. if (status != 0)
  889. return -nfs_stat_to_errno(status);
  890. res->rtmax = ntohl(*p++);
  891. res->rtpref = ntohl(*p++);
  892. res->rtmult = ntohl(*p++);
  893. res->wtmax = ntohl(*p++);
  894. res->wtpref = ntohl(*p++);
  895. res->wtmult = ntohl(*p++);
  896. res->dtpref = ntohl(*p++);
  897. p = xdr_decode_hyper(p, &res->maxfilesize);
  898. /* ignore time_delta and properties */
  899. res->lease_time = 0;
  900. return 0;
  901. }
  902. /*
  903. * Decode PATHCONF reply
  904. */
  905. static int
  906. nfs3_xdr_pathconfres(struct rpc_rqst *req, u32 *p, struct nfs_pathconf *res)
  907. {
  908. int status;
  909. status = ntohl(*p++);
  910. p = xdr_decode_post_op_attr(p, res->fattr);
  911. if (status != 0)
  912. return -nfs_stat_to_errno(status);
  913. res->max_link = ntohl(*p++);
  914. res->max_namelen = ntohl(*p++);
  915. /* ignore remaining fields */
  916. return 0;
  917. }
  918. /*
  919. * Decode COMMIT reply
  920. */
  921. static int
  922. nfs3_xdr_commitres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
  923. {
  924. int status;
  925. status = ntohl(*p++);
  926. p = xdr_decode_wcc_data(p, res->fattr);
  927. if (status != 0)
  928. return -nfs_stat_to_errno(status);
  929. res->verf->verifier[0] = *p++;
  930. res->verf->verifier[1] = *p++;
  931. return 0;
  932. }
  933. #ifdef CONFIG_NFS_V3_ACL
  934. /*
  935. * Decode GETACL reply
  936. */
  937. static int
  938. nfs3_xdr_getaclres(struct rpc_rqst *req, u32 *p,
  939. struct nfs3_getaclres *res)
  940. {
  941. struct xdr_buf *buf = &req->rq_rcv_buf;
  942. int status = ntohl(*p++);
  943. struct posix_acl **acl;
  944. unsigned int *aclcnt;
  945. int err, base;
  946. if (status != 0)
  947. return -nfs_stat_to_errno(status);
  948. p = xdr_decode_post_op_attr(p, res->fattr);
  949. res->mask = ntohl(*p++);
  950. if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
  951. return -EINVAL;
  952. base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
  953. acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
  954. aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
  955. err = nfsacl_decode(buf, base, aclcnt, acl);
  956. acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
  957. aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
  958. if (err > 0)
  959. err = nfsacl_decode(buf, base + err, aclcnt, acl);
  960. return (err > 0) ? 0 : err;
  961. }
  962. /*
  963. * Decode setacl reply.
  964. */
  965. static int
  966. nfs3_xdr_setaclres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
  967. {
  968. int status = ntohl(*p++);
  969. if (status)
  970. return -nfs_stat_to_errno(status);
  971. xdr_decode_post_op_attr(p, fattr);
  972. return 0;
  973. }
  974. #endif /* CONFIG_NFS_V3_ACL */
  975. #ifndef MAX
  976. # define MAX(a, b) (((a) > (b))? (a) : (b))
  977. #endif
  978. #define PROC(proc, argtype, restype, timer) \
  979. [NFS3PROC_##proc] = { \
  980. .p_proc = NFS3PROC_##proc, \
  981. .p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \
  982. .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \
  983. .p_bufsiz = MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2, \
  984. .p_timer = timer \
  985. }
  986. struct rpc_procinfo nfs3_procedures[] = {
  987. PROC(GETATTR, fhandle, attrstat, 1),
  988. PROC(SETATTR, sattrargs, wccstat, 0),
  989. PROC(LOOKUP, diropargs, lookupres, 2),
  990. PROC(ACCESS, accessargs, accessres, 1),
  991. PROC(READLINK, readlinkargs, readlinkres, 3),
  992. PROC(READ, readargs, readres, 3),
  993. PROC(WRITE, writeargs, writeres, 4),
  994. PROC(CREATE, createargs, createres, 0),
  995. PROC(MKDIR, mkdirargs, createres, 0),
  996. PROC(SYMLINK, symlinkargs, createres, 0),
  997. PROC(MKNOD, mknodargs, createres, 0),
  998. PROC(REMOVE, diropargs, wccstat, 0),
  999. PROC(RMDIR, diropargs, wccstat, 0),
  1000. PROC(RENAME, renameargs, renameres, 0),
  1001. PROC(LINK, linkargs, linkres, 0),
  1002. PROC(READDIR, readdirargs, readdirres, 3),
  1003. PROC(READDIRPLUS, readdirargs, readdirres, 3),
  1004. PROC(FSSTAT, fhandle, fsstatres, 0),
  1005. PROC(FSINFO, fhandle, fsinfores, 0),
  1006. PROC(PATHCONF, fhandle, pathconfres, 0),
  1007. PROC(COMMIT, commitargs, commitres, 5),
  1008. };
  1009. struct rpc_version nfs_version3 = {
  1010. .number = 3,
  1011. .nrprocs = sizeof(nfs3_procedures)/sizeof(nfs3_procedures[0]),
  1012. .procs = nfs3_procedures
  1013. };
  1014. #ifdef CONFIG_NFS_V3_ACL
  1015. static struct rpc_procinfo nfs3_acl_procedures[] = {
  1016. [ACLPROC3_GETACL] = {
  1017. .p_proc = ACLPROC3_GETACL,
  1018. .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,
  1019. .p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
  1020. .p_bufsiz = MAX(ACL3_getaclargs_sz, ACL3_getaclres_sz) << 2,
  1021. .p_timer = 1,
  1022. },
  1023. [ACLPROC3_SETACL] = {
  1024. .p_proc = ACLPROC3_SETACL,
  1025. .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
  1026. .p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
  1027. .p_bufsiz = MAX(ACL3_setaclargs_sz, ACL3_setaclres_sz) << 2,
  1028. .p_timer = 0,
  1029. },
  1030. };
  1031. struct rpc_version nfsacl_version3 = {
  1032. .number = 3,
  1033. .nrprocs = sizeof(nfs3_acl_procedures)/
  1034. sizeof(nfs3_acl_procedures[0]),
  1035. .procs = nfs3_acl_procedures,
  1036. };
  1037. #endif /* CONFIG_NFS_V3_ACL */