diff options
author | anton <anton@cvs.openbsd.org> | 2020-02-01 08:57:28 +0000 |
---|---|---|
committer | anton <anton@cvs.openbsd.org> | 2020-02-01 08:57:28 +0000 |
commit | 2dd5b6f6d2fe28d357a44b374f7c53c6061f228d (patch) | |
tree | e7b4afeea485c3ba4b2b2426d4262377adca73cf /sys/kern/kern_descrip.c | |
parent | 16d868fc8be2c951c63f512ca2434c1628fa3ec6 (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.c | 13 |
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; |