nfs3xdr.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:25k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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