aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/kern_descrip.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r--sys/kern/kern_descrip.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 07984b9a4640..da1eb24cf9c8 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -4194,9 +4194,9 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS)
if (fdp == NULL)
continue;
FILEDESC_SLOCK(fdp);
+ if (refcount_load(&fdp->fd_refcnt) == 0)
+ goto nextproc;
FILEDESC_FOREACH_FP(fdp, n, fp) {
- if (refcount_load(&fdp->fd_refcnt) == 0)
- break;
xf.xf_fd = n;
xf.xf_file = (uintptr_t)fp;
xf.xf_data = (uintptr_t)fp->f_data;
@@ -4207,9 +4207,16 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS)
xf.xf_offset = foffset_get(fp);
xf.xf_flag = fp->f_flag;
error = SYSCTL_OUT(req, &xf, sizeof(xf));
- if (error)
+
+ /*
+ * There is no need to re-check the fdtable refcount
+ * here since the filedesc lock is not dropped in the
+ * loop body.
+ */
+ if (error != 0)
break;
}
+nextproc:
FILEDESC_SUNLOCK(fdp);
fddrop(fdp);
if (error)
@@ -4469,9 +4476,9 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
if (pwd != NULL)
pwd_drop(pwd);
FILEDESC_SLOCK(fdp);
+ if (refcount_load(&fdp->fd_refcnt) == 0)
+ goto skip;
FILEDESC_FOREACH_FP(fdp, i, fp) {
- if (refcount_load(&fdp->fd_refcnt) == 0)
- break;
#ifdef CAPABILITIES
rights = *cap_rights(fdp, i);
#else /* !CAPABILITIES */
@@ -4484,9 +4491,10 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
* loop continues.
*/
error = export_file_to_sb(fp, i, &rights, efbuf);
- if (error != 0)
+ if (error != 0 || refcount_load(&fdp->fd_refcnt) == 0)
break;
}
+skip:
FILEDESC_SUNLOCK(fdp);
fail:
if (fdp != NULL)
@@ -4633,18 +4641,19 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
if (pwd != NULL)
pwd_drop(pwd);
FILEDESC_SLOCK(fdp);
+ if (refcount_load(&fdp->fd_refcnt) == 0)
+ goto skip;
FILEDESC_FOREACH_FP(fdp, i, fp) {
- if (refcount_load(&fdp->fd_refcnt) == 0)
- break;
export_file_to_kinfo(fp, i, NULL, kif, fdp,
KERN_FILEDESC_PACK_KINFO);
FILEDESC_SUNLOCK(fdp);
kinfo_to_okinfo(kif, okif);
error = SYSCTL_OUT(req, okif, sizeof(*okif));
FILEDESC_SLOCK(fdp);
- if (error)
+ if (error != 0 || refcount_load(&fdp->fd_refcnt) == 0)
break;
}
+skip:
FILEDESC_SUNLOCK(fdp);
fddrop(fdp);
pddrop(pdp);