nfs3proc.c 18 KB

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