nfs4proc.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351
  1. /*
  2. * Server-side procedures for NFSv4.
  3. *
  4. * Copyright (c) 2002 The Regents of the University of Michigan.
  5. * All rights reserved.
  6. *
  7. * Kendrick Smith <kmsmith@umich.edu>
  8. * Andy Adamson <andros@umich.edu>
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. *
  14. * 1. Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. * 2. Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in the
  18. * documentation and/or other materials provided with the distribution.
  19. * 3. Neither the name of the University nor the names of its
  20. * contributors may be used to endorse or promote products derived
  21. * from this software without specific prior written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  24. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  25. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  26. * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  27. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  28. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  29. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  30. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  31. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  32. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  33. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34. */
  35. #include <linux/file.h>
  36. #include "cache.h"
  37. #include "xdr4.h"
  38. #include "vfs.h"
  39. #define NFSDDBG_FACILITY NFSDDBG_PROC
  40. static u32 nfsd_attrmask[] = {
  41. NFSD_WRITEABLE_ATTRS_WORD0,
  42. NFSD_WRITEABLE_ATTRS_WORD1,
  43. NFSD_WRITEABLE_ATTRS_WORD2
  44. };
  45. static u32 nfsd41_ex_attrmask[] = {
  46. NFSD_SUPPATTR_EXCLCREAT_WORD0,
  47. NFSD_SUPPATTR_EXCLCREAT_WORD1,
  48. NFSD_SUPPATTR_EXCLCREAT_WORD2
  49. };
  50. static __be32
  51. check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  52. u32 *bmval, u32 *writable)
  53. {
  54. struct dentry *dentry = cstate->current_fh.fh_dentry;
  55. /*
  56. * Check about attributes are supported by the NFSv4 server or not.
  57. * According to spec, unsupported attributes return ERR_ATTRNOTSUPP.
  58. */
  59. if ((bmval[0] & ~nfsd_suppattrs0(cstate->minorversion)) ||
  60. (bmval[1] & ~nfsd_suppattrs1(cstate->minorversion)) ||
  61. (bmval[2] & ~nfsd_suppattrs2(cstate->minorversion)))
  62. return nfserr_attrnotsupp;
  63. /*
  64. * Check FATTR4_WORD0_ACL can be supported
  65. * in current environment or not.
  66. */
  67. if (bmval[0] & FATTR4_WORD0_ACL) {
  68. if (!IS_POSIXACL(dentry->d_inode))
  69. return nfserr_attrnotsupp;
  70. }
  71. /*
  72. * According to spec, read-only attributes return ERR_INVAL.
  73. */
  74. if (writable) {
  75. if ((bmval[0] & ~writable[0]) || (bmval[1] & ~writable[1]) ||
  76. (bmval[2] & ~writable[2]))
  77. return nfserr_inval;
  78. }
  79. return nfs_ok;
  80. }
  81. static __be32
  82. nfsd4_check_open_attributes(struct svc_rqst *rqstp,
  83. struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
  84. {
  85. __be32 status = nfs_ok;
  86. if (open->op_create == NFS4_OPEN_CREATE) {
  87. if (open->op_createmode == NFS4_CREATE_UNCHECKED
  88. || open->op_createmode == NFS4_CREATE_GUARDED)
  89. status = check_attr_support(rqstp, cstate,
  90. open->op_bmval, nfsd_attrmask);
  91. else if (open->op_createmode == NFS4_CREATE_EXCLUSIVE4_1)
  92. status = check_attr_support(rqstp, cstate,
  93. open->op_bmval, nfsd41_ex_attrmask);
  94. }
  95. return status;
  96. }
  97. static int
  98. is_create_with_attrs(struct nfsd4_open *open)
  99. {
  100. return open->op_create == NFS4_OPEN_CREATE
  101. && (open->op_createmode == NFS4_CREATE_UNCHECKED
  102. || open->op_createmode == NFS4_CREATE_GUARDED
  103. || open->op_createmode == NFS4_CREATE_EXCLUSIVE4_1);
  104. }
  105. /*
  106. * if error occurs when setting the acl, just clear the acl bit
  107. * in the returned attr bitmap.
  108. */
  109. static void
  110. do_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
  111. struct nfs4_acl *acl, u32 *bmval)
  112. {
  113. __be32 status;
  114. status = nfsd4_set_nfs4_acl(rqstp, fhp, acl);
  115. if (status)
  116. /*
  117. * We should probably fail the whole open at this point,
  118. * but we've already created the file, so it's too late;
  119. * So this seems the least of evils:
  120. */
  121. bmval[0] &= ~FATTR4_WORD0_ACL;
  122. }
  123. static inline void
  124. fh_dup2(struct svc_fh *dst, struct svc_fh *src)
  125. {
  126. fh_put(dst);
  127. dget(src->fh_dentry);
  128. if (src->fh_export)
  129. cache_get(&src->fh_export->h);
  130. *dst = *src;
  131. }
  132. static __be32
  133. do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, int accmode)
  134. {
  135. __be32 status;
  136. if (open->op_truncate &&
  137. !(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
  138. return nfserr_inval;
  139. if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
  140. accmode |= NFSD_MAY_READ;
  141. if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
  142. accmode |= (NFSD_MAY_WRITE | NFSD_MAY_TRUNC);
  143. if (open->op_share_deny & NFS4_SHARE_DENY_READ)
  144. accmode |= NFSD_MAY_WRITE;
  145. status = fh_verify(rqstp, current_fh, S_IFREG, accmode);
  146. return status;
  147. }
  148. static __be32
  149. do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
  150. {
  151. struct svc_fh resfh;
  152. __be32 status;
  153. int created = 0;
  154. fh_init(&resfh, NFS4_FHSIZE);
  155. open->op_truncate = 0;
  156. if (open->op_create) {
  157. /* FIXME: check session persistence and pnfs flags.
  158. * The nfsv4.1 spec requires the following semantics:
  159. *
  160. * Persistent | pNFS | Server REQUIRED | Client Allowed
  161. * Reply Cache | server | |
  162. * -------------+--------+-----------------+--------------------
  163. * no | no | EXCLUSIVE4_1 | EXCLUSIVE4_1
  164. * | | | (SHOULD)
  165. * | | and EXCLUSIVE4 | or EXCLUSIVE4
  166. * | | | (SHOULD NOT)
  167. * no | yes | EXCLUSIVE4_1 | EXCLUSIVE4_1
  168. * yes | no | GUARDED4 | GUARDED4
  169. * yes | yes | GUARDED4 | GUARDED4
  170. */
  171. /*
  172. * Note: create modes (UNCHECKED,GUARDED...) are the same
  173. * in NFSv4 as in v3.
  174. */
  175. status = nfsd_create_v3(rqstp, current_fh, open->op_fname.data,
  176. open->op_fname.len, &open->op_iattr,
  177. &resfh, open->op_createmode,
  178. (u32 *)open->op_verf.data,
  179. &open->op_truncate, &created);
  180. /*
  181. * Following rfc 3530 14.2.16, use the returned bitmask
  182. * to indicate which attributes we used to store the
  183. * verifier:
  184. */
  185. if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0)
  186. open->op_bmval[1] = (FATTR4_WORD1_TIME_ACCESS |
  187. FATTR4_WORD1_TIME_MODIFY);
  188. } else {
  189. status = nfsd_lookup(rqstp, current_fh,
  190. open->op_fname.data, open->op_fname.len, &resfh);
  191. fh_unlock(current_fh);
  192. }
  193. if (status)
  194. goto out;
  195. if (is_create_with_attrs(open) && open->op_acl != NULL)
  196. do_set_nfs4_acl(rqstp, &resfh, open->op_acl, open->op_bmval);
  197. set_change_info(&open->op_cinfo, current_fh);
  198. fh_dup2(current_fh, &resfh);
  199. /* set reply cache */
  200. fh_copy_shallow(&open->op_stateowner->so_replay.rp_openfh,
  201. &resfh.fh_handle);
  202. if (!created)
  203. status = do_open_permission(rqstp, current_fh, open,
  204. NFSD_MAY_NOP);
  205. out:
  206. fh_put(&resfh);
  207. return status;
  208. }
  209. static __be32
  210. do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
  211. {
  212. __be32 status;
  213. /* Only reclaims from previously confirmed clients are valid */
  214. if ((status = nfs4_check_open_reclaim(&open->op_clientid)))
  215. return status;
  216. /* We don't know the target directory, and therefore can not
  217. * set the change info
  218. */
  219. memset(&open->op_cinfo, 0, sizeof(struct nfsd4_change_info));
  220. /* set replay cache */
  221. fh_copy_shallow(&open->op_stateowner->so_replay.rp_openfh,
  222. &current_fh->fh_handle);
  223. open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
  224. (open->op_iattr.ia_size == 0);
  225. status = do_open_permission(rqstp, current_fh, open,
  226. NFSD_MAY_OWNER_OVERRIDE);
  227. return status;
  228. }
  229. static void
  230. copy_clientid(clientid_t *clid, struct nfsd4_session *session)
  231. {
  232. struct nfsd4_sessionid *sid =
  233. (struct nfsd4_sessionid *)session->se_sessionid.data;
  234. clid->cl_boot = sid->clientid.cl_boot;
  235. clid->cl_id = sid->clientid.cl_id;
  236. }
  237. static __be32
  238. nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  239. struct nfsd4_open *open)
  240. {
  241. __be32 status;
  242. struct nfsd4_compoundres *resp;
  243. dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n",
  244. (int)open->op_fname.len, open->op_fname.data,
  245. open->op_stateowner);
  246. /* This check required by spec. */
  247. if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
  248. return nfserr_inval;
  249. if (nfsd4_has_session(cstate))
  250. copy_clientid(&open->op_clientid, cstate->session);
  251. nfs4_lock_state();
  252. /* check seqid for replay. set nfs4_owner */
  253. resp = rqstp->rq_resp;
  254. status = nfsd4_process_open1(&resp->cstate, open);
  255. if (status == nfserr_replay_me) {
  256. struct nfs4_replay *rp = &open->op_stateowner->so_replay;
  257. fh_put(&cstate->current_fh);
  258. fh_copy_shallow(&cstate->current_fh.fh_handle,
  259. &rp->rp_openfh);
  260. status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
  261. if (status)
  262. dprintk("nfsd4_open: replay failed"
  263. " restoring previous filehandle\n");
  264. else
  265. status = nfserr_replay_me;
  266. }
  267. if (status)
  268. goto out;
  269. status = nfsd4_check_open_attributes(rqstp, cstate, open);
  270. if (status)
  271. goto out;
  272. /* Openowner is now set, so sequence id will get bumped. Now we need
  273. * these checks before we do any creates: */
  274. status = nfserr_grace;
  275. if (locks_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
  276. goto out;
  277. status = nfserr_no_grace;
  278. if (!locks_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
  279. goto out;
  280. switch (open->op_claim_type) {
  281. case NFS4_OPEN_CLAIM_DELEGATE_CUR:
  282. case NFS4_OPEN_CLAIM_NULL:
  283. /*
  284. * (1) set CURRENT_FH to the file being opened,
  285. * creating it if necessary, (2) set open->op_cinfo,
  286. * (3) set open->op_truncate if the file is to be
  287. * truncated after opening, (4) do permission checking.
  288. */
  289. status = do_open_lookup(rqstp, &cstate->current_fh,
  290. open);
  291. if (status)
  292. goto out;
  293. break;
  294. case NFS4_OPEN_CLAIM_PREVIOUS:
  295. open->op_stateowner->so_confirmed = 1;
  296. /*
  297. * The CURRENT_FH is already set to the file being
  298. * opened. (1) set open->op_cinfo, (2) set
  299. * open->op_truncate if the file is to be truncated
  300. * after opening, (3) do permission checking.
  301. */
  302. status = do_open_fhandle(rqstp, &cstate->current_fh,
  303. open);
  304. if (status)
  305. goto out;
  306. break;
  307. case NFS4_OPEN_CLAIM_DELEGATE_PREV:
  308. open->op_stateowner->so_confirmed = 1;
  309. dprintk("NFSD: unsupported OPEN claim type %d\n",
  310. open->op_claim_type);
  311. status = nfserr_notsupp;
  312. goto out;
  313. default:
  314. dprintk("NFSD: Invalid OPEN claim type %d\n",
  315. open->op_claim_type);
  316. status = nfserr_inval;
  317. goto out;
  318. }
  319. /*
  320. * nfsd4_process_open2() does the actual opening of the file. If
  321. * successful, it (1) truncates the file if open->op_truncate was
  322. * set, (2) sets open->op_stateid, (3) sets open->op_delegation.
  323. */
  324. status = nfsd4_process_open2(rqstp, &cstate->current_fh, open);
  325. out:
  326. if (open->op_stateowner) {
  327. nfs4_get_stateowner(open->op_stateowner);
  328. cstate->replay_owner = open->op_stateowner;
  329. }
  330. nfs4_unlock_state();
  331. return status;
  332. }
  333. /*
  334. * filehandle-manipulating ops.
  335. */
  336. static __be32
  337. nfsd4_getfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  338. struct svc_fh **getfh)
  339. {
  340. if (!cstate->current_fh.fh_dentry)
  341. return nfserr_nofilehandle;
  342. *getfh = &cstate->current_fh;
  343. return nfs_ok;
  344. }
  345. static __be32
  346. nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  347. struct nfsd4_putfh *putfh)
  348. {
  349. fh_put(&cstate->current_fh);
  350. cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
  351. memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
  352. putfh->pf_fhlen);
  353. return fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
  354. }
  355. static __be32
  356. nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  357. void *arg)
  358. {
  359. __be32 status;
  360. fh_put(&cstate->current_fh);
  361. status = exp_pseudoroot(rqstp, &cstate->current_fh);
  362. return status;
  363. }
  364. static __be32
  365. nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  366. void *arg)
  367. {
  368. if (!cstate->save_fh.fh_dentry)
  369. return nfserr_restorefh;
  370. fh_dup2(&cstate->current_fh, &cstate->save_fh);
  371. return nfs_ok;
  372. }
  373. static __be32
  374. nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  375. void *arg)
  376. {
  377. if (!cstate->current_fh.fh_dentry)
  378. return nfserr_nofilehandle;
  379. fh_dup2(&cstate->save_fh, &cstate->current_fh);
  380. return nfs_ok;
  381. }
  382. /*
  383. * misc nfsv4 ops
  384. */
  385. static __be32
  386. nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  387. struct nfsd4_access *access)
  388. {
  389. if (access->ac_req_access & ~NFS3_ACCESS_FULL)
  390. return nfserr_inval;
  391. access->ac_resp_access = access->ac_req_access;
  392. return nfsd_access(rqstp, &cstate->current_fh, &access->ac_resp_access,
  393. &access->ac_supported);
  394. }
  395. static __be32
  396. nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  397. struct nfsd4_commit *commit)
  398. {
  399. __be32 status;
  400. u32 *p = (u32 *)commit->co_verf.data;
  401. *p++ = nfssvc_boot.tv_sec;
  402. *p++ = nfssvc_boot.tv_usec;
  403. status = nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
  404. commit->co_count);
  405. if (status == nfserr_symlink)
  406. status = nfserr_inval;
  407. return status;
  408. }
  409. static __be32
  410. nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  411. struct nfsd4_create *create)
  412. {
  413. struct svc_fh resfh;
  414. __be32 status;
  415. dev_t rdev;
  416. fh_init(&resfh, NFS4_FHSIZE);
  417. status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR,
  418. NFSD_MAY_CREATE);
  419. if (status == nfserr_symlink)
  420. status = nfserr_notdir;
  421. if (status)
  422. return status;
  423. status = check_attr_support(rqstp, cstate, create->cr_bmval,
  424. nfsd_attrmask);
  425. if (status)
  426. return status;
  427. switch (create->cr_type) {
  428. case NF4LNK:
  429. /* ugh! we have to null-terminate the linktext, or
  430. * vfs_symlink() will choke. it is always safe to
  431. * null-terminate by brute force, since at worst we
  432. * will overwrite the first byte of the create namelen
  433. * in the XDR buffer, which has already been extracted
  434. * during XDR decode.
  435. */
  436. create->cr_linkname[create->cr_linklen] = 0;
  437. status = nfsd_symlink(rqstp, &cstate->current_fh,
  438. create->cr_name, create->cr_namelen,
  439. create->cr_linkname, create->cr_linklen,
  440. &resfh, &create->cr_iattr);
  441. break;
  442. case NF4BLK:
  443. rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
  444. if (MAJOR(rdev) != create->cr_specdata1 ||
  445. MINOR(rdev) != create->cr_specdata2)
  446. return nfserr_inval;
  447. status = nfsd_create(rqstp, &cstate->current_fh,
  448. create->cr_name, create->cr_namelen,
  449. &create->cr_iattr, S_IFBLK, rdev, &resfh);
  450. break;
  451. case NF4CHR:
  452. rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
  453. if (MAJOR(rdev) != create->cr_specdata1 ||
  454. MINOR(rdev) != create->cr_specdata2)
  455. return nfserr_inval;
  456. status = nfsd_create(rqstp, &cstate->current_fh,
  457. create->cr_name, create->cr_namelen,
  458. &create->cr_iattr,S_IFCHR, rdev, &resfh);
  459. break;
  460. case NF4SOCK:
  461. status = nfsd_create(rqstp, &cstate->current_fh,
  462. create->cr_name, create->cr_namelen,
  463. &create->cr_iattr, S_IFSOCK, 0, &resfh);
  464. break;
  465. case NF4FIFO:
  466. status = nfsd_create(rqstp, &cstate->current_fh,
  467. create->cr_name, create->cr_namelen,
  468. &create->cr_iattr, S_IFIFO, 0, &resfh);
  469. break;
  470. case NF4DIR:
  471. create->cr_iattr.ia_valid &= ~ATTR_SIZE;
  472. status = nfsd_create(rqstp, &cstate->current_fh,
  473. create->cr_name, create->cr_namelen,
  474. &create->cr_iattr, S_IFDIR, 0, &resfh);
  475. break;
  476. default:
  477. status = nfserr_badtype;
  478. }
  479. if (status)
  480. goto out;
  481. if (create->cr_acl != NULL)
  482. do_set_nfs4_acl(rqstp, &resfh, create->cr_acl,
  483. create->cr_bmval);
  484. fh_unlock(&cstate->current_fh);
  485. set_change_info(&create->cr_cinfo, &cstate->current_fh);
  486. fh_dup2(&cstate->current_fh, &resfh);
  487. out:
  488. fh_put(&resfh);
  489. return status;
  490. }
  491. static __be32
  492. nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  493. struct nfsd4_getattr *getattr)
  494. {
  495. __be32 status;
  496. status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
  497. if (status)
  498. return status;
  499. if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
  500. return nfserr_inval;
  501. getattr->ga_bmval[0] &= nfsd_suppattrs0(cstate->minorversion);
  502. getattr->ga_bmval[1] &= nfsd_suppattrs1(cstate->minorversion);
  503. getattr->ga_bmval[2] &= nfsd_suppattrs2(cstate->minorversion);
  504. getattr->ga_fhp = &cstate->current_fh;
  505. return nfs_ok;
  506. }
  507. static __be32
  508. nfsd4_link(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  509. struct nfsd4_link *link)
  510. {
  511. __be32 status = nfserr_nofilehandle;
  512. if (!cstate->save_fh.fh_dentry)
  513. return status;
  514. status = nfsd_link(rqstp, &cstate->current_fh,
  515. link->li_name, link->li_namelen, &cstate->save_fh);
  516. if (!status)
  517. set_change_info(&link->li_cinfo, &cstate->current_fh);
  518. return status;
  519. }
  520. static __be32
  521. nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  522. void *arg)
  523. {
  524. struct svc_fh tmp_fh;
  525. __be32 ret;
  526. fh_init(&tmp_fh, NFS4_FHSIZE);
  527. ret = exp_pseudoroot(rqstp, &tmp_fh);
  528. if (ret)
  529. return ret;
  530. if (tmp_fh.fh_dentry == cstate->current_fh.fh_dentry) {
  531. fh_put(&tmp_fh);
  532. return nfserr_noent;
  533. }
  534. fh_put(&tmp_fh);
  535. return nfsd_lookup(rqstp, &cstate->current_fh,
  536. "..", 2, &cstate->current_fh);
  537. }
  538. static __be32
  539. nfsd4_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  540. struct nfsd4_lookup *lookup)
  541. {
  542. return nfsd_lookup(rqstp, &cstate->current_fh,
  543. lookup->lo_name, lookup->lo_len,
  544. &cstate->current_fh);
  545. }
  546. static __be32
  547. nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  548. struct nfsd4_read *read)
  549. {
  550. __be32 status;
  551. /* no need to check permission - this will be done in nfsd_read() */
  552. read->rd_filp = NULL;
  553. if (read->rd_offset >= OFFSET_MAX)
  554. return nfserr_inval;
  555. nfs4_lock_state();
  556. /* check stateid */
  557. if ((status = nfs4_preprocess_stateid_op(cstate, &read->rd_stateid,
  558. RD_STATE, &read->rd_filp))) {
  559. dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
  560. goto out;
  561. }
  562. if (read->rd_filp)
  563. get_file(read->rd_filp);
  564. status = nfs_ok;
  565. out:
  566. nfs4_unlock_state();
  567. read->rd_rqstp = rqstp;
  568. read->rd_fhp = &cstate->current_fh;
  569. return status;
  570. }
  571. static __be32
  572. nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  573. struct nfsd4_readdir *readdir)
  574. {
  575. u64 cookie = readdir->rd_cookie;
  576. static const nfs4_verifier zeroverf;
  577. /* no need to check permission - this will be done in nfsd_readdir() */
  578. if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
  579. return nfserr_inval;
  580. readdir->rd_bmval[0] &= nfsd_suppattrs0(cstate->minorversion);
  581. readdir->rd_bmval[1] &= nfsd_suppattrs1(cstate->minorversion);
  582. readdir->rd_bmval[2] &= nfsd_suppattrs2(cstate->minorversion);
  583. if ((cookie > ~(u32)0) || (cookie == 1) || (cookie == 2) ||
  584. (cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE)))
  585. return nfserr_bad_cookie;
  586. readdir->rd_rqstp = rqstp;
  587. readdir->rd_fhp = &cstate->current_fh;
  588. return nfs_ok;
  589. }
  590. static __be32
  591. nfsd4_readlink(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  592. struct nfsd4_readlink *readlink)
  593. {
  594. readlink->rl_rqstp = rqstp;
  595. readlink->rl_fhp = &cstate->current_fh;
  596. return nfs_ok;
  597. }
  598. static __be32
  599. nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  600. struct nfsd4_remove *remove)
  601. {
  602. __be32 status;
  603. if (locks_in_grace())
  604. return nfserr_grace;
  605. status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
  606. remove->rm_name, remove->rm_namelen);
  607. if (status == nfserr_symlink)
  608. return nfserr_notdir;
  609. if (!status) {
  610. fh_unlock(&cstate->current_fh);
  611. set_change_info(&remove->rm_cinfo, &cstate->current_fh);
  612. }
  613. return status;
  614. }
  615. static __be32
  616. nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  617. struct nfsd4_rename *rename)
  618. {
  619. __be32 status = nfserr_nofilehandle;
  620. if (!cstate->save_fh.fh_dentry)
  621. return status;
  622. if (locks_in_grace() && !(cstate->save_fh.fh_export->ex_flags
  623. & NFSEXP_NOSUBTREECHECK))
  624. return nfserr_grace;
  625. status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
  626. rename->rn_snamelen, &cstate->current_fh,
  627. rename->rn_tname, rename->rn_tnamelen);
  628. /* the underlying filesystem returns different error's than required
  629. * by NFSv4. both save_fh and current_fh have been verified.. */
  630. if (status == nfserr_isdir)
  631. status = nfserr_exist;
  632. else if ((status == nfserr_notdir) &&
  633. (S_ISDIR(cstate->save_fh.fh_dentry->d_inode->i_mode) &&
  634. S_ISDIR(cstate->current_fh.fh_dentry->d_inode->i_mode)))
  635. status = nfserr_exist;
  636. else if (status == nfserr_symlink)
  637. status = nfserr_notdir;
  638. if (!status) {
  639. set_change_info(&rename->rn_sinfo, &cstate->current_fh);
  640. set_change_info(&rename->rn_tinfo, &cstate->save_fh);
  641. }
  642. return status;
  643. }
  644. static __be32
  645. nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  646. struct nfsd4_secinfo *secinfo)
  647. {
  648. struct svc_fh resfh;
  649. struct svc_export *exp;
  650. struct dentry *dentry;
  651. __be32 err;
  652. fh_init(&resfh, NFS4_FHSIZE);
  653. err = nfsd_lookup_dentry(rqstp, &cstate->current_fh,
  654. secinfo->si_name, secinfo->si_namelen,
  655. &exp, &dentry);
  656. if (err)
  657. return err;
  658. if (dentry->d_inode == NULL) {
  659. exp_put(exp);
  660. err = nfserr_noent;
  661. } else
  662. secinfo->si_exp = exp;
  663. dput(dentry);
  664. return err;
  665. }
  666. static __be32
  667. nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  668. struct nfsd4_setattr *setattr)
  669. {
  670. __be32 status = nfs_ok;
  671. if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
  672. nfs4_lock_state();
  673. status = nfs4_preprocess_stateid_op(cstate,
  674. &setattr->sa_stateid, WR_STATE, NULL);
  675. nfs4_unlock_state();
  676. if (status) {
  677. dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
  678. return status;
  679. }
  680. }
  681. status = mnt_want_write(cstate->current_fh.fh_export->ex_path.mnt);
  682. if (status)
  683. return status;
  684. status = nfs_ok;
  685. status = check_attr_support(rqstp, cstate, setattr->sa_bmval,
  686. nfsd_attrmask);
  687. if (status)
  688. goto out;
  689. if (setattr->sa_acl != NULL)
  690. status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,
  691. setattr->sa_acl);
  692. if (status)
  693. goto out;
  694. status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
  695. 0, (time_t)0);
  696. out:
  697. mnt_drop_write(cstate->current_fh.fh_export->ex_path.mnt);
  698. return status;
  699. }
  700. static __be32
  701. nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  702. struct nfsd4_write *write)
  703. {
  704. stateid_t *stateid = &write->wr_stateid;
  705. struct file *filp = NULL;
  706. u32 *p;
  707. __be32 status = nfs_ok;
  708. unsigned long cnt;
  709. /* no need to check permission - this will be done in nfsd_write() */
  710. if (write->wr_offset >= OFFSET_MAX)
  711. return nfserr_inval;
  712. nfs4_lock_state();
  713. status = nfs4_preprocess_stateid_op(cstate, stateid, WR_STATE, &filp);
  714. if (filp)
  715. get_file(filp);
  716. nfs4_unlock_state();
  717. if (status) {
  718. dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
  719. return status;
  720. }
  721. cnt = write->wr_buflen;
  722. write->wr_how_written = write->wr_stable_how;
  723. p = (u32 *)write->wr_verifier.data;
  724. *p++ = nfssvc_boot.tv_sec;
  725. *p++ = nfssvc_boot.tv_usec;
  726. status = nfsd_write(rqstp, &cstate->current_fh, filp,
  727. write->wr_offset, rqstp->rq_vec, write->wr_vlen,
  728. &cnt, &write->wr_how_written);
  729. if (filp)
  730. fput(filp);
  731. write->wr_bytes_written = cnt;
  732. if (status == nfserr_symlink)
  733. status = nfserr_inval;
  734. return status;
  735. }
  736. /* This routine never returns NFS_OK! If there are no other errors, it
  737. * will return NFSERR_SAME or NFSERR_NOT_SAME depending on whether the
  738. * attributes matched. VERIFY is implemented by mapping NFSERR_SAME
  739. * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK.
  740. */
  741. static __be32
  742. _nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  743. struct nfsd4_verify *verify)
  744. {
  745. __be32 *buf, *p;
  746. int count;
  747. __be32 status;
  748. status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
  749. if (status)
  750. return status;
  751. status = check_attr_support(rqstp, cstate, verify->ve_bmval, NULL);
  752. if (status)
  753. return status;
  754. if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)
  755. || (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1))
  756. return nfserr_inval;
  757. if (verify->ve_attrlen & 3)
  758. return nfserr_inval;
  759. /* count in words:
  760. * bitmap_len(1) + bitmap(2) + attr_len(1) = 4
  761. */
  762. count = 4 + (verify->ve_attrlen >> 2);
  763. buf = kmalloc(count << 2, GFP_KERNEL);
  764. if (!buf)
  765. return nfserr_resource;
  766. status = nfsd4_encode_fattr(&cstate->current_fh,
  767. cstate->current_fh.fh_export,
  768. cstate->current_fh.fh_dentry, buf,
  769. &count, verify->ve_bmval,
  770. rqstp, 0);
  771. /* this means that nfsd4_encode_fattr() ran out of space */
  772. if (status == nfserr_resource && count == 0)
  773. status = nfserr_not_same;
  774. if (status)
  775. goto out_kfree;
  776. /* skip bitmap */
  777. p = buf + 1 + ntohl(buf[0]);
  778. status = nfserr_not_same;
  779. if (ntohl(*p++) != verify->ve_attrlen)
  780. goto out_kfree;
  781. if (!memcmp(p, verify->ve_attrval, verify->ve_attrlen))
  782. status = nfserr_same;
  783. out_kfree:
  784. kfree(buf);
  785. return status;
  786. }
  787. static __be32
  788. nfsd4_nverify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  789. struct nfsd4_verify *verify)
  790. {
  791. __be32 status;
  792. status = _nfsd4_verify(rqstp, cstate, verify);
  793. return status == nfserr_not_same ? nfs_ok : status;
  794. }
  795. static __be32
  796. nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  797. struct nfsd4_verify *verify)
  798. {
  799. __be32 status;
  800. status = _nfsd4_verify(rqstp, cstate, verify);
  801. return status == nfserr_same ? nfs_ok : status;
  802. }
  803. /*
  804. * NULL call.
  805. */
  806. static __be32
  807. nfsd4_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
  808. {
  809. return nfs_ok;
  810. }
  811. static inline void nfsd4_increment_op_stats(u32 opnum)
  812. {
  813. if (opnum >= FIRST_NFS4_OP && opnum <= LAST_NFS4_OP)
  814. nfsdstats.nfs4_opcount[opnum]++;
  815. }
  816. typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *,
  817. void *);
  818. enum nfsd4_op_flags {
  819. ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */
  820. ALLOWED_ON_ABSENT_FS = 2 << 0, /* ops processed on absent fs */
  821. ALLOWED_AS_FIRST_OP = 3 << 0, /* ops reqired first in compound */
  822. };
  823. struct nfsd4_operation {
  824. nfsd4op_func op_func;
  825. u32 op_flags;
  826. char *op_name;
  827. };
  828. static struct nfsd4_operation nfsd4_ops[];
  829. static const char *nfsd4_op_name(unsigned opnum);
  830. /*
  831. * Enforce NFSv4.1 COMPOUND ordering rules.
  832. *
  833. * TODO:
  834. * - enforce NFS4ERR_NOT_ONLY_OP,
  835. * - DESTROY_SESSION MUST be the final operation in the COMPOUND request.
  836. */
  837. static bool nfs41_op_ordering_ok(struct nfsd4_compoundargs *args)
  838. {
  839. if (args->minorversion && args->opcnt > 0) {
  840. struct nfsd4_op *op = &args->ops[0];
  841. return (op->status == nfserr_op_illegal) ||
  842. (nfsd4_ops[op->opnum].op_flags & ALLOWED_AS_FIRST_OP);
  843. }
  844. return true;
  845. }
  846. /*
  847. * COMPOUND call.
  848. */
  849. static __be32
  850. nfsd4_proc_compound(struct svc_rqst *rqstp,
  851. struct nfsd4_compoundargs *args,
  852. struct nfsd4_compoundres *resp)
  853. {
  854. struct nfsd4_op *op;
  855. struct nfsd4_operation *opdesc;
  856. struct nfsd4_compound_state *cstate = &resp->cstate;
  857. int slack_bytes;
  858. __be32 status;
  859. resp->xbuf = &rqstp->rq_res;
  860. resp->p = rqstp->rq_res.head[0].iov_base +
  861. rqstp->rq_res.head[0].iov_len;
  862. resp->tagp = resp->p;
  863. /* reserve space for: taglen, tag, and opcnt */
  864. resp->p += 2 + XDR_QUADLEN(args->taglen);
  865. resp->end = rqstp->rq_res.head[0].iov_base + PAGE_SIZE;
  866. resp->taglen = args->taglen;
  867. resp->tag = args->tag;
  868. resp->opcnt = 0;
  869. resp->rqstp = rqstp;
  870. resp->cstate.minorversion = args->minorversion;
  871. resp->cstate.replay_owner = NULL;
  872. fh_init(&resp->cstate.current_fh, NFS4_FHSIZE);
  873. fh_init(&resp->cstate.save_fh, NFS4_FHSIZE);
  874. /* Use the deferral mechanism only for NFSv4.0 compounds */
  875. rqstp->rq_usedeferral = (args->minorversion == 0);
  876. /*
  877. * According to RFC3010, this takes precedence over all other errors.
  878. */
  879. status = nfserr_minor_vers_mismatch;
  880. if (args->minorversion > nfsd_supported_minorversion)
  881. goto out;
  882. if (!nfs41_op_ordering_ok(args)) {
  883. op = &args->ops[0];
  884. op->status = nfserr_sequence_pos;
  885. goto encode_op;
  886. }
  887. status = nfs_ok;
  888. while (!status && resp->opcnt < args->opcnt) {
  889. op = &args->ops[resp->opcnt++];
  890. dprintk("nfsv4 compound op #%d/%d: %d (%s)\n",
  891. resp->opcnt, args->opcnt, op->opnum,
  892. nfsd4_op_name(op->opnum));
  893. /*
  894. * The XDR decode routines may have pre-set op->status;
  895. * for example, if there is a miscellaneous XDR error
  896. * it will be set to nfserr_bad_xdr.
  897. */
  898. if (op->status)
  899. goto encode_op;
  900. /* We must be able to encode a successful response to
  901. * this operation, with enough room left over to encode a
  902. * failed response to the next operation. If we don't
  903. * have enough room, fail with ERR_RESOURCE.
  904. */
  905. slack_bytes = (char *)resp->end - (char *)resp->p;
  906. if (slack_bytes < COMPOUND_SLACK_SPACE
  907. + COMPOUND_ERR_SLACK_SPACE) {
  908. BUG_ON(slack_bytes < COMPOUND_ERR_SLACK_SPACE);
  909. op->status = nfserr_resource;
  910. goto encode_op;
  911. }
  912. opdesc = &nfsd4_ops[op->opnum];
  913. if (!cstate->current_fh.fh_dentry) {
  914. if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
  915. op->status = nfserr_nofilehandle;
  916. goto encode_op;
  917. }
  918. } else if (cstate->current_fh.fh_export->ex_fslocs.migrated &&
  919. !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
  920. op->status = nfserr_moved;
  921. goto encode_op;
  922. }
  923. if (opdesc->op_func)
  924. op->status = opdesc->op_func(rqstp, cstate, &op->u);
  925. else
  926. BUG_ON(op->status == nfs_ok);
  927. encode_op:
  928. /* Only from SEQUENCE */
  929. if (resp->cstate.status == nfserr_replay_cache) {
  930. dprintk("%s NFS4.1 replay from cache\n", __func__);
  931. status = op->status;
  932. goto out;
  933. }
  934. if (op->status == nfserr_replay_me) {
  935. op->replay = &cstate->replay_owner->so_replay;
  936. nfsd4_encode_replay(resp, op);
  937. status = op->status = op->replay->rp_status;
  938. } else {
  939. nfsd4_encode_operation(resp, op);
  940. status = op->status;
  941. }
  942. dprintk("nfsv4 compound op %p opcnt %d #%d: %d: status %d\n",
  943. args->ops, args->opcnt, resp->opcnt, op->opnum,
  944. be32_to_cpu(status));
  945. if (cstate->replay_owner) {
  946. nfs4_put_stateowner(cstate->replay_owner);
  947. cstate->replay_owner = NULL;
  948. }
  949. /* XXX Ugh, we need to get rid of this kind of special case: */
  950. if (op->opnum == OP_READ && op->u.read.rd_filp)
  951. fput(op->u.read.rd_filp);
  952. nfsd4_increment_op_stats(op->opnum);
  953. }
  954. if (!rqstp->rq_usedeferral && status == nfserr_dropit) {
  955. dprintk("%s Dropit - send NFS4ERR_DELAY\n", __func__);
  956. status = nfserr_jukebox;
  957. }
  958. resp->cstate.status = status;
  959. fh_put(&resp->cstate.current_fh);
  960. fh_put(&resp->cstate.save_fh);
  961. BUG_ON(resp->cstate.replay_owner);
  962. out:
  963. nfsd4_release_compoundargs(args);
  964. /* Reset deferral mechanism for RPC deferrals */
  965. rqstp->rq_usedeferral = 1;
  966. dprintk("nfsv4 compound returned %d\n", ntohl(status));
  967. return status;
  968. }
  969. static struct nfsd4_operation nfsd4_ops[] = {
  970. [OP_ACCESS] = {
  971. .op_func = (nfsd4op_func)nfsd4_access,
  972. .op_name = "OP_ACCESS",
  973. },
  974. [OP_CLOSE] = {
  975. .op_func = (nfsd4op_func)nfsd4_close,
  976. .op_name = "OP_CLOSE",
  977. },
  978. [OP_COMMIT] = {
  979. .op_func = (nfsd4op_func)nfsd4_commit,
  980. .op_name = "OP_COMMIT",
  981. },
  982. [OP_CREATE] = {
  983. .op_func = (nfsd4op_func)nfsd4_create,
  984. .op_name = "OP_CREATE",
  985. },
  986. [OP_DELEGRETURN] = {
  987. .op_func = (nfsd4op_func)nfsd4_delegreturn,
  988. .op_name = "OP_DELEGRETURN",
  989. },
  990. [OP_GETATTR] = {
  991. .op_func = (nfsd4op_func)nfsd4_getattr,
  992. .op_flags = ALLOWED_ON_ABSENT_FS,
  993. .op_name = "OP_GETATTR",
  994. },
  995. [OP_GETFH] = {
  996. .op_func = (nfsd4op_func)nfsd4_getfh,
  997. .op_name = "OP_GETFH",
  998. },
  999. [OP_LINK] = {
  1000. .op_func = (nfsd4op_func)nfsd4_link,
  1001. .op_name = "OP_LINK",
  1002. },
  1003. [OP_LOCK] = {
  1004. .op_func = (nfsd4op_func)nfsd4_lock,
  1005. .op_name = "OP_LOCK",
  1006. },
  1007. [OP_LOCKT] = {
  1008. .op_func = (nfsd4op_func)nfsd4_lockt,
  1009. .op_name = "OP_LOCKT",
  1010. },
  1011. [OP_LOCKU] = {
  1012. .op_func = (nfsd4op_func)nfsd4_locku,
  1013. .op_name = "OP_LOCKU",
  1014. },
  1015. [OP_LOOKUP] = {
  1016. .op_func = (nfsd4op_func)nfsd4_lookup,
  1017. .op_name = "OP_LOOKUP",
  1018. },
  1019. [OP_LOOKUPP] = {
  1020. .op_func = (nfsd4op_func)nfsd4_lookupp,
  1021. .op_name = "OP_LOOKUPP",
  1022. },
  1023. [OP_NVERIFY] = {
  1024. .op_func = (nfsd4op_func)nfsd4_nverify,
  1025. .op_name = "OP_NVERIFY",
  1026. },
  1027. [OP_OPEN] = {
  1028. .op_func = (nfsd4op_func)nfsd4_open,
  1029. .op_name = "OP_OPEN",
  1030. },
  1031. [OP_OPEN_CONFIRM] = {
  1032. .op_func = (nfsd4op_func)nfsd4_open_confirm,
  1033. .op_name = "OP_OPEN_CONFIRM",
  1034. },
  1035. [OP_OPEN_DOWNGRADE] = {
  1036. .op_func = (nfsd4op_func)nfsd4_open_downgrade,
  1037. .op_name = "OP_OPEN_DOWNGRADE",
  1038. },
  1039. [OP_PUTFH] = {
  1040. .op_func = (nfsd4op_func)nfsd4_putfh,
  1041. .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
  1042. .op_name = "OP_PUTFH",
  1043. },
  1044. [OP_PUTPUBFH] = {
  1045. .op_func = (nfsd4op_func)nfsd4_putrootfh,
  1046. .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
  1047. .op_name = "OP_PUTPUBFH",
  1048. },
  1049. [OP_PUTROOTFH] = {
  1050. .op_func = (nfsd4op_func)nfsd4_putrootfh,
  1051. .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
  1052. .op_name = "OP_PUTROOTFH",
  1053. },
  1054. [OP_READ] = {
  1055. .op_func = (nfsd4op_func)nfsd4_read,
  1056. .op_name = "OP_READ",
  1057. },
  1058. [OP_READDIR] = {
  1059. .op_func = (nfsd4op_func)nfsd4_readdir,
  1060. .op_name = "OP_READDIR",
  1061. },
  1062. [OP_READLINK] = {
  1063. .op_func = (nfsd4op_func)nfsd4_readlink,
  1064. .op_name = "OP_READLINK",
  1065. },
  1066. [OP_REMOVE] = {
  1067. .op_func = (nfsd4op_func)nfsd4_remove,
  1068. .op_name = "OP_REMOVE",
  1069. },
  1070. [OP_RENAME] = {
  1071. .op_name = "OP_RENAME",
  1072. .op_func = (nfsd4op_func)nfsd4_rename,
  1073. },
  1074. [OP_RENEW] = {
  1075. .op_func = (nfsd4op_func)nfsd4_renew,
  1076. .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
  1077. .op_name = "OP_RENEW",
  1078. },
  1079. [OP_RESTOREFH] = {
  1080. .op_func = (nfsd4op_func)nfsd4_restorefh,
  1081. .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
  1082. .op_name = "OP_RESTOREFH",
  1083. },
  1084. [OP_SAVEFH] = {
  1085. .op_func = (nfsd4op_func)nfsd4_savefh,
  1086. .op_name = "OP_SAVEFH",
  1087. },
  1088. [OP_SECINFO] = {
  1089. .op_func = (nfsd4op_func)nfsd4_secinfo,
  1090. .op_name = "OP_SECINFO",
  1091. },
  1092. [OP_SETATTR] = {
  1093. .op_func = (nfsd4op_func)nfsd4_setattr,
  1094. .op_name = "OP_SETATTR",
  1095. },
  1096. [OP_SETCLIENTID] = {
  1097. .op_func = (nfsd4op_func)nfsd4_setclientid,
  1098. .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
  1099. .op_name = "OP_SETCLIENTID",
  1100. },
  1101. [OP_SETCLIENTID_CONFIRM] = {
  1102. .op_func = (nfsd4op_func)nfsd4_setclientid_confirm,
  1103. .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
  1104. .op_name = "OP_SETCLIENTID_CONFIRM",
  1105. },
  1106. [OP_VERIFY] = {
  1107. .op_func = (nfsd4op_func)nfsd4_verify,
  1108. .op_name = "OP_VERIFY",
  1109. },
  1110. [OP_WRITE] = {
  1111. .op_func = (nfsd4op_func)nfsd4_write,
  1112. .op_name = "OP_WRITE",
  1113. },
  1114. [OP_RELEASE_LOCKOWNER] = {
  1115. .op_func = (nfsd4op_func)nfsd4_release_lockowner,
  1116. .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
  1117. .op_name = "OP_RELEASE_LOCKOWNER",
  1118. },
  1119. /* NFSv4.1 operations */
  1120. [OP_EXCHANGE_ID] = {
  1121. .op_func = (nfsd4op_func)nfsd4_exchange_id,
  1122. .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
  1123. .op_name = "OP_EXCHANGE_ID",
  1124. },
  1125. [OP_CREATE_SESSION] = {
  1126. .op_func = (nfsd4op_func)nfsd4_create_session,
  1127. .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
  1128. .op_name = "OP_CREATE_SESSION",
  1129. },
  1130. [OP_DESTROY_SESSION] = {
  1131. .op_func = (nfsd4op_func)nfsd4_destroy_session,
  1132. .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
  1133. .op_name = "OP_DESTROY_SESSION",
  1134. },
  1135. [OP_SEQUENCE] = {
  1136. .op_func = (nfsd4op_func)nfsd4_sequence,
  1137. .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
  1138. .op_name = "OP_SEQUENCE",
  1139. },
  1140. };
  1141. static const char *nfsd4_op_name(unsigned opnum)
  1142. {
  1143. if (opnum < ARRAY_SIZE(nfsd4_ops))
  1144. return nfsd4_ops[opnum].op_name;
  1145. return "unknown_operation";
  1146. }
  1147. #define nfsd4_voidres nfsd4_voidargs
  1148. struct nfsd4_voidargs { int dummy; };
  1149. /*
  1150. * TODO: At the present time, the NFSv4 server does not do XID caching
  1151. * of requests. Implementing XID caching would not be a serious problem,
  1152. * although it would require a mild change in interfaces since one
  1153. * doesn't know whether an NFSv4 request is idempotent until after the
  1154. * XDR decode. However, XID caching totally confuses pynfs (Peter
  1155. * Astrand's regression testsuite for NFSv4 servers), which reuses
  1156. * XID's liberally, so I've left it unimplemented until pynfs generates
  1157. * better XID's.
  1158. */
  1159. static struct svc_procedure nfsd_procedures4[2] = {
  1160. [NFSPROC4_NULL] = {
  1161. .pc_func = (svc_procfunc) nfsd4_proc_null,
  1162. .pc_encode = (kxdrproc_t) nfs4svc_encode_voidres,
  1163. .pc_argsize = sizeof(struct nfsd4_voidargs),
  1164. .pc_ressize = sizeof(struct nfsd4_voidres),
  1165. .pc_cachetype = RC_NOCACHE,
  1166. .pc_xdrressize = 1,
  1167. },
  1168. [NFSPROC4_COMPOUND] = {
  1169. .pc_func = (svc_procfunc) nfsd4_proc_compound,
  1170. .pc_decode = (kxdrproc_t) nfs4svc_decode_compoundargs,
  1171. .pc_encode = (kxdrproc_t) nfs4svc_encode_compoundres,
  1172. .pc_argsize = sizeof(struct nfsd4_compoundargs),
  1173. .pc_ressize = sizeof(struct nfsd4_compoundres),
  1174. .pc_cachetype = RC_NOCACHE,
  1175. .pc_xdrressize = NFSD_BUFSIZE/4,
  1176. },
  1177. };
  1178. struct svc_version nfsd_version4 = {
  1179. .vs_vers = 4,
  1180. .vs_nproc = 2,
  1181. .vs_proc = nfsd_procedures4,
  1182. .vs_dispatch = nfsd_dispatch,
  1183. .vs_xdrsize = NFS4_SVC_XDRSIZE,
  1184. };
  1185. /*
  1186. * Local variables:
  1187. * c-basic-offset: 8
  1188. * End:
  1189. */