nfs3proc.c 18 KB

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