nfs3proc.c 25 KB

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