diff options
author | mjg <mjg@FreeBSD.org> | 2014-07-06 22:56:34 +0000 |
---|---|---|
committer | mjg <mjg@FreeBSD.org> | 2014-07-06 22:56:34 +0000 |
commit | c9bb8da01167a7b5ceaa16259e6b6bab943b7ea9 (patch) | |
tree | 4aa49597bd2f7bcb0c343c74a2b0398a865addd7 /sys/kern | |
parent | 4ec4a6585547ae29000dc768cf108796f523d42a (diff) | |
download | FreeBSD-src-c9bb8da01167a7b5ceaa16259e6b6bab943b7ea9.zip FreeBSD-src-c9bb8da01167a7b5ceaa16259e6b6bab943b7ea9.tar.gz |
MFC r267755:
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).
Diffstat (limited to 'sys/kern')
-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 80a9c20..83873af 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1885,17 +1885,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; } /* |