diff options
author | Mateusz Guzik <mjg@FreeBSD.org> | 2020-07-11 21:57:03 +0000 |
---|---|---|
committer | Mateusz Guzik <mjg@FreeBSD.org> | 2020-07-11 21:57:03 +0000 |
commit | 373278a7f6678dc113b850f9ec0e09ca457cf644 (patch) | |
tree | 92be8a7824cbb35583bf8b4e4596d12b7c50e69f /sys/kern | |
parent | 463b8ebdcb319bf3784b24462ad917f584145031 (diff) | |
download | src-373278a7f6678dc113b850f9ec0e09ca457cf644.tar.gz src-373278a7f6678dc113b850f9ec0e09ca457cf644.zip |
fd: stop looping in pwd_hold
We don't expect to fail acquiring the reference unless running into a corner
case. Just in case ensure forward progress by taking the lock.
Reviewed by: kib, markj
Differential Revision: https://reviews.freebsd.org/D25616
Notes
Notes:
svn path=/head/; revision=363112
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_descrip.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 62c4d9a334cc..34e980b411ea 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -3347,13 +3347,17 @@ pwd_hold(struct thread *td) fdp = td->td_proc->p_fd; smr_enter(pwd_smr); - for (;;) { - pwd = smr_entered_load(&fdp->fd_pwd, pwd_smr); - MPASS(pwd != NULL); - if (refcount_acquire_if_not_zero(&pwd->pwd_refcount)) - break; + pwd = smr_entered_load(&fdp->fd_pwd, pwd_smr); + MPASS(pwd != NULL); + if (__predict_true(refcount_acquire_if_not_zero(&pwd->pwd_refcount))) { + smr_exit(pwd_smr); + return (pwd); } smr_exit(pwd_smr); + FILEDESC_SLOCK(fdp); + pwd = pwd_hold_filedesc(fdp); + MPASS(pwd != NULL); + FILEDESC_SUNLOCK(fdp); return (pwd); } |