nfs3proc.c 24 KB

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