nfs3xdr.c 28 KB

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