nfs3proc.c 18 KB

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