Patch "nfsd: Always lock state exclusively." has been added to the 4.4-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
nfsd: Always lock state exclusively.
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
nfsd-always-lock-state-exclusively.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
feb9dad5209280085d5b0c094fa67e7a8d75c81aMon Sep 17 00:00:00 2001
From: Oleg Drokin <[email protected]>
Date: Tue, 14 Jun 2016 23:28:04 -0400
Subject: nfsd: Always lock state exclusively.
From: Oleg Drokin <[email protected]>
commit feb9dad5209280085d5b0c094fa67e7a8d75c81a upstream.
It used to be the case that state had an rwlock that was locked for write by downgrades, but for read for upgrades (opens). Well, the problem is if there are two competing opens for the same state, they step on each other toes potentially leading to leaking file descriptors from the state structure, since access mode is a bitmap only set once.
--- fs/nfsd/nfs4state.c | 40 ++++++++++++++++++++-------------------- fs/nfsd/state.h | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-)
fs/nfsd/nfs4state.c +20 -20
@@ -3467,7 +3467,7 @@ init_open_stateid(struct nfs4_ol_stateid stp->st_access_bmap =0 ; stp->st_deny_bmap =0 ; stp->st_openstp =NULL ; -init_rwsem (&stp->st_rwsem); +mutex_init (&stp->st_mutex);list_add (&stp->st_perstateowner, &oo->oo_owner.so_stateids);list_add (&stp->st_perfile, &fp->fi_stateids);
@@ -4300,10 +4300,10 @@ nfsd4_process_open2(struct svc_rqst *rqs*/ if (stp) {/* Stateid was found, this is an OPEN upgrade */ -down_read (&stp->st_rwsem); +mutex_lock (&stp->st_mutex); status =nfs4_upgrade_open (rqstp, fp, current_fh, stp, open);if (status) { -up_read (&stp->st_rwsem); +mutex_unlock (&stp->st_mutex); goto out; } }else {
@@ -4313,19 +4313,19 @@ nfsd4_process_open2(struct svc_rqst *rqsif (swapstp) {nfs4_put_stid (&stp->st_stid); stp = swapstp; -down_read (&stp->st_rwsem); +mutex_lock (&stp->st_mutex); status =nfs4_upgrade_open (rqstp, fp, current_fh, stp, open);if (status) { -up_read (&stp->st_rwsem); +mutex_unlock (&stp->st_mutex); goto out; } goto upgrade_out; } -down_read (&stp->st_rwsem); +mutex_lock (&stp->st_mutex); status =nfs4_get_vfs_file (rqstp, fp, current_fh, stp, open);if (status) { -up_read (&stp->st_rwsem); +mutex_unlock (&stp->st_mutex);release_open_stateid (stp); goto out; }
@@ -4337,7 +4337,7 @@ nfsd4_process_open2(struct svc_rqst *rqs } upgrade_out:nfs4_inc_and_copy_stateid (&open->op_stateid, &stp->st_stid); -up_read (&stp->st_rwsem); +mutex_unlock (&stp->st_mutex);if (nfsd4_has_session (&resp->cstate)) {if (open->op_deleg_want &NFS4_SHARE_WANT_NO_DELEG ) {
@@ -4950,12 +4950,12 @@ static __be32 nfs4_seqid_op_checks(struc* revoked delegations are kept only for free_stateid. */ return nfserr_bad_stateid; -down_write (&stp->st_rwsem); +mutex_lock (&stp->st_mutex); status =check_stateid_generation (stateid, &stp->st_stid.sc_stateid,nfsd4_has_session (cstate));if (status == nfs_ok) status =nfs4_check_fh (current_fh, &stp->st_stid);if (status != nfs_ok) -up_write (&stp->st_rwsem); +mutex_unlock (&stp->st_mutex);return status; }
@@ -5003,7 +5003,7 @@ static __be32 nfs4_preprocess_confirmed_return status; oo =openowner (stp->st_stateowner);if (!(oo->oo_flags &NFS4_OO_CONFIRMED )) { -up_write (&stp->st_rwsem); +mutex_unlock (&stp->st_mutex);nfs4_put_stid (&stp->st_stid);return nfserr_bad_stateid; }
@@ -5035,12 +5035,12 @@ nfsd4_open_confirm(struct svc_rqst *rqst oo =openowner (stp->st_stateowner); status = nfserr_bad_stateid;if (oo->oo_flags &NFS4_OO_CONFIRMED ) { -up_write (&stp->st_rwsem); +mutex_unlock (&stp->st_mutex); goto put_stateid; } oo->oo_flags |=NFS4_OO_CONFIRMED ;nfs4_inc_and_copy_stateid (&oc->oc_resp_stateid, &stp->st_stid); -up_write (&stp->st_rwsem); +mutex_unlock (&stp->st_mutex);dprintk ("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n" , __func__, oc->oc_seqid,STATEID_VAL (&stp->st_stid.sc_stateid));
@@ -5116,7 +5116,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqnfs4_inc_and_copy_stateid (&od->od_stateid, &stp->st_stid); status = nfs_ok; put_stateid: -up_write (&stp->st_rwsem); +mutex_unlock (&stp->st_mutex);nfs4_put_stid (&stp->st_stid); out:nfsd4_bump_seqid (cstate, status);
@@ -5169,7 +5169,7 @@ nfsd4_close(struct svc_rqst *rqstp, struif (status) goto out;nfs4_inc_and_copy_stateid (&close->cl_stateid, &stp->st_stid); -up_write (&stp->st_rwsem); +mutex_unlock (&stp->st_mutex);nfsd4_close_open_stateid (stp);
@@ -5395,7 +5395,7 @@ init_lock_stateid(struct nfs4_ol_stateid stp->st_access_bmap =0 ; stp->st_deny_bmap = open_stp->st_deny_bmap; stp->st_openstp = open_stp; -init_rwsem (&stp->st_rwsem); +mutex_init (&stp->st_mutex);list_add (&stp->st_locks, &open_stp->st_locks);list_add (&stp->st_perstateowner, &lo->lo_owner.so_stateids);spin_lock (&fp->fi_lock);
@@ -5564,7 +5564,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struc &open_stp, nn);if (status) goto out; -up_write (&open_stp->st_rwsem); +mutex_unlock (&open_stp->st_mutex); open_sop =openowner (open_stp->st_stateowner); status = nfserr_bad_stateid; if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid,
@@ -5573,7 +5573,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struc status =lookup_or_create_lock_state (cstate, open_stp, lock, &lock_stp, &new);if (status == nfs_ok) -down_write (&lock_stp->st_rwsem); +mutex_lock (&lock_stp->st_mutex); }else { status = nfs4_preprocess_seqid_op(cstate, lock->lk_old_lock_seqid,
@@ -5677,7 +5677,7 @@ out: seqid_mutating_err(ntohl(status))) lock_sop->lo_owner.so_seqid++; -up_write (&lock_stp->st_rwsem); +mutex_unlock (&lock_stp->st_mutex);/* * If this is a new, never-before-used stateid, and we are
@@ -5847,7 +5847,7 @@ nfsd4_locku(struct svc_rqst *rqstp, stru fput:fput (filp); put_stateid: -up_write (&stp->st_rwsem); +mutex_unlock (&stp->st_mutex);nfs4_put_stid (&stp->st_stid); out:nfsd4_bump_seqid (cstate, status);
fs/nfsd/state.h +1 -1
@@ -535,7 +535,7 @@ struct nfs4_ol_stateid {unsigned char st_access_bmap;unsigned char st_deny_bmap;struct nfs4_ol_stateid *st_openstp; -struct rw_semaphore st_rwsem; +struct mutex st_mutex; };static inline struct nfs4_ol_stateid *openlockstateid (struct nfs4_stid *s)
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/nfsd-always-lock-state-exclusively.patch queue-4.4/nfsd-extend-the-mutex-holding-region-around-in-nfsd4_process_open2.patch queue-4.4/make-nfs_atomic_open-call-d_drop-on-all-open_context-errors.patch