summaryrefslogtreecommitdiff
path: root/sys/kern/kern_descrip.c
diff options
context:
space:
mode:
authoranton <anton@cvs.openbsd.org>2020-02-01 08:57:28 +0000
committeranton <anton@cvs.openbsd.org>2020-02-01 08:57:28 +0000
commit2dd5b6f6d2fe28d357a44b374f7c53c6061f228d (patch)
treee7b4afeea485c3ba4b2b2426d4262377adca73cf /sys/kern/kern_descrip.c
parent16d868fc8be2c951c63f512ca2434c1628fa3ec6 (diff)
Make writes to the f_flag field of `struct file' MP-safe using atomic
operations. Since the type of f_flag must change in order to use the atomic(9) API, reorder the struct in order to avoid padding; as pointed out by tedu@. ok mpi@ visa@
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r--sys/kern/kern_descrip.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 1de195a2851..9a35e7c1e13 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_descrip.c,v 1.196 2020/01/08 16:45:28 visa Exp $ */
+/* $OpenBSD: kern_descrip.c,v 1.197 2020/02/01 08:57:27 anton Exp $ */
/* $NetBSD: kern_descrip.c,v 1.42 1996/03/30 22:24:38 christos Exp $ */
/*
@@ -410,7 +410,7 @@ sys_fcntl(struct proc *p, void *v, register_t *retval)
struct filedesc *fdp = p->p_fd;
struct file *fp;
struct vnode *vp;
- int i, tmp, newmin, flg = F_POSIX;
+ int i, prev, tmp, newmin, flg = F_POSIX;
struct flock fl;
int error = 0;
@@ -480,8 +480,11 @@ restart:
break;
case F_SETFL:
- fp->f_flag &= ~FCNTLFLAGS;
- fp->f_flag |= FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS;
+ do {
+ tmp = prev = fp->f_flag;
+ tmp &= ~FCNTLFLAGS;
+ tmp |= FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS;
+ } while (atomic_cas_uint(&fp->f_flag, prev, tmp) != prev);
tmp = fp->f_flag & FNONBLOCK;
error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
if (error)
@@ -490,7 +493,7 @@ restart:
error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
if (!error)
break;
- fp->f_flag &= ~FNONBLOCK;
+ atomic_clearbits_int(&fp->f_flag, FNONBLOCK);
tmp = 0;
(void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
break;