nfs3proc.c 24 KB

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