nfs3proc.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Process version 3 NFS requests.
  4. *
  5. * Copyright (C) 1996, 1997, 1998 Olaf Kirch <okir@monad.swb.de>
  6. */
  7. #include <linux/fs.h>
  8. #include <linux/ext2_fs.h>
  9. #include <linux/magic.h>
  10. #include "cache.h"
  11. #include "xdr3.h"
  12. #include "vfs.h"
  13. #define NFSDDBG_FACILITY NFSDDBG_PROC
  14. #define RETURN_STATUS(st) { resp->status = (st); return (st); }
  15. static int nfs3_ftypes[] = {
  16. 0, /* NF3NON */
  17. S_IFREG, /* NF3REG */
  18. S_IFDIR, /* NF3DIR */
  19. S_IFBLK, /* NF3BLK */
  20. S_IFCHR, /* NF3CHR */
  21. S_IFLNK, /* NF3LNK */
  22. S_IFSOCK, /* NF3SOCK */
  23. S_IFIFO, /* NF3FIFO */
  24. };
  25. /*
  26. * NULL call.
  27. */
  28. static __be32
  29. nfsd3_proc_null(struct svc_rqst *rqstp)
  30. {
  31. return nfs_ok;
  32. }
  33. /*
  34. * Get a file's attributes
  35. */
  36. static __be32
  37. nfsd3_proc_getattr(struct svc_rqst *rqstp)
  38. {
  39. struct nfsd_fhandle *argp = rqstp->rq_argp;
  40. struct nfsd3_attrstat *resp = rqstp->rq_resp;
  41. __be32 nfserr;
  42. dprintk("nfsd: GETATTR(3) %s\n",
  43. SVCFH_fmt(&argp->fh));
  44. fh_copy(&resp->fh, &argp->fh);
  45. nfserr = fh_verify(rqstp, &resp->fh, 0,
  46. NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
  47. if (nfserr)
  48. RETURN_STATUS(nfserr);
  49. nfserr = fh_getattr(&resp->fh, &resp->stat);
  50. RETURN_STATUS(nfserr);
  51. }
  52. /*
  53. * Set a file's attributes
  54. */
  55. static __be32
  56. nfsd3_proc_setattr(struct svc_rqst *rqstp)
  57. {
  58. struct nfsd3_sattrargs *argp = rqstp->rq_argp;
  59. struct nfsd3_attrstat *resp = rqstp->rq_resp;
  60. __be32 nfserr;
  61. dprintk("nfsd: SETATTR(3) %s\n",
  62. SVCFH_fmt(&argp->fh));
  63. fh_copy(&resp->fh, &argp->fh);
  64. nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,
  65. argp->check_guard, argp->guardtime);
  66. RETURN_STATUS(nfserr);
  67. }
  68. /*
  69. * Look up a path name component
  70. */
  71. static __be32
  72. nfsd3_proc_lookup(struct svc_rqst *rqstp)
  73. {
  74. struct nfsd3_diropargs *argp = rqstp->rq_argp;
  75. struct nfsd3_diropres *resp = rqstp->rq_resp;
  76. __be32 nfserr;
  77. dprintk("nfsd: LOOKUP(3) %s %.*s\n",
  78. SVCFH_fmt(&argp->fh),
  79. argp->len,
  80. argp->name);
  81. fh_copy(&resp->dirfh, &argp->fh);
  82. fh_init(&resp->fh, NFS3_FHSIZE);
  83. nfserr = nfsd_lookup(rqstp, &resp->dirfh,
  84. argp->name,
  85. argp->len,
  86. &resp->fh);
  87. RETURN_STATUS(nfserr);
  88. }
  89. /*
  90. * Check file access
  91. */
  92. static __be32
  93. nfsd3_proc_access(struct svc_rqst *rqstp)
  94. {
  95. struct nfsd3_accessargs *argp = rqstp->rq_argp;
  96. struct nfsd3_accessres *resp = rqstp->rq_resp;
  97. __be32 nfserr;
  98. dprintk("nfsd: ACCESS(3) %s 0x%x\n",
  99. SVCFH_fmt(&argp->fh),
  100. argp->access);
  101. fh_copy(&resp->fh, &argp->fh);
  102. resp->access = argp->access;
  103. nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
  104. RETURN_STATUS(nfserr);
  105. }
  106. /*
  107. * Read a symlink.
  108. */
  109. static __be32
  110. nfsd3_proc_readlink(struct svc_rqst *rqstp)
  111. {
  112. struct nfsd3_readlinkargs *argp = rqstp->rq_argp;
  113. struct nfsd3_readlinkres *resp = rqstp->rq_resp;
  114. __be32 nfserr;
  115. dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
  116. /* Read the symlink. */
  117. fh_copy(&resp->fh, &argp->fh);
  118. resp->len = NFS3_MAXPATHLEN;
  119. nfserr = nfsd_readlink(rqstp, &resp->fh, argp->buffer, &resp->len);
  120. RETURN_STATUS(nfserr);
  121. }
  122. /*
  123. * Read a portion of a file.
  124. */
  125. static __be32
  126. nfsd3_proc_read(struct svc_rqst *rqstp)
  127. {
  128. struct nfsd3_readargs *argp = rqstp->rq_argp;
  129. struct nfsd3_readres *resp = rqstp->rq_resp;
  130. __be32 nfserr;
  131. u32 max_blocksize = svc_max_payload(rqstp);
  132. unsigned long cnt = min(argp->count, max_blocksize);
  133. dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n",
  134. SVCFH_fmt(&argp->fh),
  135. (unsigned long) argp->count,
  136. (unsigned long long) argp->offset);
  137. /* Obtain buffer pointer for payload.
  138. * 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof)
  139. * + 1 (xdr opaque byte count) = 26
  140. */
  141. resp->count = cnt;
  142. svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
  143. fh_copy(&resp->fh, &argp->fh);
  144. nfserr = nfsd_read(rqstp, &resp->fh,
  145. argp->offset,
  146. rqstp->rq_vec, argp->vlen,
  147. &resp->count);
  148. if (nfserr == 0) {
  149. struct inode *inode = d_inode(resp->fh.fh_dentry);
  150. resp->eof = nfsd_eof_on_read(cnt, resp->count, argp->offset,
  151. inode->i_size);
  152. }
  153. RETURN_STATUS(nfserr);
  154. }
  155. /*
  156. * Write data to a file
  157. */
  158. static __be32
  159. nfsd3_proc_write(struct svc_rqst *rqstp)
  160. {
  161. struct nfsd3_writeargs *argp = rqstp->rq_argp;
  162. struct nfsd3_writeres *resp = rqstp->rq_resp;
  163. __be32 nfserr;
  164. unsigned long cnt = argp->len;
  165. unsigned int nvecs;
  166. dprintk("nfsd: WRITE(3) %s %d bytes at %Lu%s\n",
  167. SVCFH_fmt(&argp->fh),
  168. argp->len,
  169. (unsigned long long) argp->offset,
  170. argp->stable? " stable" : "");
  171. fh_copy(&resp->fh, &argp->fh);
  172. resp->committed = argp->stable;
  173. nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages,
  174. &argp->first, cnt);
  175. if (!nvecs)
  176. RETURN_STATUS(nfserr_io);
  177. nfserr = nfsd_write(rqstp, &resp->fh, argp->offset,
  178. rqstp->rq_vec, nvecs, &cnt,
  179. resp->committed);
  180. resp->count = cnt;
  181. RETURN_STATUS(nfserr);
  182. }
  183. /*
  184. * With NFSv3, CREATE processing is a lot easier than with NFSv2.
  185. * At least in theory; we'll see how it fares in practice when the
  186. * first reports about SunOS compatibility problems start to pour in...
  187. */
  188. static __be32
  189. nfsd3_proc_create(struct svc_rqst *rqstp)
  190. {
  191. struct nfsd3_createargs *argp = rqstp->rq_argp;
  192. struct nfsd3_diropres *resp = rqstp->rq_resp;
  193. svc_fh *dirfhp, *newfhp = NULL;
  194. struct iattr *attr;
  195. __be32 nfserr;
  196. dprintk("nfsd: CREATE(3) %s %.*s\n",
  197. SVCFH_fmt(&argp->fh),
  198. argp->len,
  199. argp->name);
  200. dirfhp = fh_copy(&resp->dirfh, &argp->fh);
  201. newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
  202. attr = &argp->attrs;
  203. /* Unfudge the mode bits */
  204. attr->ia_mode &= ~S_IFMT;
  205. if (!(attr->ia_valid & ATTR_MODE)) {
  206. attr->ia_valid |= ATTR_MODE;
  207. attr->ia_mode = S_IFREG;
  208. } else {
  209. attr->ia_mode = (attr->ia_mode & ~S_IFMT) | S_IFREG;
  210. }
  211. /* Now create the file and set attributes */
  212. nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len,
  213. attr, newfhp,
  214. argp->createmode, (u32 *)argp->verf, NULL, NULL);
  215. RETURN_STATUS(nfserr);
  216. }
  217. /*
  218. * Make directory. This operation is not idempotent.
  219. */
  220. static __be32
  221. nfsd3_proc_mkdir(struct svc_rqst *rqstp)
  222. {
  223. struct nfsd3_createargs *argp = rqstp->rq_argp;
  224. struct nfsd3_diropres *resp = rqstp->rq_resp;
  225. __be32 nfserr;
  226. dprintk("nfsd: MKDIR(3) %s %.*s\n",
  227. SVCFH_fmt(&argp->fh),
  228. argp->len,
  229. argp->name);
  230. argp->attrs.ia_valid &= ~ATTR_SIZE;
  231. fh_copy(&resp->dirfh, &argp->fh);
  232. fh_init(&resp->fh, NFS3_FHSIZE);
  233. nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
  234. &argp->attrs, S_IFDIR, 0, &resp->fh);
  235. fh_unlock(&resp->dirfh);
  236. RETURN_STATUS(nfserr);
  237. }
  238. static __be32
  239. nfsd3_proc_symlink(struct svc_rqst *rqstp)
  240. {
  241. struct nfsd3_symlinkargs *argp = rqstp->rq_argp;
  242. struct nfsd3_diropres *resp = rqstp->rq_resp;
  243. __be32 nfserr;
  244. if (argp->tlen == 0)
  245. RETURN_STATUS(nfserr_inval);
  246. if (argp->tlen > NFS3_MAXPATHLEN)
  247. RETURN_STATUS(nfserr_nametoolong);
  248. argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first,
  249. page_address(rqstp->rq_arg.pages[0]),
  250. argp->tlen);
  251. if (IS_ERR(argp->tname))
  252. RETURN_STATUS(nfserrno(PTR_ERR(argp->tname)));
  253. dprintk("nfsd: SYMLINK(3) %s %.*s -> %.*s\n",
  254. SVCFH_fmt(&argp->ffh),
  255. argp->flen, argp->fname,
  256. argp->tlen, argp->tname);
  257. fh_copy(&resp->dirfh, &argp->ffh);
  258. fh_init(&resp->fh, NFS3_FHSIZE);
  259. nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,
  260. argp->tname, &resp->fh);
  261. kfree(argp->tname);
  262. RETURN_STATUS(nfserr);
  263. }
  264. /*
  265. * Make socket/fifo/device.
  266. */
  267. static __be32
  268. nfsd3_proc_mknod(struct svc_rqst *rqstp)
  269. {
  270. struct nfsd3_mknodargs *argp = rqstp->rq_argp;
  271. struct nfsd3_diropres *resp = rqstp->rq_resp;
  272. __be32 nfserr;
  273. int type;
  274. dev_t rdev = 0;
  275. dprintk("nfsd: MKNOD(3) %s %.*s\n",
  276. SVCFH_fmt(&argp->fh),
  277. argp->len,
  278. argp->name);
  279. fh_copy(&resp->dirfh, &argp->fh);
  280. fh_init(&resp->fh, NFS3_FHSIZE);
  281. if (argp->ftype == 0 || argp->ftype >= NF3BAD)
  282. RETURN_STATUS(nfserr_inval);
  283. if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
  284. rdev = MKDEV(argp->major, argp->minor);
  285. if (MAJOR(rdev) != argp->major ||
  286. MINOR(rdev) != argp->minor)
  287. RETURN_STATUS(nfserr_inval);
  288. } else
  289. if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO)
  290. RETURN_STATUS(nfserr_inval);
  291. type = nfs3_ftypes[argp->ftype];
  292. nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
  293. &argp->attrs, type, rdev, &resp->fh);
  294. fh_unlock(&resp->dirfh);
  295. RETURN_STATUS(nfserr);
  296. }
  297. /*
  298. * Remove file/fifo/socket etc.
  299. */
  300. static __be32
  301. nfsd3_proc_remove(struct svc_rqst *rqstp)
  302. {
  303. struct nfsd3_diropargs *argp = rqstp->rq_argp;
  304. struct nfsd3_attrstat *resp = rqstp->rq_resp;
  305. __be32 nfserr;
  306. dprintk("nfsd: REMOVE(3) %s %.*s\n",
  307. SVCFH_fmt(&argp->fh),
  308. argp->len,
  309. argp->name);
  310. /* Unlink. -S_IFDIR means file must not be a directory */
  311. fh_copy(&resp->fh, &argp->fh);
  312. nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len);
  313. fh_unlock(&resp->fh);
  314. RETURN_STATUS(nfserr);
  315. }
  316. /*
  317. * Remove a directory
  318. */
  319. static __be32
  320. nfsd3_proc_rmdir(struct svc_rqst *rqstp)
  321. {
  322. struct nfsd3_diropargs *argp = rqstp->rq_argp;
  323. struct nfsd3_attrstat *resp = rqstp->rq_resp;
  324. __be32 nfserr;
  325. dprintk("nfsd: RMDIR(3) %s %.*s\n",
  326. SVCFH_fmt(&argp->fh),
  327. argp->len,
  328. argp->name);
  329. fh_copy(&resp->fh, &argp->fh);
  330. nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len);
  331. fh_unlock(&resp->fh);
  332. RETURN_STATUS(nfserr);
  333. }
  334. static __be32
  335. nfsd3_proc_rename(struct svc_rqst *rqstp)
  336. {
  337. struct nfsd3_renameargs *argp = rqstp->rq_argp;
  338. struct nfsd3_renameres *resp = rqstp->rq_resp;
  339. __be32 nfserr;
  340. dprintk("nfsd: RENAME(3) %s %.*s ->\n",
  341. SVCFH_fmt(&argp->ffh),
  342. argp->flen,
  343. argp->fname);
  344. dprintk("nfsd: -> %s %.*s\n",
  345. SVCFH_fmt(&argp->tfh),
  346. argp->tlen,
  347. argp->tname);
  348. fh_copy(&resp->ffh, &argp->ffh);
  349. fh_copy(&resp->tfh, &argp->tfh);
  350. nfserr = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
  351. &resp->tfh, argp->tname, argp->tlen);
  352. RETURN_STATUS(nfserr);
  353. }
  354. static __be32
  355. nfsd3_proc_link(struct svc_rqst *rqstp)
  356. {
  357. struct nfsd3_linkargs *argp = rqstp->rq_argp;
  358. struct nfsd3_linkres *resp = rqstp->rq_resp;
  359. __be32 nfserr;
  360. dprintk("nfsd: LINK(3) %s ->\n",
  361. SVCFH_fmt(&argp->ffh));
  362. dprintk("nfsd: -> %s %.*s\n",
  363. SVCFH_fmt(&argp->tfh),
  364. argp->tlen,
  365. argp->tname);
  366. fh_copy(&resp->fh, &argp->ffh);
  367. fh_copy(&resp->tfh, &argp->tfh);
  368. nfserr = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
  369. &resp->fh);
  370. RETURN_STATUS(nfserr);
  371. }
  372. /*
  373. * Read a portion of a directory.
  374. */
  375. static __be32
  376. nfsd3_proc_readdir(struct svc_rqst *rqstp)
  377. {
  378. struct nfsd3_readdirargs *argp = rqstp->rq_argp;
  379. struct nfsd3_readdirres *resp = rqstp->rq_resp;
  380. __be32 nfserr;
  381. int count;
  382. dprintk("nfsd: READDIR(3) %s %d bytes at %d\n",
  383. SVCFH_fmt(&argp->fh),
  384. argp->count, (u32) argp->cookie);
  385. /* Make sure we've room for the NULL ptr & eof flag, and shrink to
  386. * client read size */
  387. count = (argp->count >> 2) - 2;
  388. /* Read directory and encode entries on the fly */
  389. fh_copy(&resp->fh, &argp->fh);
  390. resp->buflen = count;
  391. resp->common.err = nfs_ok;
  392. resp->buffer = argp->buffer;
  393. resp->rqstp = rqstp;
  394. nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t*) &argp->cookie,
  395. &resp->common, nfs3svc_encode_entry);
  396. memcpy(resp->verf, argp->verf, 8);
  397. resp->count = resp->buffer - argp->buffer;
  398. if (resp->offset) {
  399. loff_t offset = argp->cookie;
  400. if (unlikely(resp->offset1)) {
  401. /* we ended up with offset on a page boundary */
  402. *resp->offset = htonl(offset >> 32);
  403. *resp->offset1 = htonl(offset & 0xffffffff);
  404. resp->offset1 = NULL;
  405. } else {
  406. xdr_encode_hyper(resp->offset, offset);
  407. }
  408. resp->offset = NULL;
  409. }
  410. RETURN_STATUS(nfserr);
  411. }
  412. /*
  413. * Read a portion of a directory, including file handles and attrs.
  414. * For now, we choose to ignore the dircount parameter.
  415. */
  416. static __be32
  417. nfsd3_proc_readdirplus(struct svc_rqst *rqstp)
  418. {
  419. struct nfsd3_readdirargs *argp = rqstp->rq_argp;
  420. struct nfsd3_readdirres *resp = rqstp->rq_resp;
  421. __be32 nfserr;
  422. int count = 0;
  423. loff_t offset;
  424. struct page **p;
  425. caddr_t page_addr = NULL;
  426. dprintk("nfsd: READDIR+(3) %s %d bytes at %d\n",
  427. SVCFH_fmt(&argp->fh),
  428. argp->count, (u32) argp->cookie);
  429. /* Convert byte count to number of words (i.e. >> 2),
  430. * and reserve room for the NULL ptr & eof flag (-2 words) */
  431. resp->count = (argp->count >> 2) - 2;
  432. /* Read directory and encode entries on the fly */
  433. fh_copy(&resp->fh, &argp->fh);
  434. resp->common.err = nfs_ok;
  435. resp->buffer = argp->buffer;
  436. resp->buflen = resp->count;
  437. resp->rqstp = rqstp;
  438. offset = argp->cookie;
  439. nfserr = fh_verify(rqstp, &resp->fh, S_IFDIR, NFSD_MAY_NOP);
  440. if (nfserr)
  441. RETURN_STATUS(nfserr);
  442. if (resp->fh.fh_export->ex_flags & NFSEXP_NOREADDIRPLUS)
  443. RETURN_STATUS(nfserr_notsupp);
  444. nfserr = nfsd_readdir(rqstp, &resp->fh,
  445. &offset,
  446. &resp->common,
  447. nfs3svc_encode_entry_plus);
  448. memcpy(resp->verf, argp->verf, 8);
  449. for (p = rqstp->rq_respages + 1; p < rqstp->rq_next_page; p++) {
  450. page_addr = page_address(*p);
  451. if (((caddr_t)resp->buffer >= page_addr) &&
  452. ((caddr_t)resp->buffer < page_addr + PAGE_SIZE)) {
  453. count += (caddr_t)resp->buffer - page_addr;
  454. break;
  455. }
  456. count += PAGE_SIZE;
  457. }
  458. resp->count = count >> 2;
  459. if (resp->offset) {
  460. if (unlikely(resp->offset1)) {
  461. /* we ended up with offset on a page boundary */
  462. *resp->offset = htonl(offset >> 32);
  463. *resp->offset1 = htonl(offset & 0xffffffff);
  464. resp->offset1 = NULL;
  465. } else {
  466. xdr_encode_hyper(resp->offset, offset);
  467. }
  468. resp->offset = NULL;
  469. }
  470. RETURN_STATUS(nfserr);
  471. }
  472. /*
  473. * Get file system stats
  474. */
  475. static __be32
  476. nfsd3_proc_fsstat(struct svc_rqst *rqstp)
  477. {
  478. struct nfsd_fhandle *argp = rqstp->rq_argp;
  479. struct nfsd3_fsstatres *resp = rqstp->rq_resp;
  480. __be32 nfserr;
  481. dprintk("nfsd: FSSTAT(3) %s\n",
  482. SVCFH_fmt(&argp->fh));
  483. nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);
  484. fh_put(&argp->fh);
  485. RETURN_STATUS(nfserr);
  486. }
  487. /*
  488. * Get file system info
  489. */
  490. static __be32
  491. nfsd3_proc_fsinfo(struct svc_rqst *rqstp)
  492. {
  493. struct nfsd_fhandle *argp = rqstp->rq_argp;
  494. struct nfsd3_fsinfores *resp = rqstp->rq_resp;
  495. __be32 nfserr;
  496. u32 max_blocksize = svc_max_payload(rqstp);
  497. dprintk("nfsd: FSINFO(3) %s\n",
  498. SVCFH_fmt(&argp->fh));
  499. resp->f_rtmax = max_blocksize;
  500. resp->f_rtpref = max_blocksize;
  501. resp->f_rtmult = PAGE_SIZE;
  502. resp->f_wtmax = max_blocksize;
  503. resp->f_wtpref = max_blocksize;
  504. resp->f_wtmult = PAGE_SIZE;
  505. resp->f_dtpref = PAGE_SIZE;
  506. resp->f_maxfilesize = ~(u32) 0;
  507. resp->f_properties = NFS3_FSF_DEFAULT;
  508. nfserr = fh_verify(rqstp, &argp->fh, 0,
  509. NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
  510. /* Check special features of the file system. May request
  511. * different read/write sizes for file systems known to have
  512. * problems with large blocks */
  513. if (nfserr == 0) {
  514. struct super_block *sb = argp->fh.fh_dentry->d_sb;
  515. /* Note that we don't care for remote fs's here */
  516. if (sb->s_magic == MSDOS_SUPER_MAGIC) {
  517. resp->f_properties = NFS3_FSF_BILLYBOY;
  518. }
  519. resp->f_maxfilesize = sb->s_maxbytes;
  520. }
  521. fh_put(&argp->fh);
  522. RETURN_STATUS(nfserr);
  523. }
  524. /*
  525. * Get pathconf info for the specified file
  526. */
  527. static __be32
  528. nfsd3_proc_pathconf(struct svc_rqst *rqstp)
  529. {
  530. struct nfsd_fhandle *argp = rqstp->rq_argp;
  531. struct nfsd3_pathconfres *resp = rqstp->rq_resp;
  532. __be32 nfserr;
  533. dprintk("nfsd: PATHCONF(3) %s\n",
  534. SVCFH_fmt(&argp->fh));
  535. /* Set default pathconf */
  536. resp->p_link_max = 255; /* at least */
  537. resp->p_name_max = 255; /* at least */
  538. resp->p_no_trunc = 0;
  539. resp->p_chown_restricted = 1;
  540. resp->p_case_insensitive = 0;
  541. resp->p_case_preserving = 1;
  542. nfserr = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
  543. if (nfserr == 0) {
  544. struct super_block *sb = argp->fh.fh_dentry->d_sb;
  545. /* Note that we don't care for remote fs's here */
  546. switch (sb->s_magic) {
  547. case EXT2_SUPER_MAGIC:
  548. resp->p_link_max = EXT2_LINK_MAX;
  549. resp->p_name_max = EXT2_NAME_LEN;
  550. break;
  551. case MSDOS_SUPER_MAGIC:
  552. resp->p_case_insensitive = 1;
  553. resp->p_case_preserving = 0;
  554. break;
  555. }
  556. }
  557. fh_put(&argp->fh);
  558. RETURN_STATUS(nfserr);
  559. }
  560. /*
  561. * Commit a file (range) to stable storage.
  562. */
  563. static __be32
  564. nfsd3_proc_commit(struct svc_rqst *rqstp)
  565. {
  566. struct nfsd3_commitargs *argp = rqstp->rq_argp;
  567. struct nfsd3_commitres *resp = rqstp->rq_resp;
  568. __be32 nfserr;
  569. dprintk("nfsd: COMMIT(3) %s %u@%Lu\n",
  570. SVCFH_fmt(&argp->fh),
  571. argp->count,
  572. (unsigned long long) argp->offset);
  573. if (argp->offset > NFS_OFFSET_MAX)
  574. RETURN_STATUS(nfserr_inval);
  575. fh_copy(&resp->fh, &argp->fh);
  576. nfserr = nfsd_commit(rqstp, &resp->fh, argp->offset, argp->count);
  577. RETURN_STATUS(nfserr);
  578. }
  579. /*
  580. * NFSv3 Server procedures.
  581. * Only the results of non-idempotent operations are cached.
  582. */
  583. #define nfs3svc_decode_fhandleargs nfs3svc_decode_fhandle
  584. #define nfs3svc_encode_attrstatres nfs3svc_encode_attrstat
  585. #define nfs3svc_encode_wccstatres nfs3svc_encode_wccstat
  586. #define nfsd3_mkdirargs nfsd3_createargs
  587. #define nfsd3_readdirplusargs nfsd3_readdirargs
  588. #define nfsd3_fhandleargs nfsd_fhandle
  589. #define nfsd3_fhandleres nfsd3_attrstat
  590. #define nfsd3_attrstatres nfsd3_attrstat
  591. #define nfsd3_wccstatres nfsd3_attrstat
  592. #define nfsd3_createres nfsd3_diropres
  593. #define nfsd3_voidres nfsd3_voidargs
  594. struct nfsd3_voidargs { int dummy; };
  595. #define ST 1 /* status*/
  596. #define FH 17 /* filehandle with length */
  597. #define AT 21 /* attributes */
  598. #define pAT (1+AT) /* post attributes - conditional */
  599. #define WC (7+pAT) /* WCC attributes */
  600. static const struct svc_procedure nfsd_procedures3[22] = {
  601. [NFS3PROC_NULL] = {
  602. .pc_func = nfsd3_proc_null,
  603. .pc_encode = nfs3svc_encode_voidres,
  604. .pc_argsize = sizeof(struct nfsd3_voidargs),
  605. .pc_ressize = sizeof(struct nfsd3_voidres),
  606. .pc_cachetype = RC_NOCACHE,
  607. .pc_xdrressize = ST,
  608. },
  609. [NFS3PROC_GETATTR] = {
  610. .pc_func = nfsd3_proc_getattr,
  611. .pc_decode = nfs3svc_decode_fhandleargs,
  612. .pc_encode = nfs3svc_encode_attrstatres,
  613. .pc_release = nfs3svc_release_fhandle,
  614. .pc_argsize = sizeof(struct nfsd3_fhandleargs),
  615. .pc_ressize = sizeof(struct nfsd3_attrstatres),
  616. .pc_cachetype = RC_NOCACHE,
  617. .pc_xdrressize = ST+AT,
  618. },
  619. [NFS3PROC_SETATTR] = {
  620. .pc_func = nfsd3_proc_setattr,
  621. .pc_decode = nfs3svc_decode_sattrargs,
  622. .pc_encode = nfs3svc_encode_wccstatres,
  623. .pc_release = nfs3svc_release_fhandle,
  624. .pc_argsize = sizeof(struct nfsd3_sattrargs),
  625. .pc_ressize = sizeof(struct nfsd3_wccstatres),
  626. .pc_cachetype = RC_REPLBUFF,
  627. .pc_xdrressize = ST+WC,
  628. },
  629. [NFS3PROC_LOOKUP] = {
  630. .pc_func = nfsd3_proc_lookup,
  631. .pc_decode = nfs3svc_decode_diropargs,
  632. .pc_encode = nfs3svc_encode_diropres,
  633. .pc_release = nfs3svc_release_fhandle2,
  634. .pc_argsize = sizeof(struct nfsd3_diropargs),
  635. .pc_ressize = sizeof(struct nfsd3_diropres),
  636. .pc_cachetype = RC_NOCACHE,
  637. .pc_xdrressize = ST+FH+pAT+pAT,
  638. },
  639. [NFS3PROC_ACCESS] = {
  640. .pc_func = nfsd3_proc_access,
  641. .pc_decode = nfs3svc_decode_accessargs,
  642. .pc_encode = nfs3svc_encode_accessres,
  643. .pc_release = nfs3svc_release_fhandle,
  644. .pc_argsize = sizeof(struct nfsd3_accessargs),
  645. .pc_ressize = sizeof(struct nfsd3_accessres),
  646. .pc_cachetype = RC_NOCACHE,
  647. .pc_xdrressize = ST+pAT+1,
  648. },
  649. [NFS3PROC_READLINK] = {
  650. .pc_func = nfsd3_proc_readlink,
  651. .pc_decode = nfs3svc_decode_readlinkargs,
  652. .pc_encode = nfs3svc_encode_readlinkres,
  653. .pc_release = nfs3svc_release_fhandle,
  654. .pc_argsize = sizeof(struct nfsd3_readlinkargs),
  655. .pc_ressize = sizeof(struct nfsd3_readlinkres),
  656. .pc_cachetype = RC_NOCACHE,
  657. .pc_xdrressize = ST+pAT+1+NFS3_MAXPATHLEN/4,
  658. },
  659. [NFS3PROC_READ] = {
  660. .pc_func = nfsd3_proc_read,
  661. .pc_decode = nfs3svc_decode_readargs,
  662. .pc_encode = nfs3svc_encode_readres,
  663. .pc_release = nfs3svc_release_fhandle,
  664. .pc_argsize = sizeof(struct nfsd3_readargs),
  665. .pc_ressize = sizeof(struct nfsd3_readres),
  666. .pc_cachetype = RC_NOCACHE,
  667. .pc_xdrressize = ST+pAT+4+NFSSVC_MAXBLKSIZE/4,
  668. },
  669. [NFS3PROC_WRITE] = {
  670. .pc_func = nfsd3_proc_write,
  671. .pc_decode = nfs3svc_decode_writeargs,
  672. .pc_encode = nfs3svc_encode_writeres,
  673. .pc_release = nfs3svc_release_fhandle,
  674. .pc_argsize = sizeof(struct nfsd3_writeargs),
  675. .pc_ressize = sizeof(struct nfsd3_writeres),
  676. .pc_cachetype = RC_REPLBUFF,
  677. .pc_xdrressize = ST+WC+4,
  678. },
  679. [NFS3PROC_CREATE] = {
  680. .pc_func = nfsd3_proc_create,
  681. .pc_decode = nfs3svc_decode_createargs,
  682. .pc_encode = nfs3svc_encode_createres,
  683. .pc_release = nfs3svc_release_fhandle2,
  684. .pc_argsize = sizeof(struct nfsd3_createargs),
  685. .pc_ressize = sizeof(struct nfsd3_createres),
  686. .pc_cachetype = RC_REPLBUFF,
  687. .pc_xdrressize = ST+(1+FH+pAT)+WC,
  688. },
  689. [NFS3PROC_MKDIR] = {
  690. .pc_func = nfsd3_proc_mkdir,
  691. .pc_decode = nfs3svc_decode_mkdirargs,
  692. .pc_encode = nfs3svc_encode_createres,
  693. .pc_release = nfs3svc_release_fhandle2,
  694. .pc_argsize = sizeof(struct nfsd3_mkdirargs),
  695. .pc_ressize = sizeof(struct nfsd3_createres),
  696. .pc_cachetype = RC_REPLBUFF,
  697. .pc_xdrressize = ST+(1+FH+pAT)+WC,
  698. },
  699. [NFS3PROC_SYMLINK] = {
  700. .pc_func = nfsd3_proc_symlink,
  701. .pc_decode = nfs3svc_decode_symlinkargs,
  702. .pc_encode = nfs3svc_encode_createres,
  703. .pc_release = nfs3svc_release_fhandle2,
  704. .pc_argsize = sizeof(struct nfsd3_symlinkargs),
  705. .pc_ressize = sizeof(struct nfsd3_createres),
  706. .pc_cachetype = RC_REPLBUFF,
  707. .pc_xdrressize = ST+(1+FH+pAT)+WC,
  708. },
  709. [NFS3PROC_MKNOD] = {
  710. .pc_func = nfsd3_proc_mknod,
  711. .pc_decode = nfs3svc_decode_mknodargs,
  712. .pc_encode = nfs3svc_encode_createres,
  713. .pc_release = nfs3svc_release_fhandle2,
  714. .pc_argsize = sizeof(struct nfsd3_mknodargs),
  715. .pc_ressize = sizeof(struct nfsd3_createres),
  716. .pc_cachetype = RC_REPLBUFF,
  717. .pc_xdrressize = ST+(1+FH+pAT)+WC,
  718. },
  719. [NFS3PROC_REMOVE] = {
  720. .pc_func = nfsd3_proc_remove,
  721. .pc_decode = nfs3svc_decode_diropargs,
  722. .pc_encode = nfs3svc_encode_wccstatres,
  723. .pc_release = nfs3svc_release_fhandle,
  724. .pc_argsize = sizeof(struct nfsd3_diropargs),
  725. .pc_ressize = sizeof(struct nfsd3_wccstatres),
  726. .pc_cachetype = RC_REPLBUFF,
  727. .pc_xdrressize = ST+WC,
  728. },
  729. [NFS3PROC_RMDIR] = {
  730. .pc_func = nfsd3_proc_rmdir,
  731. .pc_decode = nfs3svc_decode_diropargs,
  732. .pc_encode = nfs3svc_encode_wccstatres,
  733. .pc_release = nfs3svc_release_fhandle,
  734. .pc_argsize = sizeof(struct nfsd3_diropargs),
  735. .pc_ressize = sizeof(struct nfsd3_wccstatres),
  736. .pc_cachetype = RC_REPLBUFF,
  737. .pc_xdrressize = ST+WC,
  738. },
  739. [NFS3PROC_RENAME] = {
  740. .pc_func = nfsd3_proc_rename,
  741. .pc_decode = nfs3svc_decode_renameargs,
  742. .pc_encode = nfs3svc_encode_renameres,
  743. .pc_release = nfs3svc_release_fhandle2,
  744. .pc_argsize = sizeof(struct nfsd3_renameargs),
  745. .pc_ressize = sizeof(struct nfsd3_renameres),
  746. .pc_cachetype = RC_REPLBUFF,
  747. .pc_xdrressize = ST+WC+WC,
  748. },
  749. [NFS3PROC_LINK] = {
  750. .pc_func = nfsd3_proc_link,
  751. .pc_decode = nfs3svc_decode_linkargs,
  752. .pc_encode = nfs3svc_encode_linkres,
  753. .pc_release = nfs3svc_release_fhandle2,
  754. .pc_argsize = sizeof(struct nfsd3_linkargs),
  755. .pc_ressize = sizeof(struct nfsd3_linkres),
  756. .pc_cachetype = RC_REPLBUFF,
  757. .pc_xdrressize = ST+pAT+WC,
  758. },
  759. [NFS3PROC_READDIR] = {
  760. .pc_func = nfsd3_proc_readdir,
  761. .pc_decode = nfs3svc_decode_readdirargs,
  762. .pc_encode = nfs3svc_encode_readdirres,
  763. .pc_release = nfs3svc_release_fhandle,
  764. .pc_argsize = sizeof(struct nfsd3_readdirargs),
  765. .pc_ressize = sizeof(struct nfsd3_readdirres),
  766. .pc_cachetype = RC_NOCACHE,
  767. },
  768. [NFS3PROC_READDIRPLUS] = {
  769. .pc_func = nfsd3_proc_readdirplus,
  770. .pc_decode = nfs3svc_decode_readdirplusargs,
  771. .pc_encode = nfs3svc_encode_readdirres,
  772. .pc_release = nfs3svc_release_fhandle,
  773. .pc_argsize = sizeof(struct nfsd3_readdirplusargs),
  774. .pc_ressize = sizeof(struct nfsd3_readdirres),
  775. .pc_cachetype = RC_NOCACHE,
  776. },
  777. [NFS3PROC_FSSTAT] = {
  778. .pc_func = nfsd3_proc_fsstat,
  779. .pc_decode = nfs3svc_decode_fhandleargs,
  780. .pc_encode = nfs3svc_encode_fsstatres,
  781. .pc_argsize = sizeof(struct nfsd3_fhandleargs),
  782. .pc_ressize = sizeof(struct nfsd3_fsstatres),
  783. .pc_cachetype = RC_NOCACHE,
  784. .pc_xdrressize = ST+pAT+2*6+1,
  785. },
  786. [NFS3PROC_FSINFO] = {
  787. .pc_func = nfsd3_proc_fsinfo,
  788. .pc_decode = nfs3svc_decode_fhandleargs,
  789. .pc_encode = nfs3svc_encode_fsinfores,
  790. .pc_argsize = sizeof(struct nfsd3_fhandleargs),
  791. .pc_ressize = sizeof(struct nfsd3_fsinfores),
  792. .pc_cachetype = RC_NOCACHE,
  793. .pc_xdrressize = ST+pAT+12,
  794. },
  795. [NFS3PROC_PATHCONF] = {
  796. .pc_func = nfsd3_proc_pathconf,
  797. .pc_decode = nfs3svc_decode_fhandleargs,
  798. .pc_encode = nfs3svc_encode_pathconfres,
  799. .pc_argsize = sizeof(struct nfsd3_fhandleargs),
  800. .pc_ressize = sizeof(struct nfsd3_pathconfres),
  801. .pc_cachetype = RC_NOCACHE,
  802. .pc_xdrressize = ST+pAT+6,
  803. },
  804. [NFS3PROC_COMMIT] = {
  805. .pc_func = nfsd3_proc_commit,
  806. .pc_decode = nfs3svc_decode_commitargs,
  807. .pc_encode = nfs3svc_encode_commitres,
  808. .pc_release = nfs3svc_release_fhandle,
  809. .pc_argsize = sizeof(struct nfsd3_commitargs),
  810. .pc_ressize = sizeof(struct nfsd3_commitres),
  811. .pc_cachetype = RC_NOCACHE,
  812. .pc_xdrressize = ST+WC+2,
  813. },
  814. };
  815. static unsigned int nfsd_count3[ARRAY_SIZE(nfsd_procedures3)];
  816. const struct svc_version nfsd_version3 = {
  817. .vs_vers = 3,
  818. .vs_nproc = 22,
  819. .vs_proc = nfsd_procedures3,
  820. .vs_dispatch = nfsd_dispatch,
  821. .vs_count = nfsd_count3,
  822. .vs_xdrsize = NFS3_SVC_XDRSIZE,
  823. };