nfs3proc.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909
  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/magic.h>
  21. #include <linux/sunrpc/svc.h>
  22. #include <linux/nfsd/nfsd.h>
  23. #include <linux/nfsd/cache.h>
  24. #include <linux/nfsd/xdr3.h>
  25. #include <linux/nfs3.h>
  26. #include "vfs.h"
  27. #define NFSDDBG_FACILITY NFSDDBG_PROC
  28. #define RETURN_STATUS(st) { resp->status = (st); return (st); }
  29. static int nfs3_ftypes[] = {
  30. 0, /* NF3NON */
  31. S_IFREG, /* NF3REG */
  32. S_IFDIR, /* NF3DIR */
  33. S_IFBLK, /* NF3BLK */
  34. S_IFCHR, /* NF3CHR */
  35. S_IFLNK, /* NF3LNK */
  36. S_IFSOCK, /* NF3SOCK */
  37. S_IFIFO, /* NF3FIFO */
  38. };
  39. /*
  40. * NULL call.
  41. */
  42. static __be32
  43. nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
  44. {
  45. return nfs_ok;
  46. }
  47. /*
  48. * Get a file's attributes
  49. */
  50. static __be32
  51. nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
  52. struct nfsd3_attrstat *resp)
  53. {
  54. int err;
  55. __be32 nfserr;
  56. dprintk("nfsd: GETATTR(3) %s\n",
  57. SVCFH_fmt(&argp->fh));
  58. fh_copy(&resp->fh, &argp->fh);
  59. nfserr = fh_verify(rqstp, &resp->fh, 0,
  60. NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
  61. if (nfserr)
  62. RETURN_STATUS(nfserr);
  63. err = vfs_getattr(resp->fh.fh_export->ex_path.mnt,
  64. resp->fh.fh_dentry, &resp->stat);
  65. nfserr = nfserrno(err);
  66. RETURN_STATUS(nfserr);
  67. }
  68. /*
  69. * Set a file's attributes
  70. */
  71. static __be32
  72. nfsd3_proc_setattr(struct svc_rqst *rqstp, struct nfsd3_sattrargs *argp,
  73. struct nfsd3_attrstat *resp)
  74. {
  75. __be32 nfserr;
  76. dprintk("nfsd: SETATTR(3) %s\n",
  77. SVCFH_fmt(&argp->fh));
  78. fh_copy(&resp->fh, &argp->fh);
  79. nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs,
  80. argp->check_guard, argp->guardtime);
  81. RETURN_STATUS(nfserr);
  82. }
  83. /*
  84. * Look up a path name component
  85. */
  86. static __be32
  87. nfsd3_proc_lookup(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
  88. struct nfsd3_diropres *resp)
  89. {
  90. __be32 nfserr;
  91. dprintk("nfsd: LOOKUP(3) %s %.*s\n",
  92. SVCFH_fmt(&argp->fh),
  93. argp->len,
  94. argp->name);
  95. fh_copy(&resp->dirfh, &argp->fh);
  96. fh_init(&resp->fh, NFS3_FHSIZE);
  97. nfserr = nfsd_lookup(rqstp, &resp->dirfh,
  98. argp->name,
  99. argp->len,
  100. &resp->fh);
  101. RETURN_STATUS(nfserr);
  102. }
  103. /*
  104. * Check file access
  105. */
  106. static __be32
  107. nfsd3_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp,
  108. struct nfsd3_accessres *resp)
  109. {
  110. __be32 nfserr;
  111. dprintk("nfsd: ACCESS(3) %s 0x%x\n",
  112. SVCFH_fmt(&argp->fh),
  113. argp->access);
  114. fh_copy(&resp->fh, &argp->fh);
  115. resp->access = argp->access;
  116. nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
  117. RETURN_STATUS(nfserr);
  118. }
  119. /*
  120. * Read a symlink.
  121. */
  122. static __be32
  123. nfsd3_proc_readlink(struct svc_rqst *rqstp, struct nfsd3_readlinkargs *argp,
  124. struct nfsd3_readlinkres *resp)
  125. {
  126. __be32 nfserr;
  127. dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
  128. /* Read the symlink. */
  129. fh_copy(&resp->fh, &argp->fh);
  130. resp->len = NFS3_MAXPATHLEN;
  131. nfserr = nfsd_readlink(rqstp, &resp->fh, argp->buffer, &resp->len);
  132. RETURN_STATUS(nfserr);
  133. }
  134. /*
  135. * Read a portion of a file.
  136. */
  137. static __be32
  138. nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
  139. struct nfsd3_readres *resp)
  140. {
  141. __be32 nfserr;
  142. u32 max_blocksize = svc_max_payload(rqstp);
  143. dprintk("nfsd: READ(3) %s %lu bytes at %lu\n",
  144. SVCFH_fmt(&argp->fh),
  145. (unsigned long) argp->count,
  146. (unsigned long) argp->offset);
  147. /* Obtain buffer pointer for payload.
  148. * 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof)
  149. * + 1 (xdr opaque byte count) = 26
  150. */
  151. resp->count = argp->count;
  152. if (max_blocksize < resp->count)
  153. resp->count = max_blocksize;
  154. svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
  155. fh_copy(&resp->fh, &argp->fh);
  156. nfserr = nfsd_read(rqstp, &resp->fh, NULL,
  157. argp->offset,
  158. rqstp->rq_vec, argp->vlen,
  159. &resp->count);
  160. if (nfserr == 0) {
  161. struct inode *inode = resp->fh.fh_dentry->d_inode;
  162. resp->eof = (argp->offset + resp->count) >= inode->i_size;
  163. }
  164. RETURN_STATUS(nfserr);
  165. }
  166. /*
  167. * Write data to a file
  168. */
  169. static __be32
  170. nfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp,
  171. struct nfsd3_writeres *resp)
  172. {
  173. __be32 nfserr;
  174. unsigned long cnt = argp->len;
  175. dprintk("nfsd: WRITE(3) %s %d bytes at %ld%s\n",
  176. SVCFH_fmt(&argp->fh),
  177. argp->len,
  178. (unsigned long) argp->offset,
  179. argp->stable? " stable" : "");
  180. fh_copy(&resp->fh, &argp->fh);
  181. resp->committed = argp->stable;
  182. nfserr = nfsd_write(rqstp, &resp->fh, NULL,
  183. argp->offset,
  184. rqstp->rq_vec, argp->vlen,
  185. &cnt,
  186. &resp->committed);
  187. resp->count = cnt;
  188. RETURN_STATUS(nfserr);
  189. }
  190. /*
  191. * With NFSv3, CREATE processing is a lot easier than with NFSv2.
  192. * At least in theory; we'll see how it fares in practice when the
  193. * first reports about SunOS compatibility problems start to pour in...
  194. */
  195. static __be32
  196. nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
  197. struct nfsd3_diropres *resp)
  198. {
  199. svc_fh *dirfhp, *newfhp = NULL;
  200. struct iattr *attr;
  201. __be32 nfserr;
  202. dprintk("nfsd: CREATE(3) %s %.*s\n",
  203. SVCFH_fmt(&argp->fh),
  204. argp->len,
  205. argp->name);
  206. dirfhp = fh_copy(&resp->dirfh, &argp->fh);
  207. newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
  208. attr = &argp->attrs;
  209. /* Get the directory inode */
  210. nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_CREATE);
  211. if (nfserr)
  212. RETURN_STATUS(nfserr);
  213. /* Unfudge the mode bits */
  214. attr->ia_mode &= ~S_IFMT;
  215. if (!(attr->ia_valid & ATTR_MODE)) {
  216. attr->ia_valid |= ATTR_MODE;
  217. attr->ia_mode = S_IFREG;
  218. } else {
  219. attr->ia_mode = (attr->ia_mode & ~S_IFMT) | S_IFREG;
  220. }
  221. /* Now create the file and set attributes */
  222. nfserr = nfsd_create_v3(rqstp, dirfhp, argp->name, argp->len,
  223. attr, newfhp,
  224. argp->createmode, argp->verf, NULL, NULL);
  225. RETURN_STATUS(nfserr);
  226. }
  227. /*
  228. * Make directory. This operation is not idempotent.
  229. */
  230. static __be32
  231. nfsd3_proc_mkdir(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
  232. struct nfsd3_diropres *resp)
  233. {
  234. __be32 nfserr;
  235. dprintk("nfsd: MKDIR(3) %s %.*s\n",
  236. SVCFH_fmt(&argp->fh),
  237. argp->len,
  238. argp->name);
  239. argp->attrs.ia_valid &= ~ATTR_SIZE;
  240. fh_copy(&resp->dirfh, &argp->fh);
  241. fh_init(&resp->fh, NFS3_FHSIZE);
  242. nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
  243. &argp->attrs, S_IFDIR, 0, &resp->fh);
  244. RETURN_STATUS(nfserr);
  245. }
  246. static __be32
  247. nfsd3_proc_symlink(struct svc_rqst *rqstp, struct nfsd3_symlinkargs *argp,
  248. struct nfsd3_diropres *resp)
  249. {
  250. __be32 nfserr;
  251. dprintk("nfsd: SYMLINK(3) %s %.*s -> %.*s\n",
  252. SVCFH_fmt(&argp->ffh),
  253. argp->flen, argp->fname,
  254. argp->tlen, argp->tname);
  255. fh_copy(&resp->dirfh, &argp->ffh);
  256. fh_init(&resp->fh, NFS3_FHSIZE);
  257. nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,
  258. argp->tname, argp->tlen,
  259. &resp->fh, &argp->attrs);
  260. RETURN_STATUS(nfserr);
  261. }
  262. /*
  263. * Make socket/fifo/device.
  264. */
  265. static __be32
  266. nfsd3_proc_mknod(struct svc_rqst *rqstp, struct nfsd3_mknodargs *argp,
  267. struct nfsd3_diropres *resp)
  268. {
  269. __be32 nfserr;
  270. int type;
  271. dev_t rdev = 0;
  272. dprintk("nfsd: MKNOD(3) %s %.*s\n",
  273. SVCFH_fmt(&argp->fh),
  274. argp->len,
  275. argp->name);
  276. fh_copy(&resp->dirfh, &argp->fh);
  277. fh_init(&resp->fh, NFS3_FHSIZE);
  278. if (argp->ftype == 0 || argp->ftype >= NF3BAD)
  279. RETURN_STATUS(nfserr_inval);
  280. if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
  281. rdev = MKDEV(argp->major, argp->minor);
  282. if (MAJOR(rdev) != argp->major ||
  283. MINOR(rdev) != argp->minor)
  284. RETURN_STATUS(nfserr_inval);
  285. } else
  286. if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO)
  287. RETURN_STATUS(nfserr_inval);
  288. type = nfs3_ftypes[argp->ftype];
  289. nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
  290. &argp->attrs, type, rdev, &resp->fh);
  291. RETURN_STATUS(nfserr);
  292. }
  293. /*
  294. * Remove file/fifo/socket etc.
  295. */
  296. static __be32
  297. nfsd3_proc_remove(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
  298. struct nfsd3_attrstat *resp)
  299. {
  300. __be32 nfserr;
  301. dprintk("nfsd: REMOVE(3) %s %.*s\n",
  302. SVCFH_fmt(&argp->fh),
  303. argp->len,
  304. argp->name);
  305. /* Unlink. -S_IFDIR means file must not be a directory */
  306. fh_copy(&resp->fh, &argp->fh);
  307. nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len);
  308. RETURN_STATUS(nfserr);
  309. }
  310. /*
  311. * Remove a directory
  312. */
  313. static __be32
  314. nfsd3_proc_rmdir(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
  315. struct nfsd3_attrstat *resp)
  316. {
  317. __be32 nfserr;
  318. dprintk("nfsd: RMDIR(3) %s %.*s\n",
  319. SVCFH_fmt(&argp->fh),
  320. argp->len,
  321. argp->name);
  322. fh_copy(&resp->fh, &argp->fh);
  323. nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len);
  324. RETURN_STATUS(nfserr);
  325. }
  326. static __be32
  327. nfsd3_proc_rename(struct svc_rqst *rqstp, struct nfsd3_renameargs *argp,
  328. struct nfsd3_renameres *resp)
  329. {
  330. __be32 nfserr;
  331. dprintk("nfsd: RENAME(3) %s %.*s ->\n",
  332. SVCFH_fmt(&argp->ffh),
  333. argp->flen,
  334. argp->fname);
  335. dprintk("nfsd: -> %s %.*s\n",
  336. SVCFH_fmt(&argp->tfh),
  337. argp->tlen,
  338. argp->tname);
  339. fh_copy(&resp->ffh, &argp->ffh);
  340. fh_copy(&resp->tfh, &argp->tfh);
  341. nfserr = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
  342. &resp->tfh, argp->tname, argp->tlen);
  343. RETURN_STATUS(nfserr);
  344. }
  345. static __be32
  346. nfsd3_proc_link(struct svc_rqst *rqstp, struct nfsd3_linkargs *argp,
  347. struct nfsd3_linkres *resp)
  348. {
  349. __be32 nfserr;
  350. dprintk("nfsd: LINK(3) %s ->\n",
  351. SVCFH_fmt(&argp->ffh));
  352. dprintk("nfsd: -> %s %.*s\n",
  353. SVCFH_fmt(&argp->tfh),
  354. argp->tlen,
  355. argp->tname);
  356. fh_copy(&resp->fh, &argp->ffh);
  357. fh_copy(&resp->tfh, &argp->tfh);
  358. nfserr = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
  359. &resp->fh);
  360. RETURN_STATUS(nfserr);
  361. }
  362. /*
  363. * Read a portion of a directory.
  364. */
  365. static __be32
  366. nfsd3_proc_readdir(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
  367. struct nfsd3_readdirres *resp)
  368. {
  369. __be32 nfserr;
  370. int count;
  371. dprintk("nfsd: READDIR(3) %s %d bytes at %d\n",
  372. SVCFH_fmt(&argp->fh),
  373. argp->count, (u32) argp->cookie);
  374. /* Make sure we've room for the NULL ptr & eof flag, and shrink to
  375. * client read size */
  376. count = (argp->count >> 2) - 2;
  377. /* Read directory and encode entries on the fly */
  378. fh_copy(&resp->fh, &argp->fh);
  379. resp->buflen = count;
  380. resp->common.err = nfs_ok;
  381. resp->buffer = argp->buffer;
  382. resp->rqstp = rqstp;
  383. nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t*) &argp->cookie,
  384. &resp->common, nfs3svc_encode_entry);
  385. memcpy(resp->verf, argp->verf, 8);
  386. resp->count = resp->buffer - argp->buffer;
  387. if (resp->offset)
  388. xdr_encode_hyper(resp->offset, argp->cookie);
  389. RETURN_STATUS(nfserr);
  390. }
  391. /*
  392. * Read a portion of a directory, including file handles and attrs.
  393. * For now, we choose to ignore the dircount parameter.
  394. */
  395. static __be32
  396. nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
  397. struct nfsd3_readdirres *resp)
  398. {
  399. __be32 nfserr;
  400. int count = 0;
  401. loff_t offset;
  402. int i;
  403. caddr_t page_addr = NULL;
  404. dprintk("nfsd: READDIR+(3) %s %d bytes at %d\n",
  405. SVCFH_fmt(&argp->fh),
  406. argp->count, (u32) argp->cookie);
  407. /* Convert byte count to number of words (i.e. >> 2),
  408. * and reserve room for the NULL ptr & eof flag (-2 words) */
  409. resp->count = (argp->count >> 2) - 2;
  410. /* Read directory and encode entries on the fly */
  411. fh_copy(&resp->fh, &argp->fh);
  412. resp->common.err = nfs_ok;
  413. resp->buffer = argp->buffer;
  414. resp->buflen = resp->count;
  415. resp->rqstp = rqstp;
  416. offset = argp->cookie;
  417. nfserr = nfsd_readdir(rqstp, &resp->fh,
  418. &offset,
  419. &resp->common,
  420. nfs3svc_encode_entry_plus);
  421. memcpy(resp->verf, argp->verf, 8);
  422. for (i=1; i<rqstp->rq_resused ; i++) {
  423. page_addr = page_address(rqstp->rq_respages[i]);
  424. if (((caddr_t)resp->buffer >= page_addr) &&
  425. ((caddr_t)resp->buffer < page_addr + PAGE_SIZE)) {
  426. count += (caddr_t)resp->buffer - page_addr;
  427. break;
  428. }
  429. count += PAGE_SIZE;
  430. }
  431. resp->count = count >> 2;
  432. if (resp->offset) {
  433. if (unlikely(resp->offset1)) {
  434. /* we ended up with offset on a page boundary */
  435. *resp->offset = htonl(offset >> 32);
  436. *resp->offset1 = htonl(offset & 0xffffffff);
  437. resp->offset1 = NULL;
  438. } else {
  439. xdr_encode_hyper(resp->offset, offset);
  440. }
  441. }
  442. RETURN_STATUS(nfserr);
  443. }
  444. /*
  445. * Get file system stats
  446. */
  447. static __be32
  448. nfsd3_proc_fsstat(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
  449. struct nfsd3_fsstatres *resp)
  450. {
  451. __be32 nfserr;
  452. dprintk("nfsd: FSSTAT(3) %s\n",
  453. SVCFH_fmt(&argp->fh));
  454. nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0);
  455. fh_put(&argp->fh);
  456. RETURN_STATUS(nfserr);
  457. }
  458. /*
  459. * Get file system info
  460. */
  461. static __be32
  462. nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
  463. struct nfsd3_fsinfores *resp)
  464. {
  465. __be32 nfserr;
  466. u32 max_blocksize = svc_max_payload(rqstp);
  467. dprintk("nfsd: FSINFO(3) %s\n",
  468. SVCFH_fmt(&argp->fh));
  469. resp->f_rtmax = max_blocksize;
  470. resp->f_rtpref = max_blocksize;
  471. resp->f_rtmult = PAGE_SIZE;
  472. resp->f_wtmax = max_blocksize;
  473. resp->f_wtpref = max_blocksize;
  474. resp->f_wtmult = PAGE_SIZE;
  475. resp->f_dtpref = PAGE_SIZE;
  476. resp->f_maxfilesize = ~(u32) 0;
  477. resp->f_properties = NFS3_FSF_DEFAULT;
  478. nfserr = fh_verify(rqstp, &argp->fh, 0,
  479. NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT);
  480. /* Check special features of the file system. May request
  481. * different read/write sizes for file systems known to have
  482. * problems with large blocks */
  483. if (nfserr == 0) {
  484. struct super_block *sb = argp->fh.fh_dentry->d_inode->i_sb;
  485. /* Note that we don't care for remote fs's here */
  486. if (sb->s_magic == MSDOS_SUPER_MAGIC) {
  487. resp->f_properties = NFS3_FSF_BILLYBOY;
  488. }
  489. resp->f_maxfilesize = sb->s_maxbytes;
  490. }
  491. fh_put(&argp->fh);
  492. RETURN_STATUS(nfserr);
  493. }
  494. /*
  495. * Get pathconf info for the specified file
  496. */
  497. static __be32
  498. nfsd3_proc_pathconf(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
  499. struct nfsd3_pathconfres *resp)
  500. {
  501. __be32 nfserr;
  502. dprintk("nfsd: PATHCONF(3) %s\n",
  503. SVCFH_fmt(&argp->fh));
  504. /* Set default pathconf */
  505. resp->p_link_max = 255; /* at least */
  506. resp->p_name_max = 255; /* at least */
  507. resp->p_no_trunc = 0;
  508. resp->p_chown_restricted = 1;
  509. resp->p_case_insensitive = 0;
  510. resp->p_case_preserving = 1;
  511. nfserr = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP);
  512. if (nfserr == 0) {
  513. struct super_block *sb = argp->fh.fh_dentry->d_inode->i_sb;
  514. /* Note that we don't care for remote fs's here */
  515. switch (sb->s_magic) {
  516. case EXT2_SUPER_MAGIC:
  517. resp->p_link_max = EXT2_LINK_MAX;
  518. resp->p_name_max = EXT2_NAME_LEN;
  519. break;
  520. case MSDOS_SUPER_MAGIC:
  521. resp->p_case_insensitive = 1;
  522. resp->p_case_preserving = 0;
  523. break;
  524. }
  525. }
  526. fh_put(&argp->fh);
  527. RETURN_STATUS(nfserr);
  528. }
  529. /*
  530. * Commit a file (range) to stable storage.
  531. */
  532. static __be32
  533. nfsd3_proc_commit(struct svc_rqst * rqstp, struct nfsd3_commitargs *argp,
  534. struct nfsd3_commitres *resp)
  535. {
  536. __be32 nfserr;
  537. dprintk("nfsd: COMMIT(3) %s %u@%Lu\n",
  538. SVCFH_fmt(&argp->fh),
  539. argp->count,
  540. (unsigned long long) argp->offset);
  541. if (argp->offset > NFS_OFFSET_MAX)
  542. RETURN_STATUS(nfserr_inval);
  543. fh_copy(&resp->fh, &argp->fh);
  544. nfserr = nfsd_commit(rqstp, &resp->fh, argp->offset, argp->count);
  545. RETURN_STATUS(nfserr);
  546. }
  547. /*
  548. * NFSv3 Server procedures.
  549. * Only the results of non-idempotent operations are cached.
  550. */
  551. #define nfs3svc_decode_fhandleargs nfs3svc_decode_fhandle
  552. #define nfs3svc_encode_attrstatres nfs3svc_encode_attrstat
  553. #define nfs3svc_encode_wccstatres nfs3svc_encode_wccstat
  554. #define nfsd3_mkdirargs nfsd3_createargs
  555. #define nfsd3_readdirplusargs nfsd3_readdirargs
  556. #define nfsd3_fhandleargs nfsd_fhandle
  557. #define nfsd3_fhandleres nfsd3_attrstat
  558. #define nfsd3_attrstatres nfsd3_attrstat
  559. #define nfsd3_wccstatres nfsd3_attrstat
  560. #define nfsd3_createres nfsd3_diropres
  561. #define nfsd3_voidres nfsd3_voidargs
  562. struct nfsd3_voidargs { int dummy; };
  563. #define PROC(name, argt, rest, relt, cache, respsize) \
  564. { (svc_procfunc) nfsd3_proc_##name, \
  565. (kxdrproc_t) nfs3svc_decode_##argt##args, \
  566. (kxdrproc_t) nfs3svc_encode_##rest##res, \
  567. (kxdrproc_t) nfs3svc_release_##relt, \
  568. sizeof(struct nfsd3_##argt##args), \
  569. sizeof(struct nfsd3_##rest##res), \
  570. 0, \
  571. cache, \
  572. respsize, \
  573. }
  574. #define ST 1 /* status*/
  575. #define FH 17 /* filehandle with length */
  576. #define AT 21 /* attributes */
  577. #define pAT (1+AT) /* post attributes - conditional */
  578. #define WC (7+pAT) /* WCC attributes */
  579. static struct svc_procedure nfsd_procedures3[22] = {
  580. [NFS3PROC_NULL] = {
  581. .pc_func = (svc_procfunc) nfsd3_proc_null,
  582. .pc_encode = (kxdrproc_t) nfs3svc_encode_voidres,
  583. .pc_argsize = sizeof(struct nfsd3_voidargs),
  584. .pc_ressize = sizeof(struct nfsd3_voidres),
  585. .pc_cachetype = RC_NOCACHE,
  586. .pc_xdrressize = ST,
  587. },
  588. [NFS3PROC_GETATTR] = {
  589. .pc_func = (svc_procfunc) nfsd3_proc_getattr,
  590. .pc_decode = (kxdrproc_t) nfs3svc_decode_fhandleargs,
  591. .pc_encode = (kxdrproc_t) nfs3svc_encode_attrstatres,
  592. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle,
  593. .pc_argsize = sizeof(struct nfsd3_fhandleargs),
  594. .pc_ressize = sizeof(struct nfsd3_attrstatres),
  595. .pc_cachetype = RC_NOCACHE,
  596. .pc_xdrressize = ST+AT,
  597. },
  598. [NFS3PROC_SETATTR] = {
  599. .pc_func = (svc_procfunc) nfsd3_proc_setattr,
  600. .pc_decode = (kxdrproc_t) nfs3svc_decode_sattrargs,
  601. .pc_encode = (kxdrproc_t) nfs3svc_encode_wccstatres,
  602. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle,
  603. .pc_argsize = sizeof(struct nfsd3_sattrargs),
  604. .pc_ressize = sizeof(struct nfsd3_wccstatres),
  605. .pc_cachetype = RC_REPLBUFF,
  606. .pc_xdrressize = ST+WC,
  607. },
  608. [NFS3PROC_LOOKUP] = {
  609. .pc_func = (svc_procfunc) nfsd3_proc_lookup,
  610. .pc_decode = (kxdrproc_t) nfs3svc_decode_diropargs,
  611. .pc_encode = (kxdrproc_t) nfs3svc_encode_diropres,
  612. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle2,
  613. .pc_argsize = sizeof(struct nfsd3_diropargs),
  614. .pc_ressize = sizeof(struct nfsd3_diropres),
  615. .pc_cachetype = RC_NOCACHE,
  616. .pc_xdrressize = ST+FH+pAT+pAT,
  617. },
  618. [NFS3PROC_ACCESS] = {
  619. .pc_func = (svc_procfunc) nfsd3_proc_access,
  620. .pc_decode = (kxdrproc_t) nfs3svc_decode_accessargs,
  621. .pc_encode = (kxdrproc_t) nfs3svc_encode_accessres,
  622. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle,
  623. .pc_argsize = sizeof(struct nfsd3_accessargs),
  624. .pc_ressize = sizeof(struct nfsd3_accessres),
  625. .pc_cachetype = RC_NOCACHE,
  626. .pc_xdrressize = ST+pAT+1,
  627. },
  628. [NFS3PROC_READLINK] = {
  629. .pc_func = (svc_procfunc) nfsd3_proc_readlink,
  630. .pc_decode = (kxdrproc_t) nfs3svc_decode_readlinkargs,
  631. .pc_encode = (kxdrproc_t) nfs3svc_encode_readlinkres,
  632. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle,
  633. .pc_argsize = sizeof(struct nfsd3_readlinkargs),
  634. .pc_ressize = sizeof(struct nfsd3_readlinkres),
  635. .pc_cachetype = RC_NOCACHE,
  636. .pc_xdrressize = ST+pAT+1+NFS3_MAXPATHLEN/4,
  637. },
  638. [NFS3PROC_READ] = {
  639. .pc_func = (svc_procfunc) nfsd3_proc_read,
  640. .pc_decode = (kxdrproc_t) nfs3svc_decode_readargs,
  641. .pc_encode = (kxdrproc_t) nfs3svc_encode_readres,
  642. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle,
  643. .pc_argsize = sizeof(struct nfsd3_readargs),
  644. .pc_ressize = sizeof(struct nfsd3_readres),
  645. .pc_cachetype = RC_NOCACHE,
  646. .pc_xdrressize = ST+pAT+4+NFSSVC_MAXBLKSIZE/4,
  647. },
  648. [NFS3PROC_WRITE] = {
  649. .pc_func = (svc_procfunc) nfsd3_proc_write,
  650. .pc_decode = (kxdrproc_t) nfs3svc_decode_writeargs,
  651. .pc_encode = (kxdrproc_t) nfs3svc_encode_writeres,
  652. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle,
  653. .pc_argsize = sizeof(struct nfsd3_writeargs),
  654. .pc_ressize = sizeof(struct nfsd3_writeres),
  655. .pc_cachetype = RC_REPLBUFF,
  656. .pc_xdrressize = ST+WC+4,
  657. },
  658. [NFS3PROC_CREATE] = {
  659. .pc_func = (svc_procfunc) nfsd3_proc_create,
  660. .pc_decode = (kxdrproc_t) nfs3svc_decode_createargs,
  661. .pc_encode = (kxdrproc_t) nfs3svc_encode_createres,
  662. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle2,
  663. .pc_argsize = sizeof(struct nfsd3_createargs),
  664. .pc_ressize = sizeof(struct nfsd3_createres),
  665. .pc_cachetype = RC_REPLBUFF,
  666. .pc_xdrressize = ST+(1+FH+pAT)+WC,
  667. },
  668. [NFS3PROC_MKDIR] = {
  669. .pc_func = (svc_procfunc) nfsd3_proc_mkdir,
  670. .pc_decode = (kxdrproc_t) nfs3svc_decode_mkdirargs,
  671. .pc_encode = (kxdrproc_t) nfs3svc_encode_createres,
  672. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle2,
  673. .pc_argsize = sizeof(struct nfsd3_mkdirargs),
  674. .pc_ressize = sizeof(struct nfsd3_createres),
  675. .pc_cachetype = RC_REPLBUFF,
  676. .pc_xdrressize = ST+(1+FH+pAT)+WC,
  677. },
  678. [NFS3PROC_SYMLINK] = {
  679. .pc_func = (svc_procfunc) nfsd3_proc_symlink,
  680. .pc_decode = (kxdrproc_t) nfs3svc_decode_symlinkargs,
  681. .pc_encode = (kxdrproc_t) nfs3svc_encode_createres,
  682. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle2,
  683. .pc_argsize = sizeof(struct nfsd3_symlinkargs),
  684. .pc_ressize = sizeof(struct nfsd3_createres),
  685. .pc_cachetype = RC_REPLBUFF,
  686. .pc_xdrressize = ST+(1+FH+pAT)+WC,
  687. },
  688. [NFS3PROC_MKNOD] = {
  689. .pc_func = (svc_procfunc) nfsd3_proc_mknod,
  690. .pc_decode = (kxdrproc_t) nfs3svc_decode_mknodargs,
  691. .pc_encode = (kxdrproc_t) nfs3svc_encode_createres,
  692. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle2,
  693. .pc_argsize = sizeof(struct nfsd3_mknodargs),
  694. .pc_ressize = sizeof(struct nfsd3_createres),
  695. .pc_cachetype = RC_REPLBUFF,
  696. .pc_xdrressize = ST+(1+FH+pAT)+WC,
  697. },
  698. [NFS3PROC_REMOVE] = {
  699. .pc_func = (svc_procfunc) nfsd3_proc_remove,
  700. .pc_decode = (kxdrproc_t) nfs3svc_decode_diropargs,
  701. .pc_encode = (kxdrproc_t) nfs3svc_encode_wccstatres,
  702. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle,
  703. .pc_argsize = sizeof(struct nfsd3_diropargs),
  704. .pc_ressize = sizeof(struct nfsd3_wccstatres),
  705. .pc_cachetype = RC_REPLBUFF,
  706. .pc_xdrressize = ST+WC,
  707. },
  708. [NFS3PROC_RMDIR] = {
  709. .pc_func = (svc_procfunc) nfsd3_proc_rmdir,
  710. .pc_decode = (kxdrproc_t) nfs3svc_decode_diropargs,
  711. .pc_encode = (kxdrproc_t) nfs3svc_encode_wccstatres,
  712. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle,
  713. .pc_argsize = sizeof(struct nfsd3_diropargs),
  714. .pc_ressize = sizeof(struct nfsd3_wccstatres),
  715. .pc_cachetype = RC_REPLBUFF,
  716. .pc_xdrressize = ST+WC,
  717. },
  718. [NFS3PROC_RENAME] = {
  719. .pc_func = (svc_procfunc) nfsd3_proc_rename,
  720. .pc_decode = (kxdrproc_t) nfs3svc_decode_renameargs,
  721. .pc_encode = (kxdrproc_t) nfs3svc_encode_renameres,
  722. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle2,
  723. .pc_argsize = sizeof(struct nfsd3_renameargs),
  724. .pc_ressize = sizeof(struct nfsd3_renameres),
  725. .pc_cachetype = RC_REPLBUFF,
  726. .pc_xdrressize = ST+WC+WC,
  727. },
  728. [NFS3PROC_LINK] = {
  729. .pc_func = (svc_procfunc) nfsd3_proc_link,
  730. .pc_decode = (kxdrproc_t) nfs3svc_decode_linkargs,
  731. .pc_encode = (kxdrproc_t) nfs3svc_encode_linkres,
  732. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle2,
  733. .pc_argsize = sizeof(struct nfsd3_linkargs),
  734. .pc_ressize = sizeof(struct nfsd3_linkres),
  735. .pc_cachetype = RC_REPLBUFF,
  736. .pc_xdrressize = ST+pAT+WC,
  737. },
  738. [NFS3PROC_READDIR] = {
  739. .pc_func = (svc_procfunc) nfsd3_proc_readdir,
  740. .pc_decode = (kxdrproc_t) nfs3svc_decode_readdirargs,
  741. .pc_encode = (kxdrproc_t) nfs3svc_encode_readdirres,
  742. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle,
  743. .pc_argsize = sizeof(struct nfsd3_readdirargs),
  744. .pc_ressize = sizeof(struct nfsd3_readdirres),
  745. .pc_cachetype = RC_NOCACHE,
  746. },
  747. [NFS3PROC_READDIRPLUS] = {
  748. .pc_func = (svc_procfunc) nfsd3_proc_readdirplus,
  749. .pc_decode = (kxdrproc_t) nfs3svc_decode_readdirplusargs,
  750. .pc_encode = (kxdrproc_t) nfs3svc_encode_readdirres,
  751. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle,
  752. .pc_argsize = sizeof(struct nfsd3_readdirplusargs),
  753. .pc_ressize = sizeof(struct nfsd3_readdirres),
  754. .pc_cachetype = RC_NOCACHE,
  755. },
  756. [NFS3PROC_FSSTAT] = {
  757. .pc_func = (svc_procfunc) nfsd3_proc_fsstat,
  758. .pc_decode = (kxdrproc_t) nfs3svc_decode_fhandleargs,
  759. .pc_encode = (kxdrproc_t) nfs3svc_encode_fsstatres,
  760. .pc_argsize = sizeof(struct nfsd3_fhandleargs),
  761. .pc_ressize = sizeof(struct nfsd3_fsstatres),
  762. .pc_cachetype = RC_NOCACHE,
  763. .pc_xdrressize = ST+pAT+2*6+1,
  764. },
  765. [NFS3PROC_FSINFO] = {
  766. .pc_func = (svc_procfunc) nfsd3_proc_fsinfo,
  767. .pc_decode = (kxdrproc_t) nfs3svc_decode_fhandleargs,
  768. .pc_encode = (kxdrproc_t) nfs3svc_encode_fsinfores,
  769. .pc_argsize = sizeof(struct nfsd3_fhandleargs),
  770. .pc_ressize = sizeof(struct nfsd3_fsinfores),
  771. .pc_cachetype = RC_NOCACHE,
  772. .pc_xdrressize = ST+pAT+12,
  773. },
  774. [NFS3PROC_PATHCONF] = {
  775. .pc_func = (svc_procfunc) nfsd3_proc_pathconf,
  776. .pc_decode = (kxdrproc_t) nfs3svc_decode_fhandleargs,
  777. .pc_encode = (kxdrproc_t) nfs3svc_encode_pathconfres,
  778. .pc_argsize = sizeof(struct nfsd3_fhandleargs),
  779. .pc_ressize = sizeof(struct nfsd3_pathconfres),
  780. .pc_cachetype = RC_NOCACHE,
  781. .pc_xdrressize = ST+pAT+6,
  782. },
  783. [NFS3PROC_COMMIT] = {
  784. .pc_func = (svc_procfunc) nfsd3_proc_commit,
  785. .pc_decode = (kxdrproc_t) nfs3svc_decode_commitargs,
  786. .pc_encode = (kxdrproc_t) nfs3svc_encode_commitres,
  787. .pc_release = (kxdrproc_t) nfs3svc_release_fhandle,
  788. .pc_argsize = sizeof(struct nfsd3_commitargs),
  789. .pc_ressize = sizeof(struct nfsd3_commitres),
  790. .pc_cachetype = RC_NOCACHE,
  791. .pc_xdrressize = ST+WC+2,
  792. },
  793. };
  794. struct svc_version nfsd_version3 = {
  795. .vs_vers = 3,
  796. .vs_nproc = 22,
  797. .vs_proc = nfsd_procedures3,
  798. .vs_dispatch = nfsd_dispatch,
  799. .vs_xdrsize = NFS3_SVC_XDRSIZE,
  800. };