nfs3proc.c 18 KB

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