nfs3xdr.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107
  1. /*
  2. * linux/fs/nfsd/nfs3xdr.c
  3. *
  4. * XDR support for nfsd/protocol version 3.
  5. *
  6. * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
  7. *
  8. * 2003-08-09 Jamie Lokier: Use htonl() for nanoseconds, not htons()!
  9. */
  10. #include <linux/types.h>
  11. #include <linux/time.h>
  12. #include <linux/nfs3.h>
  13. #include <linux/list.h>
  14. #include <linux/spinlock.h>
  15. #include <linux/dcache.h>
  16. #include <linux/namei.h>
  17. #include <linux/mm.h>
  18. #include <linux/vfs.h>
  19. #include <linux/sunrpc/xdr.h>
  20. #include <linux/sunrpc/svc.h>
  21. #include <linux/nfsd/nfsd.h>
  22. #include <linux/nfsd/xdr3.h>
  23. #define NFSDDBG_FACILITY NFSDDBG_XDR
  24. #ifdef NFSD_OPTIMIZE_SPACE
  25. # define inline
  26. #endif
  27. /*
  28. * Mapping of S_IF* types to NFS file types
  29. */
  30. static u32 nfs3_ftypes[] = {
  31. NF3NON, NF3FIFO, NF3CHR, NF3BAD,
  32. NF3DIR, NF3BAD, NF3BLK, NF3BAD,
  33. NF3REG, NF3BAD, NF3LNK, NF3BAD,
  34. NF3SOCK, NF3BAD, NF3LNK, NF3BAD,
  35. };
  36. /*
  37. * XDR functions for basic NFS types
  38. */
  39. static inline __be32 *
  40. encode_time3(__be32 *p, struct timespec *time)
  41. {
  42. *p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec);
  43. return p;
  44. }
  45. static inline __be32 *
  46. decode_time3(__be32 *p, struct timespec *time)
  47. {
  48. time->tv_sec = ntohl(*p++);
  49. time->tv_nsec = ntohl(*p++);
  50. return p;
  51. }
  52. static inline __be32 *
  53. decode_fh(__be32 *p, struct svc_fh *fhp)
  54. {
  55. unsigned int size;
  56. fh_init(fhp, NFS3_FHSIZE);
  57. size = ntohl(*p++);
  58. if (size > NFS3_FHSIZE)
  59. return NULL;
  60. memcpy(&fhp->fh_handle.fh_base, p, size);
  61. fhp->fh_handle.fh_size = size;
  62. return p + XDR_QUADLEN(size);
  63. }
  64. /* Helper function for NFSv3 ACL code */
  65. __be32 *nfs3svc_decode_fh(__be32 *p, struct svc_fh *fhp)
  66. {
  67. return decode_fh(p, fhp);
  68. }
  69. static inline __be32 *
  70. encode_fh(__be32 *p, struct svc_fh *fhp)
  71. {
  72. unsigned int size = fhp->fh_handle.fh_size;
  73. *p++ = htonl(size);
  74. if (size) p[XDR_QUADLEN(size)-1]=0;
  75. memcpy(p, &fhp->fh_handle.fh_base, size);
  76. return p + XDR_QUADLEN(size);
  77. }
  78. /*
  79. * Decode a file name and make sure that the path contains
  80. * no slashes or null bytes.
  81. */
  82. static inline __be32 *
  83. decode_filename(__be32 *p, char **namp, int *lenp)
  84. {
  85. char *name;
  86. int i;
  87. if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS3_MAXNAMLEN)) != NULL) {
  88. for (i = 0, name = *namp; i < *lenp; i++, name++) {
  89. if (*name == '\0' || *name == '/')
  90. return NULL;
  91. }
  92. }
  93. return p;
  94. }
  95. static inline __be32 *
  96. decode_sattr3(__be32 *p, struct iattr *iap)
  97. {
  98. u32 tmp;
  99. iap->ia_valid = 0;
  100. if (*p++) {
  101. iap->ia_valid |= ATTR_MODE;
  102. iap->ia_mode = ntohl(*p++);
  103. }
  104. if (*p++) {
  105. iap->ia_valid |= ATTR_UID;
  106. iap->ia_uid = ntohl(*p++);
  107. }
  108. if (*p++) {
  109. iap->ia_valid |= ATTR_GID;
  110. iap->ia_gid = ntohl(*p++);
  111. }
  112. if (*p++) {
  113. u64 newsize;
  114. iap->ia_valid |= ATTR_SIZE;
  115. p = xdr_decode_hyper(p, &newsize);
  116. if (newsize <= NFS_OFFSET_MAX)
  117. iap->ia_size = newsize;
  118. else
  119. iap->ia_size = NFS_OFFSET_MAX;
  120. }
  121. if ((tmp = ntohl(*p++)) == 1) { /* set to server time */
  122. iap->ia_valid |= ATTR_ATIME;
  123. } else if (tmp == 2) { /* set to client time */
  124. iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
  125. iap->ia_atime.tv_sec = ntohl(*p++);
  126. iap->ia_atime.tv_nsec = ntohl(*p++);
  127. }
  128. if ((tmp = ntohl(*p++)) == 1) { /* set to server time */
  129. iap->ia_valid |= ATTR_MTIME;
  130. } else if (tmp == 2) { /* set to client time */
  131. iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
  132. iap->ia_mtime.tv_sec = ntohl(*p++);
  133. iap->ia_mtime.tv_nsec = ntohl(*p++);
  134. }
  135. return p;
  136. }
  137. static inline __be32 *
  138. encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
  139. struct kstat *stat)
  140. {
  141. struct dentry *dentry = fhp->fh_dentry;
  142. struct timespec time;
  143. *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
  144. *p++ = htonl((u32) stat->mode);
  145. *p++ = htonl((u32) stat->nlink);
  146. *p++ = htonl((u32) nfsd_ruid(rqstp, stat->uid));
  147. *p++ = htonl((u32) nfsd_rgid(rqstp, stat->gid));
  148. if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) {
  149. p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
  150. } else {
  151. p = xdr_encode_hyper(p, (u64) stat->size);
  152. }
  153. p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9);
  154. *p++ = htonl((u32) MAJOR(stat->rdev));
  155. *p++ = htonl((u32) MINOR(stat->rdev));
  156. if (is_fsid(fhp, rqstp->rq_reffh))
  157. p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
  158. else
  159. p = xdr_encode_hyper(p, (u64) huge_encode_dev(stat->dev));
  160. p = xdr_encode_hyper(p, (u64) stat->ino);
  161. p = encode_time3(p, &stat->atime);
  162. lease_get_mtime(dentry->d_inode, &time);
  163. p = encode_time3(p, &time);
  164. p = encode_time3(p, &stat->ctime);
  165. return p;
  166. }
  167. static inline __be32 *
  168. encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
  169. {
  170. struct inode *inode = fhp->fh_dentry->d_inode;
  171. /* Attributes to follow */
  172. *p++ = xdr_one;
  173. *p++ = htonl(nfs3_ftypes[(fhp->fh_post_mode & S_IFMT) >> 12]);
  174. *p++ = htonl((u32) fhp->fh_post_mode);
  175. *p++ = htonl((u32) fhp->fh_post_nlink);
  176. *p++ = htonl((u32) nfsd_ruid(rqstp, fhp->fh_post_uid));
  177. *p++ = htonl((u32) nfsd_rgid(rqstp, fhp->fh_post_gid));
  178. if (S_ISLNK(fhp->fh_post_mode) && fhp->fh_post_size > NFS3_MAXPATHLEN) {
  179. p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
  180. } else {
  181. p = xdr_encode_hyper(p, (u64) fhp->fh_post_size);
  182. }
  183. p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9);
  184. *p++ = fhp->fh_post_rdev[0];
  185. *p++ = fhp->fh_post_rdev[1];
  186. if (is_fsid(fhp, rqstp->rq_reffh))
  187. p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
  188. else
  189. p = xdr_encode_hyper(p, (u64)huge_encode_dev(inode->i_sb->s_dev));
  190. p = xdr_encode_hyper(p, (u64) inode->i_ino);
  191. p = encode_time3(p, &fhp->fh_post_atime);
  192. p = encode_time3(p, &fhp->fh_post_mtime);
  193. p = encode_time3(p, &fhp->fh_post_ctime);
  194. return p;
  195. }
  196. /*
  197. * Encode post-operation attributes.
  198. * The inode may be NULL if the call failed because of a stale file
  199. * handle. In this case, no attributes are returned.
  200. */
  201. static __be32 *
  202. encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
  203. {
  204. struct dentry *dentry = fhp->fh_dentry;
  205. if (dentry && dentry->d_inode != NULL) {
  206. int err;
  207. struct kstat stat;
  208. err = vfs_getattr(fhp->fh_export->ex_mnt, dentry, &stat);
  209. if (!err) {
  210. *p++ = xdr_one; /* attributes follow */
  211. return encode_fattr3(rqstp, p, fhp, &stat);
  212. }
  213. }
  214. *p++ = xdr_zero;
  215. return p;
  216. }
  217. /* Helper for NFSv3 ACLs */
  218. __be32 *
  219. nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
  220. {
  221. return encode_post_op_attr(rqstp, p, fhp);
  222. }
  223. /*
  224. * Enocde weak cache consistency data
  225. */
  226. static __be32 *
  227. encode_wcc_data(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
  228. {
  229. struct dentry *dentry = fhp->fh_dentry;
  230. if (dentry && dentry->d_inode && fhp->fh_post_saved) {
  231. if (fhp->fh_pre_saved) {
  232. *p++ = xdr_one;
  233. p = xdr_encode_hyper(p, (u64) fhp->fh_pre_size);
  234. p = encode_time3(p, &fhp->fh_pre_mtime);
  235. p = encode_time3(p, &fhp->fh_pre_ctime);
  236. } else {
  237. *p++ = xdr_zero;
  238. }
  239. return encode_saved_post_attr(rqstp, p, fhp);
  240. }
  241. /* no pre- or post-attrs */
  242. *p++ = xdr_zero;
  243. return encode_post_op_attr(rqstp, p, fhp);
  244. }
  245. /*
  246. * XDR decode functions
  247. */
  248. int
  249. nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p, struct nfsd_fhandle *args)
  250. {
  251. if (!(p = decode_fh(p, &args->fh)))
  252. return 0;
  253. return xdr_argsize_check(rqstp, p);
  254. }
  255. int
  256. nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p,
  257. struct nfsd3_sattrargs *args)
  258. {
  259. if (!(p = decode_fh(p, &args->fh))
  260. || !(p = decode_sattr3(p, &args->attrs)))
  261. return 0;
  262. if ((args->check_guard = ntohl(*p++)) != 0) {
  263. struct timespec time;
  264. p = decode_time3(p, &time);
  265. args->guardtime = time.tv_sec;
  266. }
  267. return xdr_argsize_check(rqstp, p);
  268. }
  269. int
  270. nfs3svc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p,
  271. struct nfsd3_diropargs *args)
  272. {
  273. if (!(p = decode_fh(p, &args->fh))
  274. || !(p = decode_filename(p, &args->name, &args->len)))
  275. return 0;
  276. return xdr_argsize_check(rqstp, p);
  277. }
  278. int
  279. nfs3svc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p,
  280. struct nfsd3_accessargs *args)
  281. {
  282. if (!(p = decode_fh(p, &args->fh)))
  283. return 0;
  284. args->access = ntohl(*p++);
  285. return xdr_argsize_check(rqstp, p);
  286. }
  287. int
  288. nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
  289. struct nfsd3_readargs *args)
  290. {
  291. unsigned int len;
  292. int v,pn;
  293. u32 max_blocksize = svc_max_payload(rqstp);
  294. if (!(p = decode_fh(p, &args->fh))
  295. || !(p = xdr_decode_hyper(p, &args->offset)))
  296. return 0;
  297. len = args->count = ntohl(*p++);
  298. if (len > max_blocksize)
  299. len = max_blocksize;
  300. /* set up the kvec */
  301. v=0;
  302. while (len > 0) {
  303. pn = rqstp->rq_resused++;
  304. rqstp->rq_vec[v].iov_base = page_address(rqstp->rq_respages[pn]);
  305. rqstp->rq_vec[v].iov_len = len < PAGE_SIZE? len : PAGE_SIZE;
  306. len -= rqstp->rq_vec[v].iov_len;
  307. v++;
  308. }
  309. args->vlen = v;
  310. return xdr_argsize_check(rqstp, p);
  311. }
  312. int
  313. nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
  314. struct nfsd3_writeargs *args)
  315. {
  316. unsigned int len, v, hdr;
  317. u32 max_blocksize = svc_max_payload(rqstp);
  318. if (!(p = decode_fh(p, &args->fh))
  319. || !(p = xdr_decode_hyper(p, &args->offset)))
  320. return 0;
  321. args->count = ntohl(*p++);
  322. args->stable = ntohl(*p++);
  323. len = args->len = ntohl(*p++);
  324. hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
  325. if (rqstp->rq_arg.len < hdr ||
  326. rqstp->rq_arg.len - hdr < len)
  327. return 0;
  328. rqstp->rq_vec[0].iov_base = (void*)p;
  329. rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
  330. if (len > max_blocksize)
  331. len = max_blocksize;
  332. v= 0;
  333. while (len > rqstp->rq_vec[v].iov_len) {
  334. len -= rqstp->rq_vec[v].iov_len;
  335. v++;
  336. rqstp->rq_vec[v].iov_base = page_address(rqstp->rq_pages[v]);
  337. rqstp->rq_vec[v].iov_len = PAGE_SIZE;
  338. }
  339. rqstp->rq_vec[v].iov_len = len;
  340. args->vlen = v+1;
  341. return args->count == args->len && rqstp->rq_vec[0].iov_len > 0;
  342. }
  343. int
  344. nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p,
  345. struct nfsd3_createargs *args)
  346. {
  347. if (!(p = decode_fh(p, &args->fh))
  348. || !(p = decode_filename(p, &args->name, &args->len)))
  349. return 0;
  350. switch (args->createmode = ntohl(*p++)) {
  351. case NFS3_CREATE_UNCHECKED:
  352. case NFS3_CREATE_GUARDED:
  353. if (!(p = decode_sattr3(p, &args->attrs)))
  354. return 0;
  355. break;
  356. case NFS3_CREATE_EXCLUSIVE:
  357. args->verf = p;
  358. p += 2;
  359. break;
  360. default:
  361. return 0;
  362. }
  363. return xdr_argsize_check(rqstp, p);
  364. }
  365. int
  366. nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p,
  367. struct nfsd3_createargs *args)
  368. {
  369. if (!(p = decode_fh(p, &args->fh))
  370. || !(p = decode_filename(p, &args->name, &args->len))
  371. || !(p = decode_sattr3(p, &args->attrs)))
  372. return 0;
  373. return xdr_argsize_check(rqstp, p);
  374. }
  375. int
  376. nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p,
  377. struct nfsd3_symlinkargs *args)
  378. {
  379. unsigned int len;
  380. int avail;
  381. char *old, *new;
  382. struct kvec *vec;
  383. if (!(p = decode_fh(p, &args->ffh))
  384. || !(p = decode_filename(p, &args->fname, &args->flen))
  385. || !(p = decode_sattr3(p, &args->attrs))
  386. )
  387. return 0;
  388. /* now decode the pathname, which might be larger than the first page.
  389. * As we have to check for nul's anyway, we copy it into a new page
  390. * This page appears in the rq_res.pages list, but as pages_len is always
  391. * 0, it won't get in the way
  392. */
  393. len = ntohl(*p++);
  394. if (len == 0 || len > NFS3_MAXPATHLEN || len >= PAGE_SIZE)
  395. return 0;
  396. args->tname = new =
  397. page_address(rqstp->rq_respages[rqstp->rq_resused++]);
  398. args->tlen = len;
  399. /* first copy and check from the first page */
  400. old = (char*)p;
  401. vec = &rqstp->rq_arg.head[0];
  402. avail = vec->iov_len - (old - (char*)vec->iov_base);
  403. while (len && avail && *old) {
  404. *new++ = *old++;
  405. len--;
  406. avail--;
  407. }
  408. /* now copy next page if there is one */
  409. if (len && !avail && rqstp->rq_arg.page_len) {
  410. avail = rqstp->rq_arg.page_len;
  411. if (avail > PAGE_SIZE) avail = PAGE_SIZE;
  412. old = page_address(rqstp->rq_arg.pages[0]);
  413. }
  414. while (len && avail && *old) {
  415. *new++ = *old++;
  416. len--;
  417. avail--;
  418. }
  419. *new = '\0';
  420. if (len)
  421. return 0;
  422. return 1;
  423. }
  424. int
  425. nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p,
  426. struct nfsd3_mknodargs *args)
  427. {
  428. if (!(p = decode_fh(p, &args->fh))
  429. || !(p = decode_filename(p, &args->name, &args->len)))
  430. return 0;
  431. args->ftype = ntohl(*p++);
  432. if (args->ftype == NF3BLK || args->ftype == NF3CHR
  433. || args->ftype == NF3SOCK || args->ftype == NF3FIFO) {
  434. if (!(p = decode_sattr3(p, &args->attrs)))
  435. return 0;
  436. }
  437. if (args->ftype == NF3BLK || args->ftype == NF3CHR) {
  438. args->major = ntohl(*p++);
  439. args->minor = ntohl(*p++);
  440. }
  441. return xdr_argsize_check(rqstp, p);
  442. }
  443. int
  444. nfs3svc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p,
  445. struct nfsd3_renameargs *args)
  446. {
  447. if (!(p = decode_fh(p, &args->ffh))
  448. || !(p = decode_filename(p, &args->fname, &args->flen))
  449. || !(p = decode_fh(p, &args->tfh))
  450. || !(p = decode_filename(p, &args->tname, &args->tlen)))
  451. return 0;
  452. return xdr_argsize_check(rqstp, p);
  453. }
  454. int
  455. nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p,
  456. struct nfsd3_readlinkargs *args)
  457. {
  458. if (!(p = decode_fh(p, &args->fh)))
  459. return 0;
  460. args->buffer =
  461. page_address(rqstp->rq_respages[rqstp->rq_resused++]);
  462. return xdr_argsize_check(rqstp, p);
  463. }
  464. int
  465. nfs3svc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p,
  466. struct nfsd3_linkargs *args)
  467. {
  468. if (!(p = decode_fh(p, &args->ffh))
  469. || !(p = decode_fh(p, &args->tfh))
  470. || !(p = decode_filename(p, &args->tname, &args->tlen)))
  471. return 0;
  472. return xdr_argsize_check(rqstp, p);
  473. }
  474. int
  475. nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p,
  476. struct nfsd3_readdirargs *args)
  477. {
  478. if (!(p = decode_fh(p, &args->fh)))
  479. return 0;
  480. p = xdr_decode_hyper(p, &args->cookie);
  481. args->verf = p; p += 2;
  482. args->dircount = ~0;
  483. args->count = ntohl(*p++);
  484. if (args->count > PAGE_SIZE)
  485. args->count = PAGE_SIZE;
  486. args->buffer =
  487. page_address(rqstp->rq_respages[rqstp->rq_resused++]);
  488. return xdr_argsize_check(rqstp, p);
  489. }
  490. int
  491. nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p,
  492. struct nfsd3_readdirargs *args)
  493. {
  494. int len, pn;
  495. u32 max_blocksize = svc_max_payload(rqstp);
  496. if (!(p = decode_fh(p, &args->fh)))
  497. return 0;
  498. p = xdr_decode_hyper(p, &args->cookie);
  499. args->verf = p; p += 2;
  500. args->dircount = ntohl(*p++);
  501. args->count = ntohl(*p++);
  502. len = (args->count > max_blocksize) ? max_blocksize :
  503. args->count;
  504. args->count = len;
  505. while (len > 0) {
  506. pn = rqstp->rq_resused++;
  507. if (!args->buffer)
  508. args->buffer = page_address(rqstp->rq_respages[pn]);
  509. len -= PAGE_SIZE;
  510. }
  511. return xdr_argsize_check(rqstp, p);
  512. }
  513. int
  514. nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p,
  515. struct nfsd3_commitargs *args)
  516. {
  517. if (!(p = decode_fh(p, &args->fh)))
  518. return 0;
  519. p = xdr_decode_hyper(p, &args->offset);
  520. args->count = ntohl(*p++);
  521. return xdr_argsize_check(rqstp, p);
  522. }
  523. /*
  524. * XDR encode functions
  525. */
  526. /*
  527. * There must be an encoding function for void results so svc_process
  528. * will work properly.
  529. */
  530. int
  531. nfs3svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
  532. {
  533. return xdr_ressize_check(rqstp, p);
  534. }
  535. /* GETATTR */
  536. int
  537. nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p,
  538. struct nfsd3_attrstat *resp)
  539. {
  540. if (resp->status == 0)
  541. p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat);
  542. return xdr_ressize_check(rqstp, p);
  543. }
  544. /* SETATTR, REMOVE, RMDIR */
  545. int
  546. nfs3svc_encode_wccstat(struct svc_rqst *rqstp, __be32 *p,
  547. struct nfsd3_attrstat *resp)
  548. {
  549. p = encode_wcc_data(rqstp, p, &resp->fh);
  550. return xdr_ressize_check(rqstp, p);
  551. }
  552. /* LOOKUP */
  553. int
  554. nfs3svc_encode_diropres(struct svc_rqst *rqstp, __be32 *p,
  555. struct nfsd3_diropres *resp)
  556. {
  557. if (resp->status == 0) {
  558. p = encode_fh(p, &resp->fh);
  559. p = encode_post_op_attr(rqstp, p, &resp->fh);
  560. }
  561. p = encode_post_op_attr(rqstp, p, &resp->dirfh);
  562. return xdr_ressize_check(rqstp, p);
  563. }
  564. /* ACCESS */
  565. int
  566. nfs3svc_encode_accessres(struct svc_rqst *rqstp, __be32 *p,
  567. struct nfsd3_accessres *resp)
  568. {
  569. p = encode_post_op_attr(rqstp, p, &resp->fh);
  570. if (resp->status == 0)
  571. *p++ = htonl(resp->access);
  572. return xdr_ressize_check(rqstp, p);
  573. }
  574. /* READLINK */
  575. int
  576. nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p,
  577. struct nfsd3_readlinkres *resp)
  578. {
  579. p = encode_post_op_attr(rqstp, p, &resp->fh);
  580. if (resp->status == 0) {
  581. *p++ = htonl(resp->len);
  582. xdr_ressize_check(rqstp, p);
  583. rqstp->rq_res.page_len = resp->len;
  584. if (resp->len & 3) {
  585. /* need to pad the tail */
  586. rqstp->rq_res.tail[0].iov_base = p;
  587. *p = 0;
  588. rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3);
  589. }
  590. return 1;
  591. } else
  592. return xdr_ressize_check(rqstp, p);
  593. }
  594. /* READ */
  595. int
  596. nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p,
  597. struct nfsd3_readres *resp)
  598. {
  599. p = encode_post_op_attr(rqstp, p, &resp->fh);
  600. if (resp->status == 0) {
  601. *p++ = htonl(resp->count);
  602. *p++ = htonl(resp->eof);
  603. *p++ = htonl(resp->count); /* xdr opaque count */
  604. xdr_ressize_check(rqstp, p);
  605. /* now update rqstp->rq_res to reflect data aswell */
  606. rqstp->rq_res.page_len = resp->count;
  607. if (resp->count & 3) {
  608. /* need to pad the tail */
  609. rqstp->rq_res.tail[0].iov_base = p;
  610. *p = 0;
  611. rqstp->rq_res.tail[0].iov_len = 4 - (resp->count & 3);
  612. }
  613. return 1;
  614. } else
  615. return xdr_ressize_check(rqstp, p);
  616. }
  617. /* WRITE */
  618. int
  619. nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p,
  620. struct nfsd3_writeres *resp)
  621. {
  622. p = encode_wcc_data(rqstp, p, &resp->fh);
  623. if (resp->status == 0) {
  624. *p++ = htonl(resp->count);
  625. *p++ = htonl(resp->committed);
  626. *p++ = htonl(nfssvc_boot.tv_sec);
  627. *p++ = htonl(nfssvc_boot.tv_usec);
  628. }
  629. return xdr_ressize_check(rqstp, p);
  630. }
  631. /* CREATE, MKDIR, SYMLINK, MKNOD */
  632. int
  633. nfs3svc_encode_createres(struct svc_rqst *rqstp, __be32 *p,
  634. struct nfsd3_diropres *resp)
  635. {
  636. if (resp->status == 0) {
  637. *p++ = xdr_one;
  638. p = encode_fh(p, &resp->fh);
  639. p = encode_post_op_attr(rqstp, p, &resp->fh);
  640. }
  641. p = encode_wcc_data(rqstp, p, &resp->dirfh);
  642. return xdr_ressize_check(rqstp, p);
  643. }
  644. /* RENAME */
  645. int
  646. nfs3svc_encode_renameres(struct svc_rqst *rqstp, __be32 *p,
  647. struct nfsd3_renameres *resp)
  648. {
  649. p = encode_wcc_data(rqstp, p, &resp->ffh);
  650. p = encode_wcc_data(rqstp, p, &resp->tfh);
  651. return xdr_ressize_check(rqstp, p);
  652. }
  653. /* LINK */
  654. int
  655. nfs3svc_encode_linkres(struct svc_rqst *rqstp, __be32 *p,
  656. struct nfsd3_linkres *resp)
  657. {
  658. p = encode_post_op_attr(rqstp, p, &resp->fh);
  659. p = encode_wcc_data(rqstp, p, &resp->tfh);
  660. return xdr_ressize_check(rqstp, p);
  661. }
  662. /* READDIR */
  663. int
  664. nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p,
  665. struct nfsd3_readdirres *resp)
  666. {
  667. p = encode_post_op_attr(rqstp, p, &resp->fh);
  668. if (resp->status == 0) {
  669. /* stupid readdir cookie */
  670. memcpy(p, resp->verf, 8); p += 2;
  671. xdr_ressize_check(rqstp, p);
  672. if (rqstp->rq_res.head[0].iov_len + (2<<2) > PAGE_SIZE)
  673. return 1; /*No room for trailer */
  674. rqstp->rq_res.page_len = (resp->count) << 2;
  675. /* add the 'tail' to the end of the 'head' page - page 0. */
  676. rqstp->rq_res.tail[0].iov_base = p;
  677. *p++ = 0; /* no more entries */
  678. *p++ = htonl(resp->common.err == nfserr_eof);
  679. rqstp->rq_res.tail[0].iov_len = 2<<2;
  680. return 1;
  681. } else
  682. return xdr_ressize_check(rqstp, p);
  683. }
  684. static inline __be32 *
  685. encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name,
  686. int namlen, ino_t ino)
  687. {
  688. *p++ = xdr_one; /* mark entry present */
  689. p = xdr_encode_hyper(p, ino); /* file id */
  690. p = xdr_encode_array(p, name, namlen);/* name length & name */
  691. cd->offset = p; /* remember pointer */
  692. p = xdr_encode_hyper(p, NFS_OFFSET_MAX);/* offset of next entry */
  693. return p;
  694. }
  695. static inline __be32 *
  696. encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p,
  697. struct svc_fh *fhp)
  698. {
  699. p = encode_post_op_attr(cd->rqstp, p, fhp);
  700. *p++ = xdr_one; /* yes, a file handle follows */
  701. p = encode_fh(p, fhp);
  702. fh_put(fhp);
  703. return p;
  704. }
  705. static int
  706. compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
  707. const char *name, int namlen)
  708. {
  709. struct svc_export *exp;
  710. struct dentry *dparent, *dchild;
  711. int rv = 0;
  712. dparent = cd->fh.fh_dentry;
  713. exp = cd->fh.fh_export;
  714. fh_init(fhp, NFS3_FHSIZE);
  715. if (isdotent(name, namlen)) {
  716. if (namlen == 2) {
  717. dchild = dget_parent(dparent);
  718. if (dchild == dparent) {
  719. /* filesystem root - cannot return filehandle for ".." */
  720. dput(dchild);
  721. return 1;
  722. }
  723. } else
  724. dchild = dget(dparent);
  725. } else
  726. dchild = lookup_one_len(name, dparent, namlen);
  727. if (IS_ERR(dchild))
  728. return 1;
  729. if (d_mountpoint(dchild) ||
  730. fh_compose(fhp, exp, dchild, &cd->fh) != 0 ||
  731. !dchild->d_inode)
  732. rv = 1;
  733. dput(dchild);
  734. return rv;
  735. }
  736. /*
  737. * Encode a directory entry. This one works for both normal readdir
  738. * and readdirplus.
  739. * The normal readdir reply requires 2 (fileid) + 1 (stringlen)
  740. * + string + 2 (cookie) + 1 (next) words, i.e. 6 + strlen.
  741. *
  742. * The readdirplus baggage is 1+21 words for post_op_attr, plus the
  743. * file handle.
  744. */
  745. #define NFS3_ENTRY_BAGGAGE (2 + 1 + 2 + 1)
  746. #define NFS3_ENTRYPLUS_BAGGAGE (1 + 21 + 1 + (NFS3_FHSIZE >> 2))
  747. static int
  748. encode_entry(struct readdir_cd *ccd, const char *name,
  749. int namlen, off_t offset, ino_t ino, unsigned int d_type, int plus)
  750. {
  751. struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres,
  752. common);
  753. __be32 *p = cd->buffer;
  754. caddr_t curr_page_addr = NULL;
  755. int pn; /* current page number */
  756. int slen; /* string (name) length */
  757. int elen; /* estimated entry length in words */
  758. int num_entry_words = 0; /* actual number of words */
  759. if (cd->offset) {
  760. u64 offset64 = offset;
  761. if (unlikely(cd->offset1)) {
  762. /* we ended up with offset on a page boundary */
  763. *cd->offset = htonl(offset64 >> 32);
  764. *cd->offset1 = htonl(offset64 & 0xffffffff);
  765. cd->offset1 = NULL;
  766. } else {
  767. xdr_encode_hyper(cd->offset, (u64) offset);
  768. }
  769. }
  770. /*
  771. dprintk("encode_entry(%.*s @%ld%s)\n",
  772. namlen, name, (long) offset, plus? " plus" : "");
  773. */
  774. /* truncate filename if too long */
  775. if (namlen > NFS3_MAXNAMLEN)
  776. namlen = NFS3_MAXNAMLEN;
  777. slen = XDR_QUADLEN(namlen);
  778. elen = slen + NFS3_ENTRY_BAGGAGE
  779. + (plus? NFS3_ENTRYPLUS_BAGGAGE : 0);
  780. if (cd->buflen < elen) {
  781. cd->common.err = nfserr_toosmall;
  782. return -EINVAL;
  783. }
  784. /* determine which page in rq_respages[] we are currently filling */
  785. for (pn=1; pn < cd->rqstp->rq_resused; pn++) {
  786. curr_page_addr = page_address(cd->rqstp->rq_respages[pn]);
  787. if (((caddr_t)cd->buffer >= curr_page_addr) &&
  788. ((caddr_t)cd->buffer < curr_page_addr + PAGE_SIZE))
  789. break;
  790. }
  791. if ((caddr_t)(cd->buffer + elen) < (curr_page_addr + PAGE_SIZE)) {
  792. /* encode entry in current page */
  793. p = encode_entry_baggage(cd, p, name, namlen, ino);
  794. /* throw in readdirplus baggage */
  795. if (plus) {
  796. struct svc_fh fh;
  797. if (compose_entry_fh(cd, &fh, name, namlen) > 0) {
  798. *p++ = 0;
  799. *p++ = 0;
  800. } else
  801. p = encode_entryplus_baggage(cd, p, &fh);
  802. }
  803. num_entry_words = p - cd->buffer;
  804. } else if (cd->rqstp->rq_respages[pn+1] != NULL) {
  805. /* temporarily encode entry into next page, then move back to
  806. * current and next page in rq_respages[] */
  807. __be32 *p1, *tmp;
  808. int len1, len2;
  809. /* grab next page for temporary storage of entry */
  810. p1 = tmp = page_address(cd->rqstp->rq_respages[pn+1]);
  811. p1 = encode_entry_baggage(cd, p1, name, namlen, ino);
  812. /* throw in readdirplus baggage */
  813. if (plus) {
  814. struct svc_fh fh;
  815. if (compose_entry_fh(cd, &fh, name, namlen) > 0) {
  816. /* zero out the filehandle */
  817. *p1++ = 0;
  818. *p1++ = 0;
  819. } else
  820. p1 = encode_entryplus_baggage(cd, p1, &fh);
  821. }
  822. /* determine entry word length and lengths to go in pages */
  823. num_entry_words = p1 - tmp;
  824. len1 = curr_page_addr + PAGE_SIZE - (caddr_t)cd->buffer;
  825. if ((num_entry_words << 2) < len1) {
  826. /* the actual number of words in the entry is less
  827. * than elen and can still fit in the current page
  828. */
  829. memmove(p, tmp, num_entry_words << 2);
  830. p += num_entry_words;
  831. /* update offset */
  832. cd->offset = cd->buffer + (cd->offset - tmp);
  833. } else {
  834. unsigned int offset_r = (cd->offset - tmp) << 2;
  835. /* update pointer to offset location.
  836. * This is a 64bit quantity, so we need to
  837. * deal with 3 cases:
  838. * - entirely in first page
  839. * - entirely in second page
  840. * - 4 bytes in each page
  841. */
  842. if (offset_r + 8 <= len1) {
  843. cd->offset = p + (cd->offset - tmp);
  844. } else if (offset_r >= len1) {
  845. cd->offset -= len1 >> 2;
  846. } else {
  847. /* sitting on the fence */
  848. BUG_ON(offset_r != len1 - 4);
  849. cd->offset = p + (cd->offset - tmp);
  850. cd->offset1 = tmp;
  851. }
  852. len2 = (num_entry_words << 2) - len1;
  853. /* move from temp page to current and next pages */
  854. memmove(p, tmp, len1);
  855. memmove(tmp, (caddr_t)tmp+len1, len2);
  856. p = tmp + (len2 >> 2);
  857. }
  858. }
  859. else {
  860. cd->common.err = nfserr_toosmall;
  861. return -EINVAL;
  862. }
  863. cd->buflen -= num_entry_words;
  864. cd->buffer = p;
  865. cd->common.err = nfs_ok;
  866. return 0;
  867. }
  868. int
  869. nfs3svc_encode_entry(struct readdir_cd *cd, const char *name,
  870. int namlen, loff_t offset, ino_t ino, unsigned int d_type)
  871. {
  872. return encode_entry(cd, name, namlen, offset, ino, d_type, 0);
  873. }
  874. int
  875. nfs3svc_encode_entry_plus(struct readdir_cd *cd, const char *name,
  876. int namlen, loff_t offset, ino_t ino, unsigned int d_type)
  877. {
  878. return encode_entry(cd, name, namlen, offset, ino, d_type, 1);
  879. }
  880. /* FSSTAT */
  881. int
  882. nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, __be32 *p,
  883. struct nfsd3_fsstatres *resp)
  884. {
  885. struct kstatfs *s = &resp->stats;
  886. u64 bs = s->f_bsize;
  887. *p++ = xdr_zero; /* no post_op_attr */
  888. if (resp->status == 0) {
  889. p = xdr_encode_hyper(p, bs * s->f_blocks); /* total bytes */
  890. p = xdr_encode_hyper(p, bs * s->f_bfree); /* free bytes */
  891. p = xdr_encode_hyper(p, bs * s->f_bavail); /* user available bytes */
  892. p = xdr_encode_hyper(p, s->f_files); /* total inodes */
  893. p = xdr_encode_hyper(p, s->f_ffree); /* free inodes */
  894. p = xdr_encode_hyper(p, s->f_ffree); /* user available inodes */
  895. *p++ = htonl(resp->invarsec); /* mean unchanged time */
  896. }
  897. return xdr_ressize_check(rqstp, p);
  898. }
  899. /* FSINFO */
  900. int
  901. nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, __be32 *p,
  902. struct nfsd3_fsinfores *resp)
  903. {
  904. *p++ = xdr_zero; /* no post_op_attr */
  905. if (resp->status == 0) {
  906. *p++ = htonl(resp->f_rtmax);
  907. *p++ = htonl(resp->f_rtpref);
  908. *p++ = htonl(resp->f_rtmult);
  909. *p++ = htonl(resp->f_wtmax);
  910. *p++ = htonl(resp->f_wtpref);
  911. *p++ = htonl(resp->f_wtmult);
  912. *p++ = htonl(resp->f_dtpref);
  913. p = xdr_encode_hyper(p, resp->f_maxfilesize);
  914. *p++ = xdr_one;
  915. *p++ = xdr_zero;
  916. *p++ = htonl(resp->f_properties);
  917. }
  918. return xdr_ressize_check(rqstp, p);
  919. }
  920. /* PATHCONF */
  921. int
  922. nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, __be32 *p,
  923. struct nfsd3_pathconfres *resp)
  924. {
  925. *p++ = xdr_zero; /* no post_op_attr */
  926. if (resp->status == 0) {
  927. *p++ = htonl(resp->p_link_max);
  928. *p++ = htonl(resp->p_name_max);
  929. *p++ = htonl(resp->p_no_trunc);
  930. *p++ = htonl(resp->p_chown_restricted);
  931. *p++ = htonl(resp->p_case_insensitive);
  932. *p++ = htonl(resp->p_case_preserving);
  933. }
  934. return xdr_ressize_check(rqstp, p);
  935. }
  936. /* COMMIT */
  937. int
  938. nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p,
  939. struct nfsd3_commitres *resp)
  940. {
  941. p = encode_wcc_data(rqstp, p, &resp->fh);
  942. /* Write verifier */
  943. if (resp->status == 0) {
  944. *p++ = htonl(nfssvc_boot.tv_sec);
  945. *p++ = htonl(nfssvc_boot.tv_usec);
  946. }
  947. return xdr_ressize_check(rqstp, p);
  948. }
  949. /*
  950. * XDR release functions
  951. */
  952. int
  953. nfs3svc_release_fhandle(struct svc_rqst *rqstp, __be32 *p,
  954. struct nfsd3_attrstat *resp)
  955. {
  956. fh_put(&resp->fh);
  957. return 1;
  958. }
  959. int
  960. nfs3svc_release_fhandle2(struct svc_rqst *rqstp, __be32 *p,
  961. struct nfsd3_fhandle_pair *resp)
  962. {
  963. fh_put(&resp->fh1);
  964. fh_put(&resp->fh2);
  965. return 1;
  966. }