nfs4proc.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063
  1. /*
  2. * fs/nfsd/nfs4proc.c
  3. *
  4. * Server-side procedures for NFSv4.
  5. *
  6. * Copyright (c) 2002 The Regents of the University of Michigan.
  7. * All rights reserved.
  8. *
  9. * Kendrick Smith <kmsmith@umich.edu>
  10. * Andy Adamson <andros@umich.edu>
  11. *
  12. * Redistribution and use in source and binary forms, with or without
  13. * modification, are permitted provided that the following conditions
  14. * are met:
  15. *
  16. * 1. Redistributions of source code must retain the above copyright
  17. * notice, this list of conditions and the following disclaimer.
  18. * 2. Redistributions in binary form must reproduce the above copyright
  19. * notice, this list of conditions and the following disclaimer in the
  20. * documentation and/or other materials provided with the distribution.
  21. * 3. Neither the name of the University nor the names of its
  22. * contributors may be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  26. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  27. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  28. * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  30. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  31. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  32. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  33. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  34. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  35. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  36. */
  37. #include <linux/param.h>
  38. #include <linux/major.h>
  39. #include <linux/slab.h>
  40. #include <linux/file.h>
  41. #include <linux/sunrpc/svc.h>
  42. #include <linux/nfsd/nfsd.h>
  43. #include <linux/nfsd/cache.h>
  44. #include <linux/nfs4.h>
  45. #include <linux/nfsd/state.h>
  46. #include <linux/nfsd/xdr4.h>
  47. #include <linux/nfs4_acl.h>
  48. #define NFSDDBG_FACILITY NFSDDBG_PROC
  49. static inline void
  50. fh_dup2(struct svc_fh *dst, struct svc_fh *src)
  51. {
  52. fh_put(dst);
  53. dget(src->fh_dentry);
  54. if (src->fh_export)
  55. cache_get(&src->fh_export->h);
  56. *dst = *src;
  57. }
  58. static __be32
  59. do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, int accmode)
  60. {
  61. __be32 status;
  62. if (open->op_truncate &&
  63. !(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
  64. return nfserr_inval;
  65. if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
  66. accmode |= MAY_READ;
  67. if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
  68. accmode |= (MAY_WRITE | MAY_TRUNC);
  69. if (open->op_share_deny & NFS4_SHARE_DENY_WRITE)
  70. accmode |= MAY_WRITE;
  71. status = fh_verify(rqstp, current_fh, S_IFREG, accmode);
  72. return status;
  73. }
  74. static __be32
  75. do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
  76. {
  77. struct svc_fh resfh;
  78. __be32 status;
  79. int created = 0;
  80. fh_init(&resfh, NFS4_FHSIZE);
  81. open->op_truncate = 0;
  82. if (open->op_create) {
  83. /*
  84. * Note: create modes (UNCHECKED,GUARDED...) are the same
  85. * in NFSv4 as in v3.
  86. */
  87. status = nfsd_create_v3(rqstp, current_fh, open->op_fname.data,
  88. open->op_fname.len, &open->op_iattr,
  89. &resfh, open->op_createmode,
  90. (u32 *)open->op_verf.data, &open->op_truncate, &created);
  91. } else {
  92. status = nfsd_lookup(rqstp, current_fh,
  93. open->op_fname.data, open->op_fname.len, &resfh);
  94. fh_unlock(current_fh);
  95. }
  96. if (status)
  97. goto out;
  98. set_change_info(&open->op_cinfo, current_fh);
  99. /* set reply cache */
  100. fh_dup2(current_fh, &resfh);
  101. open->op_stateowner->so_replay.rp_openfh_len = resfh.fh_handle.fh_size;
  102. memcpy(open->op_stateowner->so_replay.rp_openfh,
  103. &resfh.fh_handle.fh_base, resfh.fh_handle.fh_size);
  104. if (!created)
  105. status = do_open_permission(rqstp, current_fh, open, MAY_NOP);
  106. out:
  107. fh_put(&resfh);
  108. return status;
  109. }
  110. static __be32
  111. do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
  112. {
  113. __be32 status;
  114. /* Only reclaims from previously confirmed clients are valid */
  115. if ((status = nfs4_check_open_reclaim(&open->op_clientid)))
  116. return status;
  117. /* We don't know the target directory, and therefore can not
  118. * set the change info
  119. */
  120. memset(&open->op_cinfo, 0, sizeof(struct nfsd4_change_info));
  121. /* set replay cache */
  122. open->op_stateowner->so_replay.rp_openfh_len = current_fh->fh_handle.fh_size;
  123. memcpy(open->op_stateowner->so_replay.rp_openfh,
  124. &current_fh->fh_handle.fh_base,
  125. current_fh->fh_handle.fh_size);
  126. open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
  127. (open->op_iattr.ia_size == 0);
  128. status = do_open_permission(rqstp, current_fh, open, MAY_OWNER_OVERRIDE);
  129. return status;
  130. }
  131. static __be32
  132. nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  133. struct nfsd4_open *open)
  134. {
  135. __be32 status;
  136. dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n",
  137. (int)open->op_fname.len, open->op_fname.data,
  138. open->op_stateowner);
  139. /* This check required by spec. */
  140. if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
  141. return nfserr_inval;
  142. nfs4_lock_state();
  143. /* check seqid for replay. set nfs4_owner */
  144. status = nfsd4_process_open1(open);
  145. if (status == nfserr_replay_me) {
  146. struct nfs4_replay *rp = &open->op_stateowner->so_replay;
  147. fh_put(&cstate->current_fh);
  148. cstate->current_fh.fh_handle.fh_size = rp->rp_openfh_len;
  149. memcpy(&cstate->current_fh.fh_handle.fh_base, rp->rp_openfh,
  150. rp->rp_openfh_len);
  151. status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
  152. if (status)
  153. dprintk("nfsd4_open: replay failed"
  154. " restoring previous filehandle\n");
  155. else
  156. status = nfserr_replay_me;
  157. }
  158. if (status)
  159. goto out;
  160. /* Openowner is now set, so sequence id will get bumped. Now we need
  161. * these checks before we do any creates: */
  162. status = nfserr_grace;
  163. if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
  164. goto out;
  165. status = nfserr_no_grace;
  166. if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
  167. goto out;
  168. switch (open->op_claim_type) {
  169. case NFS4_OPEN_CLAIM_DELEGATE_CUR:
  170. status = nfserr_inval;
  171. if (open->op_create)
  172. goto out;
  173. /* fall through */
  174. case NFS4_OPEN_CLAIM_NULL:
  175. /*
  176. * (1) set CURRENT_FH to the file being opened,
  177. * creating it if necessary, (2) set open->op_cinfo,
  178. * (3) set open->op_truncate if the file is to be
  179. * truncated after opening, (4) do permission checking.
  180. */
  181. status = do_open_lookup(rqstp, &cstate->current_fh,
  182. open);
  183. if (status)
  184. goto out;
  185. break;
  186. case NFS4_OPEN_CLAIM_PREVIOUS:
  187. open->op_stateowner->so_confirmed = 1;
  188. /*
  189. * The CURRENT_FH is already set to the file being
  190. * opened. (1) set open->op_cinfo, (2) set
  191. * open->op_truncate if the file is to be truncated
  192. * after opening, (3) do permission checking.
  193. */
  194. status = do_open_fhandle(rqstp, &cstate->current_fh,
  195. open);
  196. if (status)
  197. goto out;
  198. break;
  199. case NFS4_OPEN_CLAIM_DELEGATE_PREV:
  200. open->op_stateowner->so_confirmed = 1;
  201. printk("NFSD: unsupported OPEN claim type %d\n",
  202. open->op_claim_type);
  203. status = nfserr_notsupp;
  204. goto out;
  205. default:
  206. printk("NFSD: Invalid OPEN claim type %d\n",
  207. open->op_claim_type);
  208. status = nfserr_inval;
  209. goto out;
  210. }
  211. /*
  212. * nfsd4_process_open2() does the actual opening of the file. If
  213. * successful, it (1) truncates the file if open->op_truncate was
  214. * set, (2) sets open->op_stateid, (3) sets open->op_delegation.
  215. */
  216. status = nfsd4_process_open2(rqstp, &cstate->current_fh, open);
  217. out:
  218. if (open->op_stateowner) {
  219. nfs4_get_stateowner(open->op_stateowner);
  220. cstate->replay_owner = open->op_stateowner;
  221. }
  222. nfs4_unlock_state();
  223. return status;
  224. }
  225. /*
  226. * filehandle-manipulating ops.
  227. */
  228. static __be32
  229. nfsd4_getfh(struct nfsd4_compound_state *cstate, struct svc_fh **getfh)
  230. {
  231. if (!cstate->current_fh.fh_dentry)
  232. return nfserr_nofilehandle;
  233. *getfh = &cstate->current_fh;
  234. return nfs_ok;
  235. }
  236. static __be32
  237. nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  238. struct nfsd4_putfh *putfh)
  239. {
  240. fh_put(&cstate->current_fh);
  241. cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
  242. memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
  243. putfh->pf_fhlen);
  244. return fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
  245. }
  246. static __be32
  247. nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate)
  248. {
  249. __be32 status;
  250. fh_put(&cstate->current_fh);
  251. status = exp_pseudoroot(rqstp->rq_client, &cstate->current_fh,
  252. &rqstp->rq_chandle);
  253. return status;
  254. }
  255. static __be32
  256. nfsd4_restorefh(struct nfsd4_compound_state *cstate)
  257. {
  258. if (!cstate->save_fh.fh_dentry)
  259. return nfserr_restorefh;
  260. fh_dup2(&cstate->current_fh, &cstate->save_fh);
  261. return nfs_ok;
  262. }
  263. static __be32
  264. nfsd4_savefh(struct nfsd4_compound_state *cstate)
  265. {
  266. if (!cstate->current_fh.fh_dentry)
  267. return nfserr_nofilehandle;
  268. fh_dup2(&cstate->save_fh, &cstate->current_fh);
  269. return nfs_ok;
  270. }
  271. /*
  272. * misc nfsv4 ops
  273. */
  274. static __be32
  275. nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  276. struct nfsd4_access *access)
  277. {
  278. if (access->ac_req_access & ~NFS3_ACCESS_FULL)
  279. return nfserr_inval;
  280. access->ac_resp_access = access->ac_req_access;
  281. return nfsd_access(rqstp, &cstate->current_fh, &access->ac_resp_access,
  282. &access->ac_supported);
  283. }
  284. static __be32
  285. nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  286. struct nfsd4_commit *commit)
  287. {
  288. __be32 status;
  289. u32 *p = (u32 *)commit->co_verf.data;
  290. *p++ = nfssvc_boot.tv_sec;
  291. *p++ = nfssvc_boot.tv_usec;
  292. status = nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
  293. commit->co_count);
  294. if (status == nfserr_symlink)
  295. status = nfserr_inval;
  296. return status;
  297. }
  298. static __be32
  299. nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  300. struct nfsd4_create *create)
  301. {
  302. struct svc_fh resfh;
  303. __be32 status;
  304. dev_t rdev;
  305. fh_init(&resfh, NFS4_FHSIZE);
  306. status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, MAY_CREATE);
  307. if (status == nfserr_symlink)
  308. status = nfserr_notdir;
  309. if (status)
  310. return status;
  311. switch (create->cr_type) {
  312. case NF4LNK:
  313. /* ugh! we have to null-terminate the linktext, or
  314. * vfs_symlink() will choke. it is always safe to
  315. * null-terminate by brute force, since at worst we
  316. * will overwrite the first byte of the create namelen
  317. * in the XDR buffer, which has already been extracted
  318. * during XDR decode.
  319. */
  320. create->cr_linkname[create->cr_linklen] = 0;
  321. status = nfsd_symlink(rqstp, &cstate->current_fh,
  322. create->cr_name, create->cr_namelen,
  323. create->cr_linkname, create->cr_linklen,
  324. &resfh, &create->cr_iattr);
  325. break;
  326. case NF4BLK:
  327. rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
  328. if (MAJOR(rdev) != create->cr_specdata1 ||
  329. MINOR(rdev) != create->cr_specdata2)
  330. return nfserr_inval;
  331. status = nfsd_create(rqstp, &cstate->current_fh,
  332. create->cr_name, create->cr_namelen,
  333. &create->cr_iattr, S_IFBLK, rdev, &resfh);
  334. break;
  335. case NF4CHR:
  336. rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
  337. if (MAJOR(rdev) != create->cr_specdata1 ||
  338. MINOR(rdev) != create->cr_specdata2)
  339. return nfserr_inval;
  340. status = nfsd_create(rqstp, &cstate->current_fh,
  341. create->cr_name, create->cr_namelen,
  342. &create->cr_iattr,S_IFCHR, rdev, &resfh);
  343. break;
  344. case NF4SOCK:
  345. status = nfsd_create(rqstp, &cstate->current_fh,
  346. create->cr_name, create->cr_namelen,
  347. &create->cr_iattr, S_IFSOCK, 0, &resfh);
  348. break;
  349. case NF4FIFO:
  350. status = nfsd_create(rqstp, &cstate->current_fh,
  351. create->cr_name, create->cr_namelen,
  352. &create->cr_iattr, S_IFIFO, 0, &resfh);
  353. break;
  354. case NF4DIR:
  355. create->cr_iattr.ia_valid &= ~ATTR_SIZE;
  356. status = nfsd_create(rqstp, &cstate->current_fh,
  357. create->cr_name, create->cr_namelen,
  358. &create->cr_iattr, S_IFDIR, 0, &resfh);
  359. break;
  360. default:
  361. status = nfserr_badtype;
  362. }
  363. if (!status) {
  364. fh_unlock(&cstate->current_fh);
  365. set_change_info(&create->cr_cinfo, &cstate->current_fh);
  366. fh_dup2(&cstate->current_fh, &resfh);
  367. }
  368. fh_put(&resfh);
  369. return status;
  370. }
  371. static __be32
  372. nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  373. struct nfsd4_getattr *getattr)
  374. {
  375. __be32 status;
  376. status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
  377. if (status)
  378. return status;
  379. if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
  380. return nfserr_inval;
  381. getattr->ga_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0;
  382. getattr->ga_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
  383. getattr->ga_fhp = &cstate->current_fh;
  384. return nfs_ok;
  385. }
  386. static __be32
  387. nfsd4_link(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  388. struct nfsd4_link *link)
  389. {
  390. __be32 status = nfserr_nofilehandle;
  391. if (!cstate->save_fh.fh_dentry)
  392. return status;
  393. status = nfsd_link(rqstp, &cstate->current_fh,
  394. link->li_name, link->li_namelen, &cstate->save_fh);
  395. if (!status)
  396. set_change_info(&link->li_cinfo, &cstate->current_fh);
  397. return status;
  398. }
  399. static __be32
  400. nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate)
  401. {
  402. struct svc_fh tmp_fh;
  403. __be32 ret;
  404. fh_init(&tmp_fh, NFS4_FHSIZE);
  405. if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh,
  406. &rqstp->rq_chandle)) != 0)
  407. return ret;
  408. if (tmp_fh.fh_dentry == cstate->current_fh.fh_dentry) {
  409. fh_put(&tmp_fh);
  410. return nfserr_noent;
  411. }
  412. fh_put(&tmp_fh);
  413. return nfsd_lookup(rqstp, &cstate->current_fh,
  414. "..", 2, &cstate->current_fh);
  415. }
  416. static __be32
  417. nfsd4_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  418. struct nfsd4_lookup *lookup)
  419. {
  420. return nfsd_lookup(rqstp, &cstate->current_fh,
  421. lookup->lo_name, lookup->lo_len,
  422. &cstate->current_fh);
  423. }
  424. static __be32
  425. nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  426. struct nfsd4_read *read)
  427. {
  428. __be32 status;
  429. /* no need to check permission - this will be done in nfsd_read() */
  430. read->rd_filp = NULL;
  431. if (read->rd_offset >= OFFSET_MAX)
  432. return nfserr_inval;
  433. nfs4_lock_state();
  434. /* check stateid */
  435. if ((status = nfs4_preprocess_stateid_op(&cstate->current_fh,
  436. &read->rd_stateid,
  437. CHECK_FH | RD_STATE, &read->rd_filp))) {
  438. dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
  439. goto out;
  440. }
  441. if (read->rd_filp)
  442. get_file(read->rd_filp);
  443. status = nfs_ok;
  444. out:
  445. nfs4_unlock_state();
  446. read->rd_rqstp = rqstp;
  447. read->rd_fhp = &cstate->current_fh;
  448. return status;
  449. }
  450. static __be32
  451. nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  452. struct nfsd4_readdir *readdir)
  453. {
  454. u64 cookie = readdir->rd_cookie;
  455. static const nfs4_verifier zeroverf;
  456. /* no need to check permission - this will be done in nfsd_readdir() */
  457. if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
  458. return nfserr_inval;
  459. readdir->rd_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0;
  460. readdir->rd_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
  461. if ((cookie > ~(u32)0) || (cookie == 1) || (cookie == 2) ||
  462. (cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE)))
  463. return nfserr_bad_cookie;
  464. readdir->rd_rqstp = rqstp;
  465. readdir->rd_fhp = &cstate->current_fh;
  466. return nfs_ok;
  467. }
  468. static __be32
  469. nfsd4_readlink(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  470. struct nfsd4_readlink *readlink)
  471. {
  472. readlink->rl_rqstp = rqstp;
  473. readlink->rl_fhp = &cstate->current_fh;
  474. return nfs_ok;
  475. }
  476. static __be32
  477. nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  478. struct nfsd4_remove *remove)
  479. {
  480. __be32 status;
  481. if (nfs4_in_grace())
  482. return nfserr_grace;
  483. status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
  484. remove->rm_name, remove->rm_namelen);
  485. if (status == nfserr_symlink)
  486. return nfserr_notdir;
  487. if (!status) {
  488. fh_unlock(&cstate->current_fh);
  489. set_change_info(&remove->rm_cinfo, &cstate->current_fh);
  490. }
  491. return status;
  492. }
  493. static __be32
  494. nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  495. struct nfsd4_rename *rename)
  496. {
  497. __be32 status = nfserr_nofilehandle;
  498. if (!cstate->save_fh.fh_dentry)
  499. return status;
  500. if (nfs4_in_grace() && !(cstate->save_fh.fh_export->ex_flags
  501. & NFSEXP_NOSUBTREECHECK))
  502. return nfserr_grace;
  503. status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
  504. rename->rn_snamelen, &cstate->current_fh,
  505. rename->rn_tname, rename->rn_tnamelen);
  506. /* the underlying filesystem returns different error's than required
  507. * by NFSv4. both save_fh and current_fh have been verified.. */
  508. if (status == nfserr_isdir)
  509. status = nfserr_exist;
  510. else if ((status == nfserr_notdir) &&
  511. (S_ISDIR(cstate->save_fh.fh_dentry->d_inode->i_mode) &&
  512. S_ISDIR(cstate->current_fh.fh_dentry->d_inode->i_mode)))
  513. status = nfserr_exist;
  514. else if (status == nfserr_symlink)
  515. status = nfserr_notdir;
  516. if (!status) {
  517. set_change_info(&rename->rn_sinfo, &cstate->current_fh);
  518. set_change_info(&rename->rn_tinfo, &cstate->save_fh);
  519. }
  520. return status;
  521. }
  522. static __be32
  523. nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  524. struct nfsd4_setattr *setattr)
  525. {
  526. __be32 status = nfs_ok;
  527. if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
  528. nfs4_lock_state();
  529. status = nfs4_preprocess_stateid_op(&cstate->current_fh,
  530. &setattr->sa_stateid, CHECK_FH | WR_STATE, NULL);
  531. nfs4_unlock_state();
  532. if (status) {
  533. dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
  534. return status;
  535. }
  536. }
  537. status = nfs_ok;
  538. if (setattr->sa_acl != NULL)
  539. status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,
  540. setattr->sa_acl);
  541. if (status)
  542. return status;
  543. status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
  544. 0, (time_t)0);
  545. return status;
  546. }
  547. static __be32
  548. nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  549. struct nfsd4_write *write)
  550. {
  551. stateid_t *stateid = &write->wr_stateid;
  552. struct file *filp = NULL;
  553. u32 *p;
  554. __be32 status = nfs_ok;
  555. /* no need to check permission - this will be done in nfsd_write() */
  556. if (write->wr_offset >= OFFSET_MAX)
  557. return nfserr_inval;
  558. nfs4_lock_state();
  559. status = nfs4_preprocess_stateid_op(&cstate->current_fh, stateid,
  560. CHECK_FH | WR_STATE, &filp);
  561. if (filp)
  562. get_file(filp);
  563. nfs4_unlock_state();
  564. if (status) {
  565. dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
  566. return status;
  567. }
  568. write->wr_bytes_written = write->wr_buflen;
  569. write->wr_how_written = write->wr_stable_how;
  570. p = (u32 *)write->wr_verifier.data;
  571. *p++ = nfssvc_boot.tv_sec;
  572. *p++ = nfssvc_boot.tv_usec;
  573. status = nfsd_write(rqstp, &cstate->current_fh, filp,
  574. write->wr_offset, rqstp->rq_vec, write->wr_vlen,
  575. write->wr_buflen, &write->wr_how_written);
  576. if (filp)
  577. fput(filp);
  578. if (status == nfserr_symlink)
  579. status = nfserr_inval;
  580. return status;
  581. }
  582. /* This routine never returns NFS_OK! If there are no other errors, it
  583. * will return NFSERR_SAME or NFSERR_NOT_SAME depending on whether the
  584. * attributes matched. VERIFY is implemented by mapping NFSERR_SAME
  585. * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK.
  586. */
  587. static __be32
  588. nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  589. struct nfsd4_verify *verify)
  590. {
  591. __be32 *buf, *p;
  592. int count;
  593. __be32 status;
  594. status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
  595. if (status)
  596. return status;
  597. if ((verify->ve_bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0)
  598. || (verify->ve_bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1))
  599. return nfserr_attrnotsupp;
  600. if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)
  601. || (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1))
  602. return nfserr_inval;
  603. if (verify->ve_attrlen & 3)
  604. return nfserr_inval;
  605. /* count in words:
  606. * bitmap_len(1) + bitmap(2) + attr_len(1) = 4
  607. */
  608. count = 4 + (verify->ve_attrlen >> 2);
  609. buf = kmalloc(count << 2, GFP_KERNEL);
  610. if (!buf)
  611. return nfserr_resource;
  612. status = nfsd4_encode_fattr(&cstate->current_fh,
  613. cstate->current_fh.fh_export,
  614. cstate->current_fh.fh_dentry, buf,
  615. &count, verify->ve_bmval,
  616. rqstp);
  617. /* this means that nfsd4_encode_fattr() ran out of space */
  618. if (status == nfserr_resource && count == 0)
  619. status = nfserr_not_same;
  620. if (status)
  621. goto out_kfree;
  622. p = buf + 3;
  623. status = nfserr_not_same;
  624. if (ntohl(*p++) != verify->ve_attrlen)
  625. goto out_kfree;
  626. if (!memcmp(p, verify->ve_attrval, verify->ve_attrlen))
  627. status = nfserr_same;
  628. out_kfree:
  629. kfree(buf);
  630. return status;
  631. }
  632. /*
  633. * NULL call.
  634. */
  635. static __be32
  636. nfsd4_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
  637. {
  638. return nfs_ok;
  639. }
  640. static inline void nfsd4_increment_op_stats(u32 opnum)
  641. {
  642. if (opnum >= FIRST_NFS4_OP && opnum <= LAST_NFS4_OP)
  643. nfsdstats.nfs4_opcount[opnum]++;
  644. }
  645. static void cstate_free(struct nfsd4_compound_state *cstate)
  646. {
  647. if (cstate == NULL)
  648. return;
  649. fh_put(&cstate->current_fh);
  650. fh_put(&cstate->save_fh);
  651. BUG_ON(cstate->replay_owner);
  652. kfree(cstate);
  653. }
  654. static struct nfsd4_compound_state *cstate_alloc(void)
  655. {
  656. struct nfsd4_compound_state *cstate;
  657. cstate = kmalloc(sizeof(struct nfsd4_compound_state), GFP_KERNEL);
  658. if (cstate == NULL)
  659. return NULL;
  660. fh_init(&cstate->current_fh, NFS4_FHSIZE);
  661. fh_init(&cstate->save_fh, NFS4_FHSIZE);
  662. cstate->replay_owner = NULL;
  663. return cstate;
  664. }
  665. /*
  666. * COMPOUND call.
  667. */
  668. static __be32
  669. nfsd4_proc_compound(struct svc_rqst *rqstp,
  670. struct nfsd4_compoundargs *args,
  671. struct nfsd4_compoundres *resp)
  672. {
  673. struct nfsd4_op *op;
  674. struct nfsd4_compound_state *cstate = NULL;
  675. int slack_bytes;
  676. __be32 status;
  677. status = nfserr_resource;
  678. cstate = cstate_alloc();
  679. if (cstate == NULL)
  680. goto out;
  681. resp->xbuf = &rqstp->rq_res;
  682. resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len;
  683. resp->tagp = resp->p;
  684. /* reserve space for: taglen, tag, and opcnt */
  685. resp->p += 2 + XDR_QUADLEN(args->taglen);
  686. resp->end = rqstp->rq_res.head[0].iov_base + PAGE_SIZE;
  687. resp->taglen = args->taglen;
  688. resp->tag = args->tag;
  689. resp->opcnt = 0;
  690. resp->rqstp = rqstp;
  691. /*
  692. * According to RFC3010, this takes precedence over all other errors.
  693. */
  694. status = nfserr_minor_vers_mismatch;
  695. if (args->minorversion > NFSD_SUPPORTED_MINOR_VERSION)
  696. goto out;
  697. status = nfs_ok;
  698. while (!status && resp->opcnt < args->opcnt) {
  699. op = &args->ops[resp->opcnt++];
  700. dprintk("nfsv4 compound op #%d: %d\n", resp->opcnt, op->opnum);
  701. /*
  702. * The XDR decode routines may have pre-set op->status;
  703. * for example, if there is a miscellaneous XDR error
  704. * it will be set to nfserr_bad_xdr.
  705. */
  706. if (op->status)
  707. goto encode_op;
  708. /* We must be able to encode a successful response to
  709. * this operation, with enough room left over to encode a
  710. * failed response to the next operation. If we don't
  711. * have enough room, fail with ERR_RESOURCE.
  712. */
  713. slack_bytes = (char *)resp->end - (char *)resp->p;
  714. if (slack_bytes < COMPOUND_SLACK_SPACE
  715. + COMPOUND_ERR_SLACK_SPACE) {
  716. BUG_ON(slack_bytes < COMPOUND_ERR_SLACK_SPACE);
  717. op->status = nfserr_resource;
  718. goto encode_op;
  719. }
  720. /* All operations except RENEW, SETCLIENTID, RESTOREFH
  721. * SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
  722. * require a valid current filehandle
  723. */
  724. if (!cstate->current_fh.fh_dentry) {
  725. if (!((op->opnum == OP_PUTFH) ||
  726. (op->opnum == OP_PUTROOTFH) ||
  727. (op->opnum == OP_SETCLIENTID) ||
  728. (op->opnum == OP_SETCLIENTID_CONFIRM) ||
  729. (op->opnum == OP_RENEW) ||
  730. (op->opnum == OP_RESTOREFH) ||
  731. (op->opnum == OP_RELEASE_LOCKOWNER))) {
  732. op->status = nfserr_nofilehandle;
  733. goto encode_op;
  734. }
  735. }
  736. /* Check must be done at start of each operation, except
  737. * for GETATTR and ops not listed as returning NFS4ERR_MOVED
  738. */
  739. else if (cstate->current_fh.fh_export->ex_fslocs.migrated &&
  740. !((op->opnum == OP_GETATTR) ||
  741. (op->opnum == OP_PUTROOTFH) ||
  742. (op->opnum == OP_PUTPUBFH) ||
  743. (op->opnum == OP_RENEW) ||
  744. (op->opnum == OP_SETCLIENTID) ||
  745. (op->opnum == OP_RELEASE_LOCKOWNER))) {
  746. op->status = nfserr_moved;
  747. goto encode_op;
  748. }
  749. switch (op->opnum) {
  750. case OP_ACCESS:
  751. op->status = nfsd4_access(rqstp, cstate,
  752. &op->u.access);
  753. break;
  754. case OP_CLOSE:
  755. op->status = nfsd4_close(rqstp, cstate,
  756. &op->u.close);
  757. break;
  758. case OP_COMMIT:
  759. op->status = nfsd4_commit(rqstp, cstate,
  760. &op->u.commit);
  761. break;
  762. case OP_CREATE:
  763. op->status = nfsd4_create(rqstp, cstate,
  764. &op->u.create);
  765. break;
  766. case OP_DELEGRETURN:
  767. op->status = nfsd4_delegreturn(rqstp, cstate,
  768. &op->u.delegreturn);
  769. break;
  770. case OP_GETATTR:
  771. op->status = nfsd4_getattr(rqstp, cstate,
  772. &op->u.getattr);
  773. break;
  774. case OP_GETFH:
  775. op->status = nfsd4_getfh(cstate, &op->u.getfh);
  776. break;
  777. case OP_LINK:
  778. op->status = nfsd4_link(rqstp, cstate, &op->u.link);
  779. break;
  780. case OP_LOCK:
  781. op->status = nfsd4_lock(rqstp, cstate, &op->u.lock);
  782. break;
  783. case OP_LOCKT:
  784. op->status = nfsd4_lockt(rqstp, cstate, &op->u.lockt);
  785. break;
  786. case OP_LOCKU:
  787. op->status = nfsd4_locku(rqstp, cstate, &op->u.locku);
  788. break;
  789. case OP_LOOKUP:
  790. op->status = nfsd4_lookup(rqstp, cstate,
  791. &op->u.lookup);
  792. break;
  793. case OP_LOOKUPP:
  794. op->status = nfsd4_lookupp(rqstp, cstate);
  795. break;
  796. case OP_NVERIFY:
  797. op->status = nfsd4_verify(rqstp, cstate,
  798. &op->u.nverify);
  799. if (op->status == nfserr_not_same)
  800. op->status = nfs_ok;
  801. break;
  802. case OP_OPEN:
  803. op->status = nfsd4_open(rqstp, cstate,
  804. &op->u.open);
  805. break;
  806. case OP_OPEN_CONFIRM:
  807. op->status = nfsd4_open_confirm(rqstp, cstate,
  808. &op->u.open_confirm);
  809. break;
  810. case OP_OPEN_DOWNGRADE:
  811. op->status = nfsd4_open_downgrade(rqstp, cstate,
  812. &op->u.open_downgrade);
  813. break;
  814. case OP_PUTFH:
  815. op->status = nfsd4_putfh(rqstp, cstate, &op->u.putfh);
  816. break;
  817. case OP_PUTROOTFH:
  818. op->status = nfsd4_putrootfh(rqstp, cstate);
  819. break;
  820. case OP_READ:
  821. op->status = nfsd4_read(rqstp, cstate, &op->u.read);
  822. break;
  823. case OP_READDIR:
  824. op->status = nfsd4_readdir(rqstp, cstate,
  825. &op->u.readdir);
  826. break;
  827. case OP_READLINK:
  828. op->status = nfsd4_readlink(rqstp, cstate,
  829. &op->u.readlink);
  830. break;
  831. case OP_REMOVE:
  832. op->status = nfsd4_remove(rqstp, cstate,
  833. &op->u.remove);
  834. break;
  835. case OP_RENAME:
  836. op->status = nfsd4_rename(rqstp, cstate,
  837. &op->u.rename);
  838. break;
  839. case OP_RENEW:
  840. op->status = nfsd4_renew(&op->u.renew);
  841. break;
  842. case OP_RESTOREFH:
  843. op->status = nfsd4_restorefh(cstate);
  844. break;
  845. case OP_SAVEFH:
  846. op->status = nfsd4_savefh(cstate);
  847. break;
  848. case OP_SETATTR:
  849. op->status = nfsd4_setattr(rqstp, cstate,
  850. &op->u.setattr);
  851. break;
  852. case OP_SETCLIENTID:
  853. op->status = nfsd4_setclientid(rqstp, &op->u.setclientid);
  854. break;
  855. case OP_SETCLIENTID_CONFIRM:
  856. op->status = nfsd4_setclientid_confirm(rqstp, &op->u.setclientid_confirm);
  857. break;
  858. case OP_VERIFY:
  859. op->status = nfsd4_verify(rqstp, cstate,
  860. &op->u.verify);
  861. if (op->status == nfserr_same)
  862. op->status = nfs_ok;
  863. break;
  864. case OP_WRITE:
  865. op->status = nfsd4_write(rqstp, cstate, &op->u.write);
  866. break;
  867. case OP_RELEASE_LOCKOWNER:
  868. op->status = nfsd4_release_lockowner(rqstp, &op->u.release_lockowner);
  869. break;
  870. default:
  871. BUG_ON(op->status == nfs_ok);
  872. break;
  873. }
  874. encode_op:
  875. if (op->status == nfserr_replay_me) {
  876. op->replay = &cstate->replay_owner->so_replay;
  877. nfsd4_encode_replay(resp, op);
  878. status = op->status = op->replay->rp_status;
  879. } else {
  880. nfsd4_encode_operation(resp, op);
  881. status = op->status;
  882. }
  883. if (cstate->replay_owner) {
  884. nfs4_put_stateowner(cstate->replay_owner);
  885. cstate->replay_owner = NULL;
  886. }
  887. /* XXX Ugh, we need to get rid of this kind of special case: */
  888. if (op->opnum == OP_READ && op->u.read.rd_filp)
  889. fput(op->u.read.rd_filp);
  890. nfsd4_increment_op_stats(op->opnum);
  891. }
  892. out:
  893. nfsd4_release_compoundargs(args);
  894. cstate_free(cstate);
  895. return status;
  896. }
  897. #define nfs4svc_decode_voidargs NULL
  898. #define nfs4svc_release_void NULL
  899. #define nfsd4_voidres nfsd4_voidargs
  900. #define nfs4svc_release_compound NULL
  901. struct nfsd4_voidargs { int dummy; };
  902. #define PROC(name, argt, rest, relt, cache, respsize) \
  903. { (svc_procfunc) nfsd4_proc_##name, \
  904. (kxdrproc_t) nfs4svc_decode_##argt##args, \
  905. (kxdrproc_t) nfs4svc_encode_##rest##res, \
  906. (kxdrproc_t) nfs4svc_release_##relt, \
  907. sizeof(struct nfsd4_##argt##args), \
  908. sizeof(struct nfsd4_##rest##res), \
  909. 0, \
  910. cache, \
  911. respsize, \
  912. }
  913. /*
  914. * TODO: At the present time, the NFSv4 server does not do XID caching
  915. * of requests. Implementing XID caching would not be a serious problem,
  916. * although it would require a mild change in interfaces since one
  917. * doesn't know whether an NFSv4 request is idempotent until after the
  918. * XDR decode. However, XID caching totally confuses pynfs (Peter
  919. * Astrand's regression testsuite for NFSv4 servers), which reuses
  920. * XID's liberally, so I've left it unimplemented until pynfs generates
  921. * better XID's.
  922. */
  923. static struct svc_procedure nfsd_procedures4[2] = {
  924. PROC(null, void, void, void, RC_NOCACHE, 1),
  925. PROC(compound, compound, compound, compound, RC_NOCACHE, NFSD_BUFSIZE/4)
  926. };
  927. struct svc_version nfsd_version4 = {
  928. .vs_vers = 4,
  929. .vs_nproc = 2,
  930. .vs_proc = nfsd_procedures4,
  931. .vs_dispatch = nfsd_dispatch,
  932. .vs_xdrsize = NFS4_SVC_XDRSIZE,
  933. };
  934. /*
  935. * Local variables:
  936. * c-basic-offset: 8
  937. * End:
  938. */