/kern_2.6.32/fs/nfs/nfs3xdr.c

http://omnia2droid.googlecode.com/ · C · 1209 lines · 899 code · 137 blank · 173 comment · 116 complexity · a89d145339217dc8e1764ac3ba8ba0e9 MD5 · raw file

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