aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4state.c104
-rw-r--r--fs/nfsd/state.h1
2 files changed, 59 insertions, 46 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 5c0cac173068..e9c3afe4b5d3 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -218,6 +218,13 @@ static void nfsd4_put_session(struct nfsd4_session *ses)
218 spin_unlock(&nn->client_lock); 218 spin_unlock(&nn->client_lock);
219} 219}
220 220
221static inline struct nfs4_stateowner *
222nfs4_get_stateowner(struct nfs4_stateowner *sop)
223{
224 atomic_inc(&sop->so_count);
225 return sop;
226}
227
221static int 228static int
222same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner) 229same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner)
223{ 230{
@@ -237,10 +244,8 @@ find_openstateowner_str_locked(unsigned int hashval, struct nfsd4_open *open,
237 so_strhash) { 244 so_strhash) {
238 if (!so->so_is_open_owner) 245 if (!so->so_is_open_owner)
239 continue; 246 continue;
240 if (same_owner_str(so, &open->op_owner)) { 247 if (same_owner_str(so, &open->op_owner))
241 atomic_inc(&so->so_count); 248 return openowner(nfs4_get_stateowner(so));
242 return openowner(so);
243 }
244 } 249 }
245 return NULL; 250 return NULL;
246} 251}
@@ -678,18 +683,14 @@ nfs4_put_stid(struct nfs4_stid *s)
678static void nfs4_put_deleg_lease(struct nfs4_file *fp) 683static void nfs4_put_deleg_lease(struct nfs4_file *fp)
679{ 684{
680 struct file *filp = NULL; 685 struct file *filp = NULL;
681 struct file_lock *fl;
682 686
683 spin_lock(&fp->fi_lock); 687 spin_lock(&fp->fi_lock);
684 if (fp->fi_lease && atomic_dec_and_test(&fp->fi_delegees)) { 688 if (fp->fi_deleg_file && atomic_dec_and_test(&fp->fi_delegees))
685 swap(filp, fp->fi_deleg_file); 689 swap(filp, fp->fi_deleg_file);
686 fl = fp->fi_lease;
687 fp->fi_lease = NULL;
688 }
689 spin_unlock(&fp->fi_lock); 690 spin_unlock(&fp->fi_lock);
690 691
691 if (filp) { 692 if (filp) {
692 vfs_setlease(filp, F_UNLCK, &fl); 693 vfs_setlease(filp, F_UNLCK, NULL, NULL);
693 fput(filp); 694 fput(filp);
694 } 695 }
695} 696}
@@ -1655,7 +1656,7 @@ __destroy_client(struct nfs4_client *clp)
1655 } 1656 }
1656 while (!list_empty(&clp->cl_openowners)) { 1657 while (!list_empty(&clp->cl_openowners)) {
1657 oo = list_entry(clp->cl_openowners.next, struct nfs4_openowner, oo_perclient); 1658 oo = list_entry(clp->cl_openowners.next, struct nfs4_openowner, oo_perclient);
1658 atomic_inc(&oo->oo_owner.so_count); 1659 nfs4_get_stateowner(&oo->oo_owner);
1659 release_openowner(oo); 1660 release_openowner(oo);
1660 } 1661 }
1661 nfsd4_shutdown_callback(clp); 1662 nfsd4_shutdown_callback(clp);
@@ -3067,8 +3068,8 @@ static void nfsd4_init_file(struct nfs4_file *fp, struct knfsd_fh *fh)
3067 INIT_LIST_HEAD(&fp->fi_stateids); 3068 INIT_LIST_HEAD(&fp->fi_stateids);
3068 INIT_LIST_HEAD(&fp->fi_delegations); 3069 INIT_LIST_HEAD(&fp->fi_delegations);
3069 fh_copy_shallow(&fp->fi_fhandle, fh); 3070 fh_copy_shallow(&fp->fi_fhandle, fh);
3071 fp->fi_deleg_file = NULL;
3070 fp->fi_had_conflict = false; 3072 fp->fi_had_conflict = false;
3071 fp->fi_lease = NULL;
3072 fp->fi_share_deny = 0; 3073 fp->fi_share_deny = 0;
3073 memset(fp->fi_fds, 0, sizeof(fp->fi_fds)); 3074 memset(fp->fi_fds, 0, sizeof(fp->fi_fds));
3074 memset(fp->fi_access, 0, sizeof(fp->fi_access)); 3075 memset(fp->fi_access, 0, sizeof(fp->fi_access));
@@ -3136,8 +3137,7 @@ static void nfsd4_cstate_assign_replay(struct nfsd4_compound_state *cstate,
3136{ 3137{
3137 if (!nfsd4_has_session(cstate)) { 3138 if (!nfsd4_has_session(cstate)) {
3138 mutex_lock(&so->so_replay.rp_mutex); 3139 mutex_lock(&so->so_replay.rp_mutex);
3139 cstate->replay_owner = so; 3140 cstate->replay_owner = nfs4_get_stateowner(so);
3140 atomic_inc(&so->so_count);
3141 } 3141 }
3142} 3142}
3143 3143
@@ -3236,8 +3236,7 @@ static void init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
3236 atomic_inc(&stp->st_stid.sc_count); 3236 atomic_inc(&stp->st_stid.sc_count);
3237 stp->st_stid.sc_type = NFS4_OPEN_STID; 3237 stp->st_stid.sc_type = NFS4_OPEN_STID;
3238 INIT_LIST_HEAD(&stp->st_locks); 3238 INIT_LIST_HEAD(&stp->st_locks);
3239 stp->st_stateowner = &oo->oo_owner; 3239 stp->st_stateowner = nfs4_get_stateowner(&oo->oo_owner);
3240 atomic_inc(&stp->st_stateowner->so_count);
3241 get_nfs4_file(fp); 3240 get_nfs4_file(fp);
3242 stp->st_stid.sc_file = fp; 3241 stp->st_stid.sc_file = fp;
3243 stp->st_access_bmap = 0; 3242 stp->st_access_bmap = 0;
@@ -3434,18 +3433,20 @@ static void nfsd_break_one_deleg(struct nfs4_delegation *dp)
3434} 3433}
3435 3434
3436/* Called from break_lease() with i_lock held. */ 3435/* Called from break_lease() with i_lock held. */
3437static void nfsd_break_deleg_cb(struct file_lock *fl) 3436static bool
3437nfsd_break_deleg_cb(struct file_lock *fl)
3438{ 3438{
3439 bool ret = false;
3439 struct nfs4_file *fp = (struct nfs4_file *)fl->fl_owner; 3440 struct nfs4_file *fp = (struct nfs4_file *)fl->fl_owner;
3440 struct nfs4_delegation *dp; 3441 struct nfs4_delegation *dp;
3441 3442
3442 if (!fp) { 3443 if (!fp) {
3443 WARN(1, "(%p)->fl_owner NULL\n", fl); 3444 WARN(1, "(%p)->fl_owner NULL\n", fl);
3444 return; 3445 return ret;
3445 } 3446 }
3446 if (fp->fi_had_conflict) { 3447 if (fp->fi_had_conflict) {
3447 WARN(1, "duplicate break on %p\n", fp); 3448 WARN(1, "duplicate break on %p\n", fp);
3448 return; 3449 return ret;
3449 } 3450 }
3450 /* 3451 /*
3451 * We don't want the locks code to timeout the lease for us; 3452 * We don't want the locks code to timeout the lease for us;
@@ -3457,24 +3458,23 @@ static void nfsd_break_deleg_cb(struct file_lock *fl)
3457 spin_lock(&fp->fi_lock); 3458 spin_lock(&fp->fi_lock);
3458 fp->fi_had_conflict = true; 3459 fp->fi_had_conflict = true;
3459 /* 3460 /*
3460 * If there are no delegations on the list, then we can't count on this 3461 * If there are no delegations on the list, then return true
3461 * lease ever being cleaned up. Set the fl_break_time to jiffies so that 3462 * so that the lease code will go ahead and delete it.
3462 * time_out_leases will do it ASAP. The fact that fi_had_conflict is now
3463 * true should keep any new delegations from being hashed.
3464 */ 3463 */
3465 if (list_empty(&fp->fi_delegations)) 3464 if (list_empty(&fp->fi_delegations))
3466 fl->fl_break_time = jiffies; 3465 ret = true;
3467 else 3466 else
3468 list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) 3467 list_for_each_entry(dp, &fp->fi_delegations, dl_perfile)
3469 nfsd_break_one_deleg(dp); 3468 nfsd_break_one_deleg(dp);
3470 spin_unlock(&fp->fi_lock); 3469 spin_unlock(&fp->fi_lock);
3470 return ret;
3471} 3471}
3472 3472
3473static 3473static int
3474int nfsd_change_deleg_cb(struct file_lock **onlist, int arg) 3474nfsd_change_deleg_cb(struct file_lock **onlist, int arg, struct list_head *dispose)
3475{ 3475{
3476 if (arg & F_UNLCK) 3476 if (arg & F_UNLCK)
3477 return lease_modify(onlist, arg); 3477 return lease_modify(onlist, arg, dispose);
3478 else 3478 else
3479 return -EAGAIN; 3479 return -EAGAIN;
3480} 3480}
@@ -3820,7 +3820,7 @@ static struct file_lock *nfs4_alloc_init_lease(struct nfs4_file *fp, int flag)
3820static int nfs4_setlease(struct nfs4_delegation *dp) 3820static int nfs4_setlease(struct nfs4_delegation *dp)
3821{ 3821{
3822 struct nfs4_file *fp = dp->dl_stid.sc_file; 3822 struct nfs4_file *fp = dp->dl_stid.sc_file;
3823 struct file_lock *fl; 3823 struct file_lock *fl, *ret;
3824 struct file *filp; 3824 struct file *filp;
3825 int status = 0; 3825 int status = 0;
3826 3826
@@ -3834,11 +3834,12 @@ static int nfs4_setlease(struct nfs4_delegation *dp)
3834 return -EBADF; 3834 return -EBADF;
3835 } 3835 }
3836 fl->fl_file = filp; 3836 fl->fl_file = filp;
3837 status = vfs_setlease(filp, fl->fl_type, &fl); 3837 ret = fl;
3838 if (status) { 3838 status = vfs_setlease(filp, fl->fl_type, &fl, NULL);
3839 if (fl)
3839 locks_free_lock(fl); 3840 locks_free_lock(fl);
3841 if (status)
3840 goto out_fput; 3842 goto out_fput;
3841 }
3842 spin_lock(&state_lock); 3843 spin_lock(&state_lock);
3843 spin_lock(&fp->fi_lock); 3844 spin_lock(&fp->fi_lock);
3844 /* Did the lease get broken before we took the lock? */ 3845 /* Did the lease get broken before we took the lock? */
@@ -3846,13 +3847,12 @@ static int nfs4_setlease(struct nfs4_delegation *dp)
3846 if (fp->fi_had_conflict) 3847 if (fp->fi_had_conflict)
3847 goto out_unlock; 3848 goto out_unlock;
3848 /* Race breaker */ 3849 /* Race breaker */
3849 if (fp->fi_lease) { 3850 if (fp->fi_deleg_file) {
3850 status = 0; 3851 status = 0;
3851 atomic_inc(&fp->fi_delegees); 3852 atomic_inc(&fp->fi_delegees);
3852 hash_delegation_locked(dp, fp); 3853 hash_delegation_locked(dp, fp);
3853 goto out_unlock; 3854 goto out_unlock;
3854 } 3855 }
3855 fp->fi_lease = fl;
3856 fp->fi_deleg_file = filp; 3856 fp->fi_deleg_file = filp;
3857 atomic_set(&fp->fi_delegees, 1); 3857 atomic_set(&fp->fi_delegees, 1);
3858 hash_delegation_locked(dp, fp); 3858 hash_delegation_locked(dp, fp);
@@ -3885,7 +3885,7 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
3885 spin_lock(&state_lock); 3885 spin_lock(&state_lock);
3886 spin_lock(&fp->fi_lock); 3886 spin_lock(&fp->fi_lock);
3887 dp->dl_stid.sc_file = fp; 3887 dp->dl_stid.sc_file = fp;
3888 if (!fp->fi_lease) { 3888 if (!fp->fi_deleg_file) {
3889 spin_unlock(&fp->fi_lock); 3889 spin_unlock(&fp->fi_lock);
3890 spin_unlock(&state_lock); 3890 spin_unlock(&state_lock);
3891 status = nfs4_setlease(dp); 3891 status = nfs4_setlease(dp);
@@ -4929,9 +4929,25 @@ nfs4_transform_lock_offset(struct file_lock *lock)
4929 lock->fl_end = OFFSET_MAX; 4929 lock->fl_end = OFFSET_MAX;
4930} 4930}
4931 4931
4932/* Hack!: For now, we're defining this just so we can use a pointer to it 4932static void nfsd4_fl_get_owner(struct file_lock *dst, struct file_lock *src)
4933 * as a unique cookie to identify our (NFSv4's) posix locks. */ 4933{
4934 struct nfs4_lockowner *lo = (struct nfs4_lockowner *)src->fl_owner;
4935 dst->fl_owner = (fl_owner_t)lockowner(nfs4_get_stateowner(&lo->lo_owner));
4936}
4937
4938static void nfsd4_fl_put_owner(struct file_lock *fl)
4939{
4940 struct nfs4_lockowner *lo = (struct nfs4_lockowner *)fl->fl_owner;
4941
4942 if (lo) {
4943 nfs4_put_stateowner(&lo->lo_owner);
4944 fl->fl_owner = NULL;
4945 }
4946}
4947
4934static const struct lock_manager_operations nfsd_posix_mng_ops = { 4948static const struct lock_manager_operations nfsd_posix_mng_ops = {
4949 .lm_get_owner = nfsd4_fl_get_owner,
4950 .lm_put_owner = nfsd4_fl_put_owner,
4935}; 4951};
4936 4952
4937static inline void 4953static inline void
@@ -4977,10 +4993,8 @@ find_lockowner_str_locked(clientid_t *clid, struct xdr_netobj *owner,
4977 so_strhash) { 4993 so_strhash) {
4978 if (so->so_is_open_owner) 4994 if (so->so_is_open_owner)
4979 continue; 4995 continue;
4980 if (!same_owner_str(so, owner)) 4996 if (same_owner_str(so, owner))
4981 continue; 4997 return lockowner(nfs4_get_stateowner(so));
4982 atomic_inc(&so->so_count);
4983 return lockowner(so);
4984 } 4998 }
4985 return NULL; 4999 return NULL;
4986} 5000}
@@ -5059,8 +5073,7 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo,
5059 5073
5060 atomic_inc(&stp->st_stid.sc_count); 5074 atomic_inc(&stp->st_stid.sc_count);
5061 stp->st_stid.sc_type = NFS4_LOCK_STID; 5075 stp->st_stid.sc_type = NFS4_LOCK_STID;
5062 stp->st_stateowner = &lo->lo_owner; 5076 stp->st_stateowner = nfs4_get_stateowner(&lo->lo_owner);
5063 atomic_inc(&lo->lo_owner.so_count);
5064 get_nfs4_file(fp); 5077 get_nfs4_file(fp);
5065 stp->st_stid.sc_file = fp; 5078 stp->st_stid.sc_file = fp;
5066 stp->st_stid.sc_free = nfs4_free_lock_stateid; 5079 stp->st_stid.sc_free = nfs4_free_lock_stateid;
@@ -5299,7 +5312,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5299 status = nfserr_openmode; 5312 status = nfserr_openmode;
5300 goto out; 5313 goto out;
5301 } 5314 }
5302 file_lock->fl_owner = (fl_owner_t)lock_sop; 5315
5316 file_lock->fl_owner = (fl_owner_t)lockowner(nfs4_get_stateowner(&lock_sop->lo_owner));
5303 file_lock->fl_pid = current->tgid; 5317 file_lock->fl_pid = current->tgid;
5304 file_lock->fl_file = filp; 5318 file_lock->fl_file = filp;
5305 file_lock->fl_flags = FL_POSIX; 5319 file_lock->fl_flags = FL_POSIX;
@@ -5495,7 +5509,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5495 } 5509 }
5496 5510
5497 file_lock->fl_type = F_UNLCK; 5511 file_lock->fl_type = F_UNLCK;
5498 file_lock->fl_owner = (fl_owner_t)lockowner(stp->st_stateowner); 5512 file_lock->fl_owner = (fl_owner_t)lockowner(nfs4_get_stateowner(stp->st_stateowner));
5499 file_lock->fl_pid = current->tgid; 5513 file_lock->fl_pid = current->tgid;
5500 file_lock->fl_file = filp; 5514 file_lock->fl_file = filp;
5501 file_lock->fl_flags = FL_POSIX; 5515 file_lock->fl_flags = FL_POSIX;
@@ -5602,7 +5616,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
5602 } 5616 }
5603 } 5617 }
5604 5618
5605 atomic_inc(&sop->so_count); 5619 nfs4_get_stateowner(sop);
5606 break; 5620 break;
5607 } 5621 }
5608 spin_unlock(&clp->cl_lock); 5622 spin_unlock(&clp->cl_lock);
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 0a47c6a6b301..2712042a66b1 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -486,7 +486,6 @@ struct nfs4_file {
486 atomic_t fi_access[2]; 486 atomic_t fi_access[2];
487 u32 fi_share_deny; 487 u32 fi_share_deny;
488 struct file *fi_deleg_file; 488 struct file *fi_deleg_file;
489 struct file_lock *fi_lease;
490 atomic_t fi_delegees; 489 atomic_t fi_delegees;
491 struct knfsd_fh fi_fhandle; 490 struct knfsd_fh fi_fhandle;
492 bool fi_had_conflict; 491 bool fi_had_conflict;