aboutsummaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorMateusz Guzik <mjg@FreeBSD.org>2020-07-11 21:57:03 +0000
committerMateusz Guzik <mjg@FreeBSD.org>2020-07-11 21:57:03 +0000
commit373278a7f6678dc113b850f9ec0e09ca457cf644 (patch)
tree92be8a7824cbb35583bf8b4e4596d12b7c50e69f /sys/kern
parent463b8ebdcb319bf3784b24462ad917f584145031 (diff)
downloadsrc-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.c14
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);
}