nfs3xdr.c 24 KB

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