nfs3proc.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. /*
  2. * linux/fs/nfsd/nfs3proc.c
  3. *
  4. * Process version 3 NFS requests.
  5. *
  6. * Copyright (C) 1996, 1997, 1998 Olaf Kirch <okir@monad.swb.de>
  7. */
  8. #include <linux/linkage.h>
  9. #include <linux/time.h>
  10. #include <linux/errno.h>
  11. #include <linux/fs.h>
  12. #include <linux/ext2_fs.h>
  13. #include <linux/stat.h>
  14. #include <linux/fcntl.h>
  15. #include <linux/net.h>
  16. #include <linux/in.h>
  17. #include <linux/unistd.h>
  18. #include <linux/slab.h>
  19. #include <linux/major.h>
  20. #include <linux/sunrpc/svc.h>
  21. #include <linux/nfsd/nfsd.h>
  22. #include <linux/nfsd/cache.h>
  23. #include <linux/nfsd/xdr3.h>
  24. #include <linux/nfs3.h>
  25. #define NFSDDBG_FACILITY NFSDDBG_PROC
  26. #define RETURN_STATUS(st) { resp->status = (st); return (st); }
  27. static int nfs3_ftypes[] = {
  28. 0, /* NF3NON */
  29. S_IFREG, /* NF3REG */
  30. S_IFDIR, /* NF3DIR */
  31. S_IFBLK, /* NF3BLK */
  32. S_IFCHR, /* NF3CHR */
  33. S_IFLNK, /* NF3LNK */
  34. S_IFSOCK, /* NF3SOCK */
  35. S_IFIFO, /* NF3FIFO */
  36. };
  37. /*
  38. * NULL call.
  39. */
  40. static __be32
  41. nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
  42. {
  43. return nfs_ok;
  44. }
  45. /*
  46. * Get a file's attributes
  47. */
  48. static __be32
  49. nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
  50. struct nfsd3_attrstat *resp)
  51. {
  52. int err;
  53. __be32 nfserr;
  54. dprintk("nfsd: GETATTR(3) %s\n",
  55. SVCFH_fmt(&argp->fh));
  56. fh_copy(&resp->fh, &argp->fh);
  57. nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
  58. if (nfserr)
  59. RETURN_STATUS(nfserr);
  60. err = vfs_getattr(resp->fh.fh_export->ex_mnt,
  61. resp->fh.fh_dentry, &resp->stat);
  62. nfserr = nfserrno(err);
  63. RETURN_STATUS(nfserr);
  64. }
  65. /*
  66. * Set a file's attributes
  67. */
  68. static __be32
  69. nfsd3_proc_setattr(struct svc_rqst *rqstp, struct nfsd3_sattrargs *argp,
  70. struct nfsd3_attrstat *resp)
  71. {
  72. __be32 nfserr;
  73. dprintk("nfsd: SETATTR(3) %s\n",
  74. SVCFH_fmt(&argp->fh));
  75. fh_copy(&resp->fh, &argp->fh);
  76. nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,
  77. argp->check_guard, argp->guardtime);
  78. RETURN_STATUS(nfserr);
  79. }
  80. /*
  81. * Look up a path name component
  82. */
  83. static __be32
  84. nfsd3_proc_lookup(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
  85. struct nfsd3_diropres *resp)
  86. {
  87. __be32 nfserr;
  88. dprintk("nfsd: LOOKUP(3) %s %.*s\n",
  89. SVCFH_fmt(&argp->fh),
  90. argp->len,
  91. argp->name);
  92. fh_copy(&resp->dirfh, &argp->fh);
  93. fh_init(&resp->fh, NFS3_FHSIZE);
  94. nfserr = nfsd_lookup(rqstp, &resp->dirfh,
  95. argp->name,
  96. argp->len,
  97. &resp->fh);
  98. RETURN_STATUS(nfserr);
  99. }
  100. /*
  101. * Check file access
  102. */
  103. static __be32
  104. nfsd3_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp,
  105. struct nfsd3_accessres *resp)
  106. {
  107. __be32 nfserr;
  108. dprintk("nfsd: ACCESS(3) %s 0x%x\n",
  109. SVCFH_fmt(&argp->fh),
  110. argp->access);
  111. fh_copy(&resp->fh, &argp->fh);
  112. resp->access = argp->access;
  113. nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
  114. RETURN_STATUS(nfserr);
  115. }
  116. /*
  117. * Read a symlink.
  118. */
  119. static __be32
  120. nfsd3_proc_readlink(struct svc_rqst *rqstp, struct nfsd3_readlinkargs *argp,
  121. struct nfsd3_readlinkres *resp)
  122. {
  123. __be32 nfserr;
  124. dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
  125. /* Read the symlink. */
  126. fh_copy(&resp->fh, &argp->fh);
  127. resp->len = NFS3_MAXPATHLEN;
  128. nfserr = nfsd_readlink(rqstp, &resp->fh, argp->buffer, &resp->len);
  129. RETURN_STATUS(nfserr);
  130. }
  131. /*
  132. * Read a portion of a file.
  133. */
  134. static __be32
  135. nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
  136. struct nfsd3_readres *resp)
  137. {
  138. __be32 nfserr;
  139. u32 max_blocksize = svc_max_payload(rqstp);
  140. dprintk("nfsd: READ(3) %s %lu bytes at %lu\n",
  141. SVCFH_fmt(&argp->fh),
  142. (unsigned long) argp->count,
  143. (unsigned long) argp->offset);
  144. /* Obtain buffer pointer for payload.
  145. * 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof)
  146. * + 1 (xdr opaque byte count) = 26
  147. */
  148. resp->count = argp->count;
  149. if (max_blocksize < resp->count)
  150. resp->count = max_blocksize;
  151. svc_reserve(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
  152. fh_copy(&resp->fh, &argp->fh);
  153. nfserr = nfsd_read(rqstp, &resp->fh, NULL,
  154. argp->offset,
  155. rqstp->rq_vec, argp->vlen,
  156. &resp->count);
  157. if (nfserr == 0) {
  158. struct inode *inode = resp->fh.fh_dentry->d_inode;
  159. resp->eof = (argp->offset + resp->count) >= inode->i_size;
  160. }
  161. RETURN_STATUS(nfserr);
  162. }
  163. /*
  164. * Write data to a file
  165. */
  166. static __be32
  167. nfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp,
  168. struct nfsd3_writeres *resp)
  169. {
  170. __be32 nfserr;
  171. dprintk("nfsd: WRITE(3) %s %d bytes at %ld%s\n",
  172. SVCFH_fmt(&argp->fh),
  173. argp->len,
  174. (unsigned long) argp->offset,
  175. argp->stable? " stable" : "");
  176. fh_copy(&resp->fh, &argp->fh);
  177. resp->committed = argp->stable;
  178. nfserr = nfsd_write(rqstp, &resp->fh, NULL,
  179. argp->offset,
  180. rqstp->rq_vec, argp->vlen,
  181. argp->len,
  182. &resp->committed);
  183. resp->count = argp->count;
  184. RETURN_STATUS(nfserr);
  185. }
  186. /*
  187. * With NFSv3, CREATE processing is a lot easier than with NFSv2.
  188. * At least in theory; we'll see how it fares in practice when the
  189. * first reports about SunOS compatibility problems start to pour in...
  190. */
  191. static __be32
  192. nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
  193. struct nfsd3_diropres *resp)
  194. {
  195. svc_fh *dirfhp, *newfhp = NULL;
  196. struct iattr *attr;
  197. __be32 nfserr;
  198. dprintk("nfsd: CREATE(3) %s %.*s\n",
  199. SVCFH_fmt(&argp->fh),
  200. argp->len,
  201. argp->name);
  202. dirfhp = fh_copy(&resp->dirfh, &argp->fh);
  203. newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
  204. attr = &argp->attrs;
  205. /* Get the directory inode */
  206. nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_CREATE);
  207. if (nfserr)
  208. RETURN_STATUS(nfserr);
  209. /* Unfudge the mode bits */
  210. attr->ia_mode &= ~S_IFMT;
  211. if (!(attr->ia_valid & ATTR_MODE)) {
  212. attr->ia_valid |= ATTR_MODE;
  213. attr->ia_mode = S_IFREG;
  214. } else {
  215. attr->ia_mode = (attr->ia_mode & ~S_IFMT) | S_IFREG;
  216. }
  217. /* Now create the file and set attributes */
  218. nfserr = nfsd_create_v3(rqstp, dirfhp, argp->name, argp->len,
  219. attr, newfhp,
  220. argp->createmode, argp->verf, NULL, NULL);
  221. RETURN_STATUS(nfserr);
  222. }
  223. /*
  224. * Make directory. This operation is not idempotent.
  225. */
  226. static __be32
  227. nfsd3_proc_mkdir(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
  228. struct nfsd3_diropres *resp)
  229. {
  230. __be32 nfserr;
  231. dprintk("nfsd: MKDIR(3) %s %.*s\n",
  232. SVCFH_fmt(&argp->fh),
  233. argp->len,
  234. argp->name);
  235. argp->attrs.ia_valid &= ~ATTR_SIZE;
  236. fh_copy(&resp->dirfh, &argp->fh);
  237. fh_init(&resp->fh, NFS3_FHSIZE);
  238. nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
  239. &argp->attrs, S_IFDIR, 0, &resp->fh);
  240. RETURN_STATUS(nfserr);
  241. }
  242. static __be32
  243. nfsd3_proc_symlink(struct svc_rqst *rqstp, struct nfsd3_symlinkargs *argp,
  244. struct nfsd3_diropres *resp)
  245. {
  246. __be32 nfserr;
  247. dprintk("nfsd: SYMLINK(3) %s %.*s -> %.*s\n",
  248. SVCFH_fmt(&argp->ffh),
  249. argp->flen, argp->fname,
  250. argp->tlen, argp->tname);
  251. fh_copy(&resp->dirfh, &argp->ffh);
  252. fh_init(&resp->fh, NFS3_FHSIZE);
  253. nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,
  254. argp->tname, argp->tlen,
  255. &resp->fh, &argp->attrs);
  256. RETURN_STATUS(nfserr);
  257. }
  258. /*
  259. * Make socket/fifo/device.
  260. */
  261. static __be32
  262. nfsd3_proc_mknod(struct svc_rqst *rqstp, struct nfsd3_mknodargs *argp,
  263. struct nfsd3_diropres *resp)
  264. {
  265. __be32 nfserr;
  266. int type;
  267. dev_t rdev = 0;
  268. dprintk("nfsd: MKNOD(3) %s %.*s\n",
  269. SVCFH_fmt(&argp->fh),
  270. argp->len,
  271. argp->name);
  272. fh_copy(&resp->dirfh, &argp->fh);
  273. fh_init(&resp->fh, NFS3_FHSIZE);
  274. if (argp->ftype == 0 || argp->ftype >= NF3BAD)
  275. RETURN_STATUS(nfserr_inval);
  276. if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
  277. rdev = MKDEV(argp->major, argp->minor);
  278. if (MAJOR(rdev) != argp->major ||
  279. MINOR(rdev) != argp->minor)
  280. RETURN_STATUS(nfserr_inval);
  281. } else
  282. if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO)
  283. RETURN_STATUS(nfserr_inval);
  284. type = nfs3_ftypes[argp->ftype];
  285. nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
  286. &argp->attrs, type, rdev, &resp->fh);
  287. RETURN_STATUS(nfserr);
  288. }
  289. /*
  290. * Remove file/fifo/socket etc.
  291. */
  292. static __be32
  293. nfsd3_proc_remove(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
  294. struct nfsd3_attrstat *resp)
  295. {
  296. __be32 nfserr;
  297. dprintk("nfsd: REMOVE(3) %s %.*s\n",
  298. SVCFH_fmt(&argp->fh),
  299. argp->len,
  300. argp->name);
  301. /* Unlink. -S_IFDIR means file must not be a directory */
  302. fh_copy(&resp->fh, &argp->fh);
  303. nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len);
  304. RETURN_STATUS(nfserr);
  305. }
  306. /*
  307. * Remove a directory
  308. */
  309. static __be32
  310. nfsd3_proc_rmdir(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
  311. struct nfsd3_attrstat *resp)
  312. {
  313. __be32 nfserr;
  314. dprintk("nfsd: RMDIR(3) %s %.*s\n",
  315. SVCFH_fmt(&argp->fh),
  316. argp->len,
  317. argp->name);
  318. fh_copy(&resp->fh, &argp->fh);
  319. nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len);
  320. RETURN_STATUS(nfserr);
  321. }
  322. static __be32
  323. nfsd3_proc_rename(struct svc_rqst *rqstp, struct nfsd3_renameargs *argp,
  324. struct nfsd3_renameres *resp)
  325. {
  326. __be32 nfserr;
  327. dprintk("nfsd: RENAME(3) %s %.*s ->\n",
  328. SVCFH_fmt(&argp->ffh),
  329. argp->flen,
  330. argp->fname);
  331. dprintk("nfsd: -> %s %.*s\n",
  332. SVCFH_fmt(&argp->tfh),
  333. argp->tlen,
  334. argp->tname);
  335. fh_copy(&resp->ffh, &argp->ffh);
  336. fh_copy(&resp->tfh, &argp->tfh);
  337. nfserr = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
  338. &resp->tfh, argp->tname, argp->tlen);
  339. RETURN_STATUS(nfserr);
  340. }
  341. static __be32
  342. nfsd3_proc_link(struct svc_rqst *rqstp, struct nfsd3_linkargs *argp,
  343. struct nfsd3_linkres *resp)
  344. {
  345. __be32 nfserr;
  346. dprintk("nfsd: LINK(3) %s ->\n",
  347. SVCFH_fmt(&argp->ffh));
  348. dprintk("nfsd: -> %s %.*s\n",
  349. SVCFH_fmt(&argp->tfh),
  350. argp->tlen,
  351. argp->tname);
  352. fh_copy(&resp->fh, &argp->ffh);
  353. fh_copy(&resp->tfh, &argp->tfh);
  354. nfserr = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
  355. &resp->fh);
  356. RETURN_STATUS(nfserr);
  357. }
  358. /*
  359. * Read a portion of a directory.
  360. */
  361. static __be32
  362. nfsd3_proc_readdir(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
  363. struct nfsd3_readdirres *resp)
  364. {
  365. __be32 nfserr;
  366. int count;
  367. dprintk("nfsd: READDIR(3) %s %d bytes at %d\n",
  368. SVCFH_fmt(&argp->fh),
  369. argp->count, (u32) argp->cookie);
  370. /* Make sure we've room for the NULL ptr & eof flag, and shrink to
  371. * client read size */
  372. count = (argp->count >> 2) - 2;
  373. /* Read directory and encode entries on the fly */
  374. fh_copy(&resp->fh, &argp->fh);
  375. resp->buflen = count;
  376. resp->common.err = nfs_ok;
  377. resp->buffer = argp->buffer;
  378. resp->rqstp = rqstp;
  379. nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t*) &argp->cookie,
  380. &resp->common, nfs3svc_encode_entry);
  381. memcpy(resp->verf, argp->verf, 8);
  382. resp->count = resp->buffer - argp->buffer;
  383. if (resp->offset)
  384. xdr_encode_hyper(resp->offset, argp->cookie);
  385. RETURN_STATUS(nfserr);
  386. }
  387. /*
  388. * Read a portion of a directory, including file handles and attrs.
  389. * For now, we choose to ignore the dircount parameter.
  390. */
  391. static __be32
  392. nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
  393. struct nfsd3_readdirres *resp)
  394. {
  395. __be32 nfserr;
  396. int count = 0;
  397. loff_t offset;
  398. int i;
  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 = nfsd_readdir(rqstp, &resp->fh,
  414. &offset,
  415. &resp->common,
  416. nfs3svc_encode_entry_plus);
  417. memcpy(resp->verf, argp->verf, 8);
  418. for (i=1; i<rqstp->rq_resused ; i++) {
  419. page_addr = page_address(rqstp->rq_respages[i]);
  420. if (((caddr_t)resp->buffer >= page_addr) &&
  421. ((caddr_t)resp->buffer < page_addr + PAGE_SIZE)) {
  422. count += (caddr_t)resp->buffer - page_addr;
  423. break;
  424. }
  425. count += PAGE_SIZE;
  426. }
  427. resp->count = count >> 2;
  428. if (resp->offset) {
  429. if (unlikely(resp->offset1)) {
  430. /* we ended up with offset on a page boundary */
  431. *resp->offset = htonl(offset >> 32);
  432. *resp->offset1 = htonl(offset & 0xffffffff);
  433. resp->offset1 = NULL;
  434. } else {
  435. xdr_encode_hyper(resp->offset, offset);
  436. }
  437. }
  438. RETURN_STATUS(nfserr);
  439. }
  440. /*
  441. * Get file system stats
  442. */
  443. static __be32
  444. nfsd3_proc_fsstat(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
  445. struct nfsd3_fsstatres *resp)
  446. {
  447. __be32 nfserr;
  448. dprintk("nfsd: FSSTAT(3) %s\n",
  449. SVCFH_fmt(&argp->fh));
  450. nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
  451. fh_put(&argp->fh);
  452. RETURN_STATUS(nfserr);
  453. }
  454. /*
  455. * Get file system info
  456. */
  457. static __be32
  458. nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
  459. struct nfsd3_fsinfores *resp)
  460. {
  461. __be32 nfserr;
  462. u32 max_blocksize = svc_max_payload(rqstp);
  463. dprintk("nfsd: FSINFO(3) %s\n",
  464. SVCFH_fmt(&argp->fh));
  465. resp->f_rtmax = max_blocksize;
  466. resp->f_rtpref = max_blocksize;
  467. resp->f_rtmult = PAGE_SIZE;
  468. resp->f_wtmax = max_blocksize;
  469. resp->f_wtpref = max_blocksize;
  470. resp->f_wtmult = PAGE_SIZE;
  471. resp->f_dtpref = PAGE_SIZE;
  472. resp->f_maxfilesize = ~(u32) 0;
  473. resp->f_properties = NFS3_FSF_DEFAULT;
  474. nfserr = fh_verify(rqstp, &argp->fh, 0, MAY_NOP);
  475. /* Check special features of the file system. May request
  476. * different read/write sizes for file systems known to have
  477. * problems with large blocks */
  478. if (nfserr == 0) {
  479. struct super_block *sb = argp->fh.fh_dentry->d_inode->i_sb;
  480. /* Note that we don't care for remote fs's here */
  481. if (sb->s_magic == 0x4d44 /* MSDOS_SUPER_MAGIC */) {
  482. resp->f_properties = NFS3_FSF_BILLYBOY;
  483. }
  484. resp->f_maxfilesize = sb->s_maxbytes;
  485. }
  486. fh_put(&argp->fh);
  487. RETURN_STATUS(nfserr);
  488. }
  489. /*
  490. * Get pathconf info for the specified file
  491. */
  492. static __be32
  493. nfsd3_proc_pathconf(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
  494. struct nfsd3_pathconfres *resp)
  495. {
  496. __be32 nfserr;
  497. dprintk("nfsd: PATHCONF(3) %s\n",
  498. SVCFH_fmt(&argp->fh));
  499. /* Set default pathconf */
  500. resp->p_link_max = 255; /* at least */
  501. resp->p_name_max = 255; /* at least */
  502. resp->p_no_trunc = 0;
  503. resp->p_chown_restricted = 1;
  504. resp->p_case_insensitive = 0;
  505. resp->p_case_preserving = 1;
  506. nfserr = fh_verify(rqstp, &argp->fh, 0, MAY_NOP);
  507. if (nfserr == 0) {
  508. struct super_block *sb = argp->fh.fh_dentry->d_inode->i_sb;
  509. /* Note that we don't care for remote fs's here */
  510. switch (sb->s_magic) {
  511. case EXT2_SUPER_MAGIC:
  512. resp->p_link_max = EXT2_LINK_MAX;
  513. resp->p_name_max = EXT2_NAME_LEN;
  514. break;
  515. case 0x4d44: /* MSDOS_SUPER_MAGIC */
  516. resp->p_case_insensitive = 1;
  517. resp->p_case_preserving = 0;
  518. break;
  519. }
  520. }
  521. fh_put(&argp->fh);
  522. RETURN_STATUS(nfserr);
  523. }
  524. /*
  525. * Commit a file (range) to stable storage.
  526. */
  527. static __be32
  528. nfsd3_proc_commit(struct svc_rqst * rqstp, struct nfsd3_commitargs *argp,
  529. struct nfsd3_commitres *resp)
  530. {
  531. __be32 nfserr;
  532. dprintk("nfsd: COMMIT(3) %s %u@%Lu\n",
  533. SVCFH_fmt(&argp->fh),
  534. argp->count,
  535. (unsigned long long) argp->offset);
  536. if (argp->offset > NFS_OFFSET_MAX)
  537. RETURN_STATUS(nfserr_inval);
  538. fh_copy(&resp->fh, &argp->fh);
  539. nfserr = nfsd_commit(rqstp, &resp->fh, argp->offset, argp->count);
  540. RETURN_STATUS(nfserr);
  541. }
  542. /*
  543. * NFSv3 Server procedures.
  544. * Only the results of non-idempotent operations are cached.
  545. */
  546. #define nfs3svc_decode_voidargs NULL
  547. #define nfs3svc_release_void NULL
  548. #define nfs3svc_decode_fhandleargs nfs3svc_decode_fhandle
  549. #define nfs3svc_encode_attrstatres nfs3svc_encode_attrstat
  550. #define nfs3svc_encode_wccstatres nfs3svc_encode_wccstat
  551. #define nfsd3_mkdirargs nfsd3_createargs
  552. #define nfsd3_readdirplusargs nfsd3_readdirargs
  553. #define nfsd3_fhandleargs nfsd_fhandle
  554. #define nfsd3_fhandleres nfsd3_attrstat
  555. #define nfsd3_attrstatres nfsd3_attrstat
  556. #define nfsd3_wccstatres nfsd3_attrstat
  557. #define nfsd3_createres nfsd3_diropres
  558. #define nfsd3_voidres nfsd3_voidargs
  559. struct nfsd3_voidargs { int dummy; };
  560. #define PROC(name, argt, rest, relt, cache, respsize) \
  561. { (svc_procfunc) nfsd3_proc_##name, \
  562. (kxdrproc_t) nfs3svc_decode_##argt##args, \
  563. (kxdrproc_t) nfs3svc_encode_##rest##res, \
  564. (kxdrproc_t) nfs3svc_release_##relt, \
  565. sizeof(struct nfsd3_##argt##args), \
  566. sizeof(struct nfsd3_##rest##res), \
  567. 0, \
  568. cache, \
  569. respsize, \
  570. }
  571. #define ST 1 /* status*/
  572. #define FH 17 /* filehandle with length */
  573. #define AT 21 /* attributes */
  574. #define pAT (1+AT) /* post attributes - conditional */
  575. #define WC (7+pAT) /* WCC attributes */
  576. static struct svc_procedure nfsd_procedures3[22] = {
  577. PROC(null, void, void, void, RC_NOCACHE, ST),
  578. PROC(getattr, fhandle, attrstat, fhandle, RC_NOCACHE, ST+AT),
  579. PROC(setattr, sattr, wccstat, fhandle, RC_REPLBUFF, ST+WC),
  580. PROC(lookup, dirop, dirop, fhandle2, RC_NOCACHE, ST+FH+pAT+pAT),
  581. PROC(access, access, access, fhandle, RC_NOCACHE, ST+pAT+1),
  582. PROC(readlink, readlink, readlink, fhandle, RC_NOCACHE, ST+pAT+1+NFS3_MAXPATHLEN/4),
  583. PROC(read, read, read, fhandle, RC_NOCACHE, ST+pAT+4+NFSSVC_MAXBLKSIZE/4),
  584. PROC(write, write, write, fhandle, RC_REPLBUFF, ST+WC+4),
  585. PROC(create, create, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
  586. PROC(mkdir, mkdir, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
  587. PROC(symlink, symlink, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
  588. PROC(mknod, mknod, create, fhandle2, RC_REPLBUFF, ST+(1+FH+pAT)+WC),
  589. PROC(remove, dirop, wccstat, fhandle, RC_REPLBUFF, ST+WC),
  590. PROC(rmdir, dirop, wccstat, fhandle, RC_REPLBUFF, ST+WC),
  591. PROC(rename, rename, rename, fhandle2, RC_REPLBUFF, ST+WC+WC),
  592. PROC(link, link, link, fhandle2, RC_REPLBUFF, ST+pAT+WC),
  593. PROC(readdir, readdir, readdir, fhandle, RC_NOCACHE, 0),
  594. PROC(readdirplus,readdirplus, readdir, fhandle, RC_NOCACHE, 0),
  595. PROC(fsstat, fhandle, fsstat, void, RC_NOCACHE, ST+pAT+2*6+1),
  596. PROC(fsinfo, fhandle, fsinfo, void, RC_NOCACHE, ST+pAT+12),
  597. PROC(pathconf, fhandle, pathconf, void, RC_NOCACHE, ST+pAT+6),
  598. PROC(commit, commit, commit, fhandle, RC_NOCACHE, ST+WC+2),
  599. };
  600. struct svc_version nfsd_version3 = {
  601. .vs_vers = 3,
  602. .vs_nproc = 22,
  603. .vs_proc = nfsd_procedures3,
  604. .vs_dispatch = nfsd_dispatch,
  605. .vs_xdrsize = NFS3_SVC_XDRSIZE,
  606. };