aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/sys_generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/sys_generic.c')
-rw-r--r--sys/kern/sys_generic.c36
1 files changed, 21 insertions, 15 deletions
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index 5606b36f772f..7d666da9f88b 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -729,7 +729,7 @@ kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data)
{
struct file *fp;
struct filedesc *fdp;
- int error, tmp, locked;
+ int error, f_flag, tmp, locked;
AUDIT_ARG_FD(fd);
AUDIT_ARG_CMD(com);
@@ -782,30 +782,36 @@ kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data)
goto out;
}
+ f_flag = 0;
switch (com) {
case FIONCLEX:
fdp->fd_ofiles[fd].fde_flags &= ~UF_EXCLOSE;
- goto out;
+ break;
case FIOCLEX:
fdp->fd_ofiles[fd].fde_flags |= UF_EXCLOSE;
- goto out;
- case FIONBIO:
- if ((tmp = *(int *)data))
- atomic_set_int(&fp->f_flag, FNONBLOCK);
- else
- atomic_clear_int(&fp->f_flag, FNONBLOCK);
- data = (void *)&tmp;
break;
+ case FIONBIO:
case FIOASYNC:
- if ((tmp = *(int *)data))
- atomic_set_int(&fp->f_flag, FASYNC);
- else
- atomic_clear_int(&fp->f_flag, FASYNC);
- data = (void *)&tmp;
+ f_flag = com == FIONBIO ? FNONBLOCK : FASYNC;
+ tmp = *(int *)data;
+ fsetfl_lock(fp);
+ if (((fp->f_flag & f_flag) != 0) != (tmp != 0)) {
+ error = fo_ioctl(fp, com, (void *)&tmp, td->td_ucred,
+ td);
+ if (error == 0) {
+ if (tmp != 0)
+ atomic_set_int(&fp->f_flag, f_flag);
+ else
+ atomic_clear_int(&fp->f_flag, f_flag);
+ }
+ }
+ fsetfl_unlock(fp);
+ break;
+ default:
+ error = fo_ioctl(fp, com, data, td->td_ucred, td);
break;
}
- error = fo_ioctl(fp, com, data, td->td_ucred, td);
out:
switch (locked) {
case LA_XLOCKED: