nfs3xdr.c 27 KB

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