diff options
author | mjg <mjg@FreeBSD.org> | 2014-06-22 21:37:27 +0000 |
---|---|---|
committer | mjg <mjg@FreeBSD.org> | 2014-06-22 21:37:27 +0000 |
commit | 202339afcf6357683f0e37b4ac2145796d6d2fc5 (patch) | |
tree | 35484ab3d3287b205b7cb4c216643319fce9bdf7 | |
parent | 66013e8440dbaddd01711e4aefca2601746581e4 (diff) | |
download | FreeBSD-src-202339afcf6357683f0e37b4ac2145796d6d2fc5.zip FreeBSD-src-202339afcf6357683f0e37b4ac2145796d6d2fc5.tar.gz |
Don't take filedesc lock in fdunshare().
We can read refcnt safely and only care if it is equal to 1.
If it could suddenly change from 1 to something bigger the code would be
buggy even in the previous form and transitions from > 1 to 1 are equally racy
and harmless (we copy even though there is no need).
MFC after: 1 week
-rw-r--r-- | sys/kern/kern_descrip.c | 15 |
1 files changed, 6 insertions, 9 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 267b317..7e89c22 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1852,17 +1852,14 @@ fdshare(struct filedesc *fdp) void fdunshare(struct proc *p, struct thread *td) { + struct filedesc *tmp; - FILEDESC_XLOCK(p->p_fd); - if (p->p_fd->fd_refcnt > 1) { - struct filedesc *tmp; + if (p->p_fd->fd_refcnt == 1) + return; - FILEDESC_XUNLOCK(p->p_fd); - tmp = fdcopy(p->p_fd); - fdescfree(td); - p->p_fd = tmp; - } else - FILEDESC_XUNLOCK(p->p_fd); + tmp = fdcopy(p->p_fd); + fdescfree(td); + p->p_fd = tmp; } /* |