nfs3xdr.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173
  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. .p_statidx = NFS3PROC_##proc, \
  985. .p_name = #proc, \
  986. }
  987. struct rpc_procinfo nfs3_procedures[] = {
  988. PROC(GETATTR, fhandle, attrstat, 1),
  989. PROC(SETATTR, sattrargs, wccstat, 0),
  990. PROC(LOOKUP, diropargs, lookupres, 2),
  991. PROC(ACCESS, accessargs, accessres, 1),
  992. PROC(READLINK, readlinkargs, readlinkres, 3),
  993. PROC(READ, readargs, readres, 3),
  994. PROC(WRITE, writeargs, writeres, 4),
  995. PROC(CREATE, createargs, createres, 0),
  996. PROC(MKDIR, mkdirargs, createres, 0),
  997. PROC(SYMLINK, symlinkargs, createres, 0),
  998. PROC(MKNOD, mknodargs, createres, 0),
  999. PROC(REMOVE, diropargs, wccstat, 0),
  1000. PROC(RMDIR, diropargs, wccstat, 0),
  1001. PROC(RENAME, renameargs, renameres, 0),
  1002. PROC(LINK, linkargs, linkres, 0),
  1003. PROC(READDIR, readdirargs, readdirres, 3),
  1004. PROC(READDIRPLUS, readdirargs, readdirres, 3),
  1005. PROC(FSSTAT, fhandle, fsstatres, 0),
  1006. PROC(FSINFO, fhandle, fsinfores, 0),
  1007. PROC(PATHCONF, fhandle, pathconfres, 0),
  1008. PROC(COMMIT, commitargs, commitres, 5),
  1009. };
  1010. struct rpc_version nfs_version3 = {
  1011. .number = 3,
  1012. .nrprocs = ARRAY_SIZE(nfs3_procedures),
  1013. .procs = nfs3_procedures
  1014. };
  1015. #ifdef CONFIG_NFS_V3_ACL
  1016. static struct rpc_procinfo nfs3_acl_procedures[] = {
  1017. [ACLPROC3_GETACL] = {
  1018. .p_proc = ACLPROC3_GETACL,
  1019. .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,
  1020. .p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
  1021. .p_bufsiz = MAX(ACL3_getaclargs_sz, ACL3_getaclres_sz) << 2,
  1022. .p_timer = 1,
  1023. .p_name = "GETACL",
  1024. },
  1025. [ACLPROC3_SETACL] = {
  1026. .p_proc = ACLPROC3_SETACL,
  1027. .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
  1028. .p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
  1029. .p_bufsiz = MAX(ACL3_setaclargs_sz, ACL3_setaclres_sz) << 2,
  1030. .p_timer = 0,
  1031. .p_name = "SETACL",
  1032. },
  1033. };
  1034. struct rpc_version nfsacl_version3 = {
  1035. .number = 3,
  1036. .nrprocs = sizeof(nfs3_acl_procedures)/
  1037. sizeof(nfs3_acl_procedures[0]),
  1038. .procs = nfs3_acl_procedures,
  1039. };
  1040. #endif /* CONFIG_NFS_V3_ACL */