mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-23 11:18:54 +00:00
Fix a LOR in the NFSv4.1 server.
The ordering of acquisition of the state and session mutexes was reversed in two cases executed when an NFSv4.1 client created/freed a session. Since clients will typically do this only when mounting and dismounting, the likelyhood of causing a deadlock was low but possible. This can only occur for NFSv4.1 mounts, since the others do not use sessions. This was detected while testing the pNFS server/client where the client crashed during dismounting. The patch also reorders the unlocks, although that isn't necessary for correct operation. MFC after: 2 weeks
This commit is contained in:
parent
f19c33eed4
commit
0533d72612
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=298495
@ -113,7 +113,7 @@ struct nfsclient {
|
||||
* Structure for an NFSv4.1 session.
|
||||
* Locking rules for this structure.
|
||||
* To add/delete one of these structures from the lists, you must lock
|
||||
* both: NFSLOCKSESSION(session hashhead) and NFSLOCKSTATE() in that order.
|
||||
* both: NFSLOCKSTATE() and NFSLOCKSESSION(session hashhead) in that order.
|
||||
* To traverse the lists looking for one of these, you must hold one
|
||||
* of these two locks.
|
||||
* The exception is if the thread holds the exclusive root sleep lock.
|
||||
|
@ -624,13 +624,13 @@ nfsrv_getclient(nfsquad_t clientid, int opflags, struct nfsclient **clpp,
|
||||
NFSBCOPY(sessid, nsep->sess_cbsess.nfsess_sessionid,
|
||||
NFSX_V4SESSIONID);
|
||||
shp = NFSSESSIONHASH(nsep->sess_sessionid);
|
||||
NFSLOCKSTATE();
|
||||
NFSLOCKSESSION(shp);
|
||||
LIST_INSERT_HEAD(&shp->list, nsep, sess_hash);
|
||||
NFSLOCKSTATE();
|
||||
LIST_INSERT_HEAD(&clp->lc_session, nsep, sess_list);
|
||||
nsep->sess_clp = clp;
|
||||
NFSUNLOCKSTATE();
|
||||
NFSUNLOCKSESSION(shp);
|
||||
NFSUNLOCKSTATE();
|
||||
}
|
||||
}
|
||||
} else if (clp->lc_flags & LCL_NEEDSCONFIRM) {
|
||||
@ -5923,6 +5923,7 @@ nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid)
|
||||
struct nfssessionhash *shp;
|
||||
int i;
|
||||
|
||||
NFSLOCKSTATE();
|
||||
if (sep == NULL) {
|
||||
shp = NFSSESSIONHASH(sessionid);
|
||||
NFSLOCKSESSION(shp);
|
||||
@ -5932,18 +5933,17 @@ nfsrv_freesession(struct nfsdsession *sep, uint8_t *sessionid)
|
||||
NFSLOCKSESSION(shp);
|
||||
}
|
||||
if (sep != NULL) {
|
||||
NFSLOCKSTATE();
|
||||
sep->sess_refcnt--;
|
||||
if (sep->sess_refcnt > 0) {
|
||||
NFSUNLOCKSTATE();
|
||||
NFSUNLOCKSESSION(shp);
|
||||
NFSUNLOCKSTATE();
|
||||
return (0);
|
||||
}
|
||||
LIST_REMOVE(sep, sess_hash);
|
||||
LIST_REMOVE(sep, sess_list);
|
||||
NFSUNLOCKSTATE();
|
||||
}
|
||||
NFSUNLOCKSESSION(shp);
|
||||
NFSUNLOCKSTATE();
|
||||
if (sep == NULL)
|
||||
return (NFSERR_BADSESSION);
|
||||
for (i = 0; i < NFSV4_SLOTS; i++)
|
||||
|
Loading…
Reference in New Issue
Block a user