On 08 Apr 2015, at 02:31, Philip Guenther <guent...@gmail.com> wrote:
> On Tue, Apr 7, 2015 at 3:57 PM, Kanonenvogel <kanonenvogel....@gmail.com> > wrote: >> I have idea to modify falloc() function and related logic. >> Now, after successful faclloc call, we have half-initialized struct file >> object, protected by FIF_LARVAL flag. >> I want to initialise struct file object within falloc() and then put it to >> fd_ofiles array and filehead list. This modification >> permits to avoid half-initialization state and remove FIF_LARVAL flag and >> related logic. > > The hard case is blocking opens of fifos, as the underlying operation > involves a change visible to another process and that therefore cannot > be rolled back. > > > Philip Guenther Ok, I understood. And what about make struct file more smp friendly? For example, make operations under f_iflags and f_flags atomic? Index: kern/kern_descrip.c =================================================================== RCS file: /cvs/src/sys/kern/kern_descrip.c,v retrieving revision 1.116 diff -u -p -r1.116 kern_descrip.c --- kern/kern_descrip.c 19 Jan 2015 01:19:17 -0000 1.116 +++ kern/kern_descrip.c 8 Apr 2015 09:21:19 -0000 @@ -61,6 +61,7 @@ #include <sys/event.h> #include <sys/pool.h> #include <sys/ktrace.h> +#include <sys/atomic.h> #include <sys/pipe.h> @@ -332,6 +333,7 @@ sys_fcntl(struct proc *p, void *v, regis int i, tmp, newmin, flg = F_POSIX; struct flock fl; int error = 0; + int oflag, nflag; restart: if ((fp = fd_getfile(fdp, fd)) == NULL) @@ -384,8 +386,12 @@ restart: break; case F_SETFL: - fp->f_flag &= ~FCNTLFLAGS; - fp->f_flag |= FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS; + do { + oflag = fp->f_flag; + nflag = oflag & ~FCNTLFLAGS; + nflag |= FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS; + } while (atomic_cas_uint(&fp->f_flag, oflag, nflag) != oflag); + tmp = fp->f_flag & FNONBLOCK; error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); if (error) @@ -394,7 +400,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; @@ -1160,7 +1166,7 @@ sys_flock(struct proc *p, void *v, regis lf.l_len = 0; if (how & LOCK_UN) { lf.l_type = F_UNLCK; - fp->f_iflags &= ~FIF_HASLOCK; + atomic_clearbits_int(&fp->f_iflags, FIF_HASLOCK); error = VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK); goto out; } @@ -1172,7 +1178,7 @@ sys_flock(struct proc *p, void *v, regis error = EINVAL; goto out; } - fp->f_iflags |= FIF_HASLOCK; + atomic_setbits_int(&fp->f_iflags, FIF_HASLOCK); if (how & LOCK_NB) error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK); else Index: kern/sys_generic.c =================================================================== RCS file: /cvs/src/sys/kern/sys_generic.c,v retrieving revision 1.96 diff -u -p -r1.96 sys_generic.c --- kern/sys_generic.c 12 Feb 2015 22:27:04 -0000 1.96 +++ kern/sys_generic.c 8 Apr 2015 09:21:19 -0000 @@ -52,6 +52,7 @@ #include <sys/stat.h> #include <sys/malloc.h> #include <sys/poll.h> +#include <sys/atomic.h> #ifdef KTRACE #include <sys/ktrace.h> #endif @@ -456,17 +457,17 @@ sys_ioctl(struct proc *p, void *v, regis case FIONBIO: if ((tmp = *(int *)data) != 0) - fp->f_flag |= FNONBLOCK; + atomic_setbits_int(&fp->f_flag, FNONBLOCK); else - fp->f_flag &= ~FNONBLOCK; + atomic_clearbits_int(&fp->f_flag, FNONBLOCK); error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); break; case FIOASYNC: if ((tmp = *(int *)data) != 0) - fp->f_flag |= FASYNC; + atomic_setbits_int(&fp->f_flag, FASYNC); else - fp->f_flag &= ~FASYNC; + atomic_clearbits_int(&fp->f_flag, FASYNC); error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); break; Index: kern/uipc_usrreq.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_usrreq.c,v retrieving revision 1.79 diff -u -p -r1.79 uipc_usrreq.c --- kern/uipc_usrreq.c 11 Dec 2014 19:21:57 -0000 1.79 +++ kern/uipc_usrreq.c 8 Apr 2015 09:21:19 -0000 @@ -884,11 +884,11 @@ unp_gc(void) unp_gcing = 1; unp_defer = 0; LIST_FOREACH(fp, &filehead, f_list) - fp->f_iflags &= ~(FIF_MARK|FIF_DEFER); + atomic_clearbits_int(&fp->f_iflags, FIF_MARK|FIF_DEFER); do { LIST_FOREACH(fp, &filehead, f_list) { if (fp->f_iflags & FIF_DEFER) { - fp->f_iflags &= ~FIF_DEFER; + atomic_clearbits_int(&fp->f_iflags, FIF_DEFER); unp_defer--; } else { if (fp->f_count == 0) @@ -898,7 +898,7 @@ unp_gc(void) if (fp->f_count == fp->f_msgcount) continue; } - fp->f_iflags |= FIF_MARK; + atomic_setbits_int(&fp->f_iflags, FIF_MARK); if (fp->f_type != DTYPE_SOCKET || (so = fp->f_data) == NULL) @@ -1040,9 +1040,9 @@ unp_mark(struct file *fp) if (fp->f_type == DTYPE_SOCKET) { unp_defer++; - fp->f_iflags |= FIF_DEFER; + atomic_setbits_int(&fp->f_iflags, FIF_DEFER); } else { - fp->f_iflags |= FIF_MARK; + atomic_setbits_int(&fp->f_iflags, FIF_MARK); } } Index: kern/vfs_syscalls.c =================================================================== RCS file: /cvs/src/sys/kern/vfs_syscalls.c,v retrieving revision 1.216 diff -u -p -r1.216 vfs_syscalls.c --- kern/vfs_syscalls.c 16 Dec 2014 18:30:04 -0000 1.216 +++ kern/vfs_syscalls.c 8 Apr 2015 09:21:19 -0000 @@ -901,7 +901,7 @@ doopenat(struct proc *p, int fd, const c goto out; } vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); - fp->f_iflags |= FIF_HASLOCK; + atomic_setbits_int(&fp->f_iflags, FIF_HASLOCK); } if (localtrunc) { if ((fp->f_flag & FWRITE) == 0) @@ -1083,7 +1083,7 @@ sys_fhopen(struct proc *p, void *v, regi goto bad; } vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); - fp->f_iflags |= FIF_HASLOCK; + atomic_setbits_int(&fp->f_iflags, FIF_HASLOCK); } VOP_UNLOCK(vp, 0, p); *retval = indx; Index: sys/file.h =================================================================== RCS file: /cvs/src/sys/sys/file.h,v retrieving revision 1.34 diff -u -p -r1.34 file.h --- sys/file.h 18 Nov 2014 15:16:35 -0000 1.34 +++ sys/file.h 8 Apr 2015 09:21:23 -0000 @@ -63,7 +63,7 @@ struct fileops { */ struct file { LIST_ENTRY(file) f_list;/* list of active files */ - short f_flag; /* see fcntl.h */ + volatile int f_flag; /* see fcntl.h */ #define DTYPE_VNODE 1 /* file */ #define DTYPE_SOCKET 2 /* communications endpoint */ #define DTYPE_PIPE 3 /* pipe */ @@ -77,7 +77,7 @@ struct file { struct fileops *f_ops; off_t f_offset; void *f_data; /* private data */ - int f_iflags; /* internal flags */ + volatile int f_iflags; /* internal flags */ u_int64_t f_rxfer; /* total number of read transfers */ u_int64_t f_wxfer; /* total number of write transfers */ u_int64_t f_seek; /* total independent seek operations */ @@ -96,9 +96,9 @@ struct file { #define FREF(fp) do { (fp)->f_count++; } while (0) #define FRELE(fp,p) (--(fp)->f_count == 0 ? fdrop(fp, p) : 0) -#define FILE_SET_MATURE(fp,p) do { \ - (fp)->f_iflags &= ~FIF_LARVAL; \ - FRELE(fp, p); \ +#define FILE_SET_MATURE(_fp, _p) do { \ + atomic_clearbits_int(&(_fp)->f_iflags, FIF_LARVAL); \ + FRELE(_fp, _p); \ } while (0) int fdrop(struct file *, struct proc *);