aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c147
1 files changed, 129 insertions, 18 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 38f2d7abe3a7..039f9c8a95e8 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -94,6 +94,7 @@ static struct kmem_cache *lockowner_slab;
94static struct kmem_cache *file_slab; 94static struct kmem_cache *file_slab;
95static struct kmem_cache *stateid_slab; 95static struct kmem_cache *stateid_slab;
96static struct kmem_cache *deleg_slab; 96static struct kmem_cache *deleg_slab;
97static struct kmem_cache *odstate_slab;
97 98
98static void free_session(struct nfsd4_session *); 99static void free_session(struct nfsd4_session *);
99 100
@@ -281,6 +282,7 @@ put_nfs4_file(struct nfs4_file *fi)
281 if (atomic_dec_and_lock(&fi->fi_ref, &state_lock)) { 282 if (atomic_dec_and_lock(&fi->fi_ref, &state_lock)) {
282 hlist_del_rcu(&fi->fi_hash); 283 hlist_del_rcu(&fi->fi_hash);
283 spin_unlock(&state_lock); 284 spin_unlock(&state_lock);
285 WARN_ON_ONCE(!list_empty(&fi->fi_clnt_odstate));
284 WARN_ON_ONCE(!list_empty(&fi->fi_delegations)); 286 WARN_ON_ONCE(!list_empty(&fi->fi_delegations));
285 call_rcu(&fi->fi_rcu, nfsd4_free_file_rcu); 287 call_rcu(&fi->fi_rcu, nfsd4_free_file_rcu);
286 } 288 }
@@ -471,6 +473,86 @@ static void nfs4_file_put_access(struct nfs4_file *fp, u32 access)
471 __nfs4_file_put_access(fp, O_RDONLY); 473 __nfs4_file_put_access(fp, O_RDONLY);
472} 474}
473 475
476/*
477 * Allocate a new open/delegation state counter. This is needed for
478 * pNFS for proper return on close semantics.
479 *
480 * Note that we only allocate it for pNFS-enabled exports, otherwise
481 * all pointers to struct nfs4_clnt_odstate are always NULL.
482 */
483static struct nfs4_clnt_odstate *
484alloc_clnt_odstate(struct nfs4_client *clp)
485{
486 struct nfs4_clnt_odstate *co;
487
488 co = kmem_cache_zalloc(odstate_slab, GFP_KERNEL);
489 if (co) {
490 co->co_client = clp;
491 atomic_set(&co->co_odcount, 1);
492 }
493 return co;
494}
495
496static void
497hash_clnt_odstate_locked(struct nfs4_clnt_odstate *co)
498{
499 struct nfs4_file *fp = co->co_file;
500
501 lockdep_assert_held(&fp->fi_lock);
502 list_add(&co->co_perfile, &fp->fi_clnt_odstate);
503}
504
505static inline void
506get_clnt_odstate(struct nfs4_clnt_odstate *co)
507{
508 if (co)
509 atomic_inc(&co->co_odcount);
510}
511
512static void
513put_clnt_odstate(struct nfs4_clnt_odstate *co)
514{
515 struct nfs4_file *fp;
516
517 if (!co)
518 return;
519
520 fp = co->co_file;
521 if (atomic_dec_and_lock(&co->co_odcount, &fp->fi_lock)) {
522 list_del(&co->co_perfile);
523 spin_unlock(&fp->fi_lock);
524
525 nfsd4_return_all_file_layouts(co->co_client, fp);
526 kmem_cache_free(odstate_slab, co);
527 }
528}
529
530static struct nfs4_clnt_odstate *
531find_or_hash_clnt_odstate(struct nfs4_file *fp, struct nfs4_clnt_odstate *new)
532{
533 struct nfs4_clnt_odstate *co;
534 struct nfs4_client *cl;
535
536 if (!new)
537 return NULL;
538
539 cl = new->co_client;
540
541 spin_lock(&fp->fi_lock);
542 list_for_each_entry(co, &fp->fi_clnt_odstate, co_perfile) {
543 if (co->co_client == cl) {
544 get_clnt_odstate(co);
545 goto out;
546 }
547 }
548 co = new;
549 co->co_file = fp;
550 hash_clnt_odstate_locked(new);
551out:
552 spin_unlock(&fp->fi_lock);
553 return co;
554}
555
474struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, 556struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl,
475 struct kmem_cache *slab) 557 struct kmem_cache *slab)
476{ 558{
@@ -606,7 +688,8 @@ static void block_delegations(struct knfsd_fh *fh)
606} 688}
607 689
608static struct nfs4_delegation * 690static struct nfs4_delegation *
609alloc_init_deleg(struct nfs4_client *clp, struct svc_fh *current_fh) 691alloc_init_deleg(struct nfs4_client *clp, struct svc_fh *current_fh,
692 struct nfs4_clnt_odstate *odstate)
610{ 693{
611 struct nfs4_delegation *dp; 694 struct nfs4_delegation *dp;
612 long n; 695 long n;
@@ -631,6 +714,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct svc_fh *current_fh)
631 INIT_LIST_HEAD(&dp->dl_perfile); 714 INIT_LIST_HEAD(&dp->dl_perfile);
632 INIT_LIST_HEAD(&dp->dl_perclnt); 715 INIT_LIST_HEAD(&dp->dl_perclnt);
633 INIT_LIST_HEAD(&dp->dl_recall_lru); 716 INIT_LIST_HEAD(&dp->dl_recall_lru);
717 dp->dl_clnt_odstate = odstate;
718 get_clnt_odstate(odstate);
634 dp->dl_type = NFS4_OPEN_DELEGATE_READ; 719 dp->dl_type = NFS4_OPEN_DELEGATE_READ;
635 dp->dl_retries = 1; 720 dp->dl_retries = 1;
636 nfsd4_init_cb(&dp->dl_recall, dp->dl_stid.sc_client, 721 nfsd4_init_cb(&dp->dl_recall, dp->dl_stid.sc_client,
@@ -714,6 +799,7 @@ static void destroy_delegation(struct nfs4_delegation *dp)
714 spin_lock(&state_lock); 799 spin_lock(&state_lock);
715 unhash_delegation_locked(dp); 800 unhash_delegation_locked(dp);
716 spin_unlock(&state_lock); 801 spin_unlock(&state_lock);
802 put_clnt_odstate(dp->dl_clnt_odstate);
717 nfs4_put_deleg_lease(dp->dl_stid.sc_file); 803 nfs4_put_deleg_lease(dp->dl_stid.sc_file);
718 nfs4_put_stid(&dp->dl_stid); 804 nfs4_put_stid(&dp->dl_stid);
719} 805}
@@ -724,6 +810,7 @@ static void revoke_delegation(struct nfs4_delegation *dp)
724 810
725 WARN_ON(!list_empty(&dp->dl_recall_lru)); 811 WARN_ON(!list_empty(&dp->dl_recall_lru));
726 812
813 put_clnt_odstate(dp->dl_clnt_odstate);
727 nfs4_put_deleg_lease(dp->dl_stid.sc_file); 814 nfs4_put_deleg_lease(dp->dl_stid.sc_file);
728 815
729 if (clp->cl_minorversion == 0) 816 if (clp->cl_minorversion == 0)
@@ -933,6 +1020,7 @@ static void nfs4_free_ol_stateid(struct nfs4_stid *stid)
933{ 1020{
934 struct nfs4_ol_stateid *stp = openlockstateid(stid); 1021 struct nfs4_ol_stateid *stp = openlockstateid(stid);
935 1022
1023 put_clnt_odstate(stp->st_clnt_odstate);
936 release_all_access(stp); 1024 release_all_access(stp);
937 if (stp->st_stateowner) 1025 if (stp->st_stateowner)
938 nfs4_put_stateowner(stp->st_stateowner); 1026 nfs4_put_stateowner(stp->st_stateowner);
@@ -1538,7 +1626,6 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
1538 INIT_LIST_HEAD(&clp->cl_openowners); 1626 INIT_LIST_HEAD(&clp->cl_openowners);
1539 INIT_LIST_HEAD(&clp->cl_delegations); 1627 INIT_LIST_HEAD(&clp->cl_delegations);
1540 INIT_LIST_HEAD(&clp->cl_lru); 1628 INIT_LIST_HEAD(&clp->cl_lru);
1541 INIT_LIST_HEAD(&clp->cl_callbacks);
1542 INIT_LIST_HEAD(&clp->cl_revoked); 1629 INIT_LIST_HEAD(&clp->cl_revoked);
1543#ifdef CONFIG_NFSD_PNFS 1630#ifdef CONFIG_NFSD_PNFS
1544 INIT_LIST_HEAD(&clp->cl_lo_states); 1631 INIT_LIST_HEAD(&clp->cl_lo_states);
@@ -1634,6 +1721,7 @@ __destroy_client(struct nfs4_client *clp)
1634 while (!list_empty(&reaplist)) { 1721 while (!list_empty(&reaplist)) {
1635 dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru); 1722 dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru);
1636 list_del_init(&dp->dl_recall_lru); 1723 list_del_init(&dp->dl_recall_lru);
1724 put_clnt_odstate(dp->dl_clnt_odstate);
1637 nfs4_put_deleg_lease(dp->dl_stid.sc_file); 1725 nfs4_put_deleg_lease(dp->dl_stid.sc_file);
1638 nfs4_put_stid(&dp->dl_stid); 1726 nfs4_put_stid(&dp->dl_stid);
1639 } 1727 }
@@ -3057,6 +3145,7 @@ static void nfsd4_init_file(struct knfsd_fh *fh, unsigned int hashval,
3057 spin_lock_init(&fp->fi_lock); 3145 spin_lock_init(&fp->fi_lock);
3058 INIT_LIST_HEAD(&fp->fi_stateids); 3146 INIT_LIST_HEAD(&fp->fi_stateids);
3059 INIT_LIST_HEAD(&fp->fi_delegations); 3147 INIT_LIST_HEAD(&fp->fi_delegations);
3148 INIT_LIST_HEAD(&fp->fi_clnt_odstate);
3060 fh_copy_shallow(&fp->fi_fhandle, fh); 3149 fh_copy_shallow(&fp->fi_fhandle, fh);
3061 fp->fi_deleg_file = NULL; 3150 fp->fi_deleg_file = NULL;
3062 fp->fi_had_conflict = false; 3151 fp->fi_had_conflict = false;
@@ -3073,6 +3162,7 @@ static void nfsd4_init_file(struct knfsd_fh *fh, unsigned int hashval,
3073void 3162void
3074nfsd4_free_slabs(void) 3163nfsd4_free_slabs(void)
3075{ 3164{
3165 kmem_cache_destroy(odstate_slab);
3076 kmem_cache_destroy(openowner_slab); 3166 kmem_cache_destroy(openowner_slab);
3077 kmem_cache_destroy(lockowner_slab); 3167 kmem_cache_destroy(lockowner_slab);
3078 kmem_cache_destroy(file_slab); 3168 kmem_cache_destroy(file_slab);
@@ -3103,8 +3193,14 @@ nfsd4_init_slabs(void)
3103 sizeof(struct nfs4_delegation), 0, 0, NULL); 3193 sizeof(struct nfs4_delegation), 0, 0, NULL);
3104 if (deleg_slab == NULL) 3194 if (deleg_slab == NULL)
3105 goto out_free_stateid_slab; 3195 goto out_free_stateid_slab;
3196 odstate_slab = kmem_cache_create("nfsd4_odstate",
3197 sizeof(struct nfs4_clnt_odstate), 0, 0, NULL);
3198 if (odstate_slab == NULL)
3199 goto out_free_deleg_slab;
3106 return 0; 3200 return 0;
3107 3201
3202out_free_deleg_slab:
3203 kmem_cache_destroy(deleg_slab);
3108out_free_stateid_slab: 3204out_free_stateid_slab:
3109 kmem_cache_destroy(stateid_slab); 3205 kmem_cache_destroy(stateid_slab);
3110out_free_file_slab: 3206out_free_file_slab:
@@ -3581,6 +3677,14 @@ alloc_stateid:
3581 open->op_stp = nfs4_alloc_open_stateid(clp); 3677 open->op_stp = nfs4_alloc_open_stateid(clp);
3582 if (!open->op_stp) 3678 if (!open->op_stp)
3583 return nfserr_jukebox; 3679 return nfserr_jukebox;
3680
3681 if (nfsd4_has_session(cstate) &&
3682 (cstate->current_fh.fh_export->ex_flags & NFSEXP_PNFS)) {
3683 open->op_odstate = alloc_clnt_odstate(clp);
3684 if (!open->op_odstate)
3685 return nfserr_jukebox;
3686 }
3687
3584 return nfs_ok; 3688 return nfs_ok;
3585} 3689}
3586 3690
@@ -3869,7 +3973,7 @@ out_fput:
3869 3973
3870static struct nfs4_delegation * 3974static struct nfs4_delegation *
3871nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh, 3975nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
3872 struct nfs4_file *fp) 3976 struct nfs4_file *fp, struct nfs4_clnt_odstate *odstate)
3873{ 3977{
3874 int status; 3978 int status;
3875 struct nfs4_delegation *dp; 3979 struct nfs4_delegation *dp;
@@ -3877,7 +3981,7 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
3877 if (fp->fi_had_conflict) 3981 if (fp->fi_had_conflict)
3878 return ERR_PTR(-EAGAIN); 3982 return ERR_PTR(-EAGAIN);
3879 3983
3880 dp = alloc_init_deleg(clp, fh); 3984 dp = alloc_init_deleg(clp, fh, odstate);
3881 if (!dp) 3985 if (!dp)
3882 return ERR_PTR(-ENOMEM); 3986 return ERR_PTR(-ENOMEM);
3883 3987
@@ -3903,6 +4007,7 @@ out_unlock:
3903 spin_unlock(&state_lock); 4007 spin_unlock(&state_lock);
3904out: 4008out:
3905 if (status) { 4009 if (status) {
4010 put_clnt_odstate(dp->dl_clnt_odstate);
3906 nfs4_put_stid(&dp->dl_stid); 4011 nfs4_put_stid(&dp->dl_stid);
3907 return ERR_PTR(status); 4012 return ERR_PTR(status);
3908 } 4013 }
@@ -3980,7 +4085,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open,
3980 default: 4085 default:
3981 goto out_no_deleg; 4086 goto out_no_deleg;
3982 } 4087 }
3983 dp = nfs4_set_delegation(clp, fh, stp->st_stid.sc_file); 4088 dp = nfs4_set_delegation(clp, fh, stp->st_stid.sc_file, stp->st_clnt_odstate);
3984 if (IS_ERR(dp)) 4089 if (IS_ERR(dp))
3985 goto out_no_deleg; 4090 goto out_no_deleg;
3986 4091
@@ -4069,6 +4174,11 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
4069 release_open_stateid(stp); 4174 release_open_stateid(stp);
4070 goto out; 4175 goto out;
4071 } 4176 }
4177
4178 stp->st_clnt_odstate = find_or_hash_clnt_odstate(fp,
4179 open->op_odstate);
4180 if (stp->st_clnt_odstate == open->op_odstate)
4181 open->op_odstate = NULL;
4072 } 4182 }
4073 update_stateid(&stp->st_stid.sc_stateid); 4183 update_stateid(&stp->st_stid.sc_stateid);
4074 memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); 4184 memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
@@ -4129,6 +4239,8 @@ void nfsd4_cleanup_open_state(struct nfsd4_compound_state *cstate,
4129 kmem_cache_free(file_slab, open->op_file); 4239 kmem_cache_free(file_slab, open->op_file);
4130 if (open->op_stp) 4240 if (open->op_stp)
4131 nfs4_put_stid(&open->op_stp->st_stid); 4241 nfs4_put_stid(&open->op_stp->st_stid);
4242 if (open->op_odstate)
4243 kmem_cache_free(odstate_slab, open->op_odstate);
4132} 4244}
4133 4245
4134__be32 4246__be32
@@ -4385,10 +4497,17 @@ static __be32 check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_s
4385 return nfserr_old_stateid; 4497 return nfserr_old_stateid;
4386} 4498}
4387 4499
4500static __be32 nfsd4_check_openowner_confirmed(struct nfs4_ol_stateid *ols)
4501{
4502 if (ols->st_stateowner->so_is_open_owner &&
4503 !(openowner(ols->st_stateowner)->oo_flags & NFS4_OO_CONFIRMED))
4504 return nfserr_bad_stateid;
4505 return nfs_ok;
4506}
4507
4388static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid) 4508static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
4389{ 4509{
4390 struct nfs4_stid *s; 4510 struct nfs4_stid *s;
4391 struct nfs4_ol_stateid *ols;
4392 __be32 status = nfserr_bad_stateid; 4511 __be32 status = nfserr_bad_stateid;
4393 4512
4394 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) 4513 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
@@ -4418,13 +4537,7 @@ static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
4418 break; 4537 break;
4419 case NFS4_OPEN_STID: 4538 case NFS4_OPEN_STID:
4420 case NFS4_LOCK_STID: 4539 case NFS4_LOCK_STID:
4421 ols = openlockstateid(s); 4540 status = nfsd4_check_openowner_confirmed(openlockstateid(s));
4422 if (ols->st_stateowner->so_is_open_owner
4423 && !(openowner(ols->st_stateowner)->oo_flags
4424 & NFS4_OO_CONFIRMED))
4425 status = nfserr_bad_stateid;
4426 else
4427 status = nfs_ok;
4428 break; 4541 break;
4429 default: 4542 default:
4430 printk("unknown stateid type %x\n", s->sc_type); 4543 printk("unknown stateid type %x\n", s->sc_type);
@@ -4516,8 +4629,8 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
4516 status = nfs4_check_fh(current_fh, stp); 4629 status = nfs4_check_fh(current_fh, stp);
4517 if (status) 4630 if (status)
4518 goto out; 4631 goto out;
4519 if (stp->st_stateowner->so_is_open_owner 4632 status = nfsd4_check_openowner_confirmed(stp);
4520 && !(openowner(stp->st_stateowner)->oo_flags & NFS4_OO_CONFIRMED)) 4633 if (status)
4521 goto out; 4634 goto out;
4522 status = nfs4_check_openmode(stp, flags); 4635 status = nfs4_check_openmode(stp, flags);
4523 if (status) 4636 if (status)
@@ -4852,9 +4965,6 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4852 update_stateid(&stp->st_stid.sc_stateid); 4965 update_stateid(&stp->st_stid.sc_stateid);
4853 memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); 4966 memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
4854 4967
4855 nfsd4_return_all_file_layouts(stp->st_stateowner->so_client,
4856 stp->st_stid.sc_file);
4857
4858 nfsd4_close_open_stateid(stp); 4968 nfsd4_close_open_stateid(stp);
4859 4969
4860 /* put reference from nfs4_preprocess_seqid_op */ 4970 /* put reference from nfs4_preprocess_seqid_op */
@@ -6488,6 +6598,7 @@ nfs4_state_shutdown_net(struct net *net)
6488 list_for_each_safe(pos, next, &reaplist) { 6598 list_for_each_safe(pos, next, &reaplist) {
6489 dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru); 6599 dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
6490 list_del_init(&dp->dl_recall_lru); 6600 list_del_init(&dp->dl_recall_lru);
6601 put_clnt_odstate(dp->dl_clnt_odstate);
6491 nfs4_put_deleg_lease(dp->dl_stid.sc_file); 6602 nfs4_put_deleg_lease(dp->dl_stid.sc_file);
6492 nfs4_put_stid(&dp->dl_stid); 6603 nfs4_put_stid(&dp->dl_stid);
6493 } 6604 }