On Fri, Jul 12, 2019 at 03:29:53PM +0200, Solene Rapenne wrote: > On Fri, Jul 12, 2019 at 11:09:20AM +0200, Solene Rapenne wrote: > > >Synopsis: problem with cat - | tee > > >Environment: > > System : OpenBSD 6.5 > > Details : OpenBSD 6.5-current (GENERIC.MP) #127: Thu Jul 11 > > 15:44:36 MDT 2019 > > > > [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP > > > > Architecture: OpenBSD.amd64 > > Machine : amd64 > > >Description: > > There is a behavior change with "cat - | tee foobar" since 6.5 and > > 25th June snapshot. > > > > cat - > foobar works correctly. > > > > I stumbled on this because for some reasons, I have a command > > sending text to ed and then use cat - to allow me continue input > > within ed(1): > > ( echo a ; date '+%s;' | tr -d '\n' ; cat - ) | ed file > > > > I've been able to reduce it to cat - | tee file for reproducing the > > bug. > > > > reverting anton@ diff about file offset changes make it work again.
Sorry about that. Currently at $DAYJOB but can backout later this evening, if noone beats me to it. Here's the backout diff: Index: dev/pci/drm/drm_linux.c =================================================================== RCS file: /cvs/src/sys/dev/pci/drm/drm_linux.c,v retrieving revision 1.43 diff -u -p -r1.43 drm_linux.c --- dev/pci/drm/drm_linux.c 10 Jul 2019 16:43:19 -0000 1.43 +++ dev/pci/drm/drm_linux.c 12 Jul 2019 10:27:31 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: drm_linux.c,v 1.43 2019/07/10 16:43:19 anton Exp $ */ +/* $OpenBSD: drm_linux.c,v 1.42 2019/07/10 07:56:30 kettenis Exp $ */ /* * Copyright (c) 2013 Jonathan Gray <[email protected]> * Copyright (c) 2015, 2016 Mark Kettenis <[email protected]> @@ -1346,9 +1346,7 @@ dmabuf_seek(struct file *fp, off_t *offs default: return (EINVAL); } - foffset_enter(fp); - foffset_leave(fp, newoff, 0); - *offset = newoff; + fp->f_offset = *offset = newoff; return (0); } Index: isofs/cd9660/cd9660_vnops.c =================================================================== RCS file: /cvs/src/sys/isofs/cd9660/cd9660_vnops.c,v retrieving revision 1.77 diff -u -p -r1.77 cd9660_vnops.c --- isofs/cd9660/cd9660_vnops.c 10 Jul 2019 16:43:19 -0000 1.77 +++ isofs/cd9660/cd9660_vnops.c 12 Jul 2019 10:27:31 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: cd9660_vnops.c,v 1.77 2019/07/10 16:43:19 anton Exp $ */ +/* $OpenBSD: cd9660_vnops.c,v 1.76 2016/06/19 11:54:33 natano Exp $ */ /* $NetBSD: cd9660_vnops.c,v 1.42 1997/10/16 23:56:57 christos Exp $ */ /*- @@ -1016,7 +1016,7 @@ filt_cd9660read(struct knote *kn, long h return (1); } - kn->kn_data = node->i_size - foffset_get(kn->kn_fp); + kn->kn_data = node->i_size - kn->kn_fp->f_offset; if (kn->kn_data == 0 && kn->kn_sfflags & NOTE_EOF) { kn->kn_fflags |= NOTE_EOF; return (1); Index: kern/kern_descrip.c =================================================================== RCS file: /cvs/src/sys/kern/kern_descrip.c,v retrieving revision 1.189 diff -u -p -r1.189 kern_descrip.c --- kern/kern_descrip.c 10 Jul 2019 16:43:19 -0000 1.189 +++ kern/kern_descrip.c 12 Jul 2019 10:27:31 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_descrip.c,v 1.189 2019/07/10 16:43:19 anton Exp $ */ +/* $OpenBSD: kern_descrip.c,v 1.188 2019/07/03 14:32:02 visa Exp $ */ /* $NetBSD: kern_descrip.c,v 1.42 1996/03/30 22:24:38 christos Exp $ */ /* @@ -532,14 +532,12 @@ restart: ktrflock(p, &fl); #endif if (fl.l_whence == SEEK_CUR) { - off_t offset = foffset_get(fp); - if (fl.l_start == 0 && fl.l_len < 0) { /* lockf(3) compliance hack */ fl.l_len = -fl.l_len; - fl.l_start = offset - fl.l_len; + fl.l_start = fp->f_offset - fl.l_len; } else - fl.l_start += offset; + fl.l_start += fp->f_offset; } switch (fl.l_type) { @@ -604,14 +602,12 @@ restart: if (error) break; if (fl.l_whence == SEEK_CUR) { - off_t offset = foffset_get(fp); - if (fl.l_start == 0 && fl.l_len < 0) { /* lockf(3) compliance hack */ fl.l_len = -fl.l_len; - fl.l_start = offset - fl.l_len; + fl.l_start = fp->f_offset - fl.l_len; } else - fl.l_start += offset; + fl.l_start += fp->f_offset; } if (fl.l_type != F_RDLCK && fl.l_type != F_WRLCK && @@ -1278,73 +1274,6 @@ fdrop(struct file *fp, struct proc *p) pool_put(&file_pool, fp); return (error); -} - -/* - * Get the file offset without keeping the same offset locked upon return. - */ -off_t -foffset_get(struct file *fp) -{ - off_t offset; - - mtx_enter(&fp->f_mtx); - offset = fp->f_offset; - mtx_leave(&fp->f_mtx); - return (offset); -} - -/* - * Acquire an exclusive lock of the file offset. The calling thread must call - * foffset_leave() once done. - */ -off_t -foffset_enter(struct file *fp) -{ - off_t offset; - - mtx_enter(&fp->f_mtx); - - while (fp->f_olock & FOL_LOCKED) { - KASSERT((fp->f_olock & FOL_NWAIT) < FOL_NWAIT); - fp->f_olock++; - msleep(&fp->f_olock, &fp->f_mtx, PLOCK, "foffset", 0); - KASSERT((fp->f_olock & FOL_NWAIT) > 0); - fp->f_olock--; - } - fp->f_olock |= FOL_LOCKED; - - offset = fp->f_offset; - - mtx_leave(&fp->f_mtx); - - return (offset); -} - -/* - * Write a new file offset and release the lock. The calling thread must already - * have acquired the lock using foffset_enter(). - * If FO_NOUPDATE is present in flags, only the lock is released and the offset - * remains unmodified. - */ -void -foffset_leave(struct file *fp, off_t offset, int flags) -{ - unsigned int nwait; - - mtx_enter(&fp->f_mtx); - - KASSERT(fp->f_olock & FOL_LOCKED); - - if ((flags & FO_NOUPDATE) == 0) - fp->f_offset = offset; - nwait = fp->f_olock & FOL_NWAIT; - fp->f_olock &= ~FOL_LOCKED; - - mtx_leave(&fp->f_mtx); - - if (nwait > 0) - wakeup_one(&fp->f_olock); } /* Index: kern/kern_sysctl.c =================================================================== RCS file: /cvs/src/sys/kern/kern_sysctl.c,v retrieving revision 1.362 diff -u -p -r1.362 kern_sysctl.c --- kern/kern_sysctl.c 12 Jul 2019 00:04:59 -0000 1.362 +++ kern/kern_sysctl.c 12 Jul 2019 10:27:31 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sysctl.c,v 1.362 2019/07/12 00:04:59 cheloha Exp $ */ +/* $OpenBSD: kern_sysctl.c,v 1.360 2019/06/16 00:56:53 bluhm Exp $ */ /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ /*- @@ -1102,8 +1102,8 @@ fill_file(struct kinfo_file *kf, struct kf->f_usecount = 0; if (suser(p) == 0 || p->p_ucred->cr_uid == fp->f_cred->cr_uid) { - mtx_enter(&fp->f_mtx); kf->f_offset = fp->f_offset; + mtx_enter(&fp->f_mtx); kf->f_rxfer = fp->f_rxfer; kf->f_rwfer = fp->f_wxfer; kf->f_seek = fp->f_seek; Index: kern/vfs_syscalls.c =================================================================== RCS file: /cvs/src/sys/kern/vfs_syscalls.c,v retrieving revision 1.320 diff -u -p -r1.320 vfs_syscalls.c --- kern/vfs_syscalls.c 10 Jul 2019 16:43:19 -0000 1.320 +++ kern/vfs_syscalls.c 12 Jul 2019 10:27:31 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_syscalls.c,v 1.320 2019/07/10 16:43:19 anton Exp $ */ +/* $OpenBSD: vfs_syscalls.c,v 1.319 2019/06/19 16:55:51 deraadt Exp $ */ /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ /* @@ -2999,7 +2999,6 @@ sys_getdents(struct proc *p, void *v, re struct uio auio; struct iovec aiov; size_t buflen; - off_t offset; int error, eofflag; buflen = SCARG(uap, buflen); @@ -3012,16 +3011,12 @@ sys_getdents(struct proc *p, void *v, re error = EBADF; goto bad; } - - offset = foffset_enter(fp); - if (offset < 0) { - foffset_leave(fp, 0, FO_NOUPDATE); + if (fp->f_offset < 0) { error = EINVAL; goto bad; } vp = fp->f_data; if (vp->v_type != VDIR) { - foffset_leave(fp, 0, FO_NOUPDATE); error = EINVAL; goto bad; } @@ -3034,10 +3029,10 @@ sys_getdents(struct proc *p, void *v, re auio.uio_procp = p; auio.uio_resid = buflen; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - auio.uio_offset = offset; + auio.uio_offset = fp->f_offset; error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag); + fp->f_offset = auio.uio_offset; VOP_UNLOCK(vp); - foffset_leave(fp, auio.uio_offset, 0); if (error) goto bad; *retval = buflen - auio.uio_resid; Index: kern/vfs_vnops.c =================================================================== RCS file: /cvs/src/sys/kern/vfs_vnops.c,v retrieving revision 1.100 diff -u -p -r1.100 vfs_vnops.c --- kern/vfs_vnops.c 10 Jul 2019 16:43:19 -0000 1.100 +++ kern/vfs_vnops.c 12 Jul 2019 10:27:31 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_vnops.c,v 1.100 2019/07/10 16:43:19 anton Exp $ */ +/* $OpenBSD: vfs_vnops.c,v 1.99 2019/06/22 06:48:25 semarie Exp $ */ /* $NetBSD: vfs_vnops.c,v 1.20 1996/02/04 02:18:41 christos Exp $ */ /* @@ -342,35 +342,38 @@ vn_read(struct file *fp, struct uio *uio size_t count = uio->uio_resid; off_t offset; int error; - int foflags = 0; KERNEL_LOCK(); + /* + * Check below can race. We can block on the vnode lock + * and resume with a different `fp->f_offset' value. + */ if ((fflags & FO_POSITION) == 0) - uio->uio_offset = offset = foffset_enter(fp); + offset = fp->f_offset; else offset = uio->uio_offset; /* no wrap around of offsets except on character devices */ if (vp->v_type != VCHR && count > LLONG_MAX - offset) { - foflags = FO_NOUPDATE; error = EINVAL; goto done; } if (vp->v_type == VDIR) { - foflags = FO_NOUPDATE; error = EISDIR; goto done; } vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + if ((fflags & FO_POSITION) == 0) + uio->uio_offset = fp->f_offset; error = VOP_READ(vp, uio, (fp->f_flag & FNONBLOCK) ? IO_NDELAY : 0, cred); + if ((fflags & FO_POSITION) == 0) + fp->f_offset += count - uio->uio_resid; VOP_UNLOCK(vp); done: - if ((fflags & FO_POSITION) == 0) - foffset_leave(fp, offset + (count - uio->uio_resid), foflags); KERNEL_UNLOCK(); return (error); } @@ -383,15 +386,11 @@ vn_write(struct file *fp, struct uio *ui { struct vnode *vp = fp->f_data; struct ucred *cred = fp->f_cred; - off_t offset; int error, ioflag = IO_UNIT; size_t count; KERNEL_LOCK(); - if ((fflags & FO_POSITION) == 0) - uio->uio_offset = offset = foffset_enter(fp); - /* note: pwrite/pwritev are unaffected by O_APPEND */ if (vp->v_type == VREG && (fp->f_flag & O_APPEND) && (fflags & FO_POSITION) == 0) @@ -402,15 +401,17 @@ vn_write(struct file *fp, struct uio *ui (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS))) ioflag |= IO_SYNC; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + if ((fflags & FO_POSITION) == 0) + uio->uio_offset = fp->f_offset; count = uio->uio_resid; error = VOP_WRITE(vp, uio, ioflag, cred); - VOP_UNLOCK(vp); if ((fflags & FO_POSITION) == 0) { if (ioflag & IO_APPEND) - foffset_leave(fp, uio->uio_offset, 0); + fp->f_offset = uio->uio_offset; else - foffset_leave(fp, offset + (count - uio->uio_resid), 0); + fp->f_offset += count - uio->uio_resid; } + VOP_UNLOCK(vp); KERNEL_UNLOCK(); return (error); @@ -508,7 +509,7 @@ vn_ioctl(struct file *fp, u_long com, ca error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); if (error) return (error); - *(int *)data = vattr.va_size - foffset_get(fp); + *(int *)data = vattr.va_size - fp->f_offset; return (0); } if (com == FIONBIO || com == FIOASYNC) /* XXX */ @@ -600,7 +601,7 @@ vn_seek(struct file *fp, off_t *offset, struct ucred *cred = p->p_ucred; struct vnode *vp = fp->f_data; struct vattr vattr; - off_t curoff, newoff; + off_t newoff; int error, special; if (vp->v_type == VFIFO) @@ -610,35 +611,28 @@ vn_seek(struct file *fp, off_t *offset, else special = 0; - curoff = foffset_enter(fp); switch (whence) { case SEEK_CUR: - newoff = curoff + *offset; + newoff = fp->f_offset + *offset; break; case SEEK_END: error = VOP_GETATTR(vp, &vattr, cred, p); if (error) - goto bad; + return (error); newoff = *offset + (off_t)vattr.va_size; break; case SEEK_SET: newoff = *offset; break; default: - error = EINVAL; - goto bad; + return (EINVAL); } - if (!special && newoff < 0) { - error = EINVAL; - goto bad; + if (!special) { + if (newoff < 0) + return(EINVAL); } - foffset_leave(fp, newoff, 0); - *offset = newoff; + fp->f_offset = *offset = newoff; return (0); - -bad: - foffset_leave(fp, 0, FO_NOUPDATE); - return (error); } /* Index: miscfs/fuse/fuse_vnops.c =================================================================== RCS file: /cvs/src/sys/miscfs/fuse/fuse_vnops.c,v retrieving revision 1.53 diff -u -p -r1.53 fuse_vnops.c --- miscfs/fuse/fuse_vnops.c 10 Jul 2019 16:43:19 -0000 1.53 +++ miscfs/fuse/fuse_vnops.c 12 Jul 2019 10:27:32 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: fuse_vnops.c,v 1.53 2019/07/10 16:43:19 anton Exp $ */ +/* $OpenBSD: fuse_vnops.c,v 1.52 2018/07/18 10:47:02 helg Exp $ */ /* * Copyright (c) 2012-2013 Sylvestre Gallon <[email protected]> * @@ -168,7 +168,7 @@ filt_fusefsread(struct knote *kn, long h return (1); } - kn->kn_data = ip->filesize - foffset_get(kn->kn_fp); + kn->kn_data = ip->filesize - kn->kn_fp->f_offset; if (kn->kn_data == 0 && kn->kn_sfflags & NOTE_EOF) { kn->kn_fflags |= NOTE_EOF; return (1); Index: msdosfs/msdosfs_vnops.c =================================================================== RCS file: /cvs/src/sys/msdosfs/msdosfs_vnops.c,v retrieving revision 1.123 diff -u -p -r1.123 msdosfs_vnops.c --- msdosfs/msdosfs_vnops.c 10 Jul 2019 16:43:19 -0000 1.123 +++ msdosfs/msdosfs_vnops.c 12 Jul 2019 10:27:32 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: msdosfs_vnops.c,v 1.123 2019/07/10 16:43:19 anton Exp $ */ +/* $OpenBSD: msdosfs_vnops.c,v 1.122 2018/06/21 14:17:23 visa Exp $ */ /* $NetBSD: msdosfs_vnops.c,v 1.63 1997/10/17 11:24:19 ws Exp $ */ /*- @@ -2017,7 +2017,7 @@ filt_msdosfsread(struct knote *kn, long return (1); } - kn->kn_data = dep->de_FileSize - foffset_get(kn->kn_fp); + kn->kn_data = dep->de_FileSize - kn->kn_fp->f_offset; if (kn->kn_data == 0 && kn->kn_sfflags & NOTE_EOF) { kn->kn_fflags |= NOTE_EOF; return (1); Index: nfs/nfs_kq.c =================================================================== RCS file: /cvs/src/sys/nfs/nfs_kq.c,v retrieving revision 1.23 diff -u -p -r1.23 nfs_kq.c --- nfs/nfs_kq.c 10 Jul 2019 16:43:20 -0000 1.23 +++ nfs/nfs_kq.c 12 Jul 2019 10:27:32 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_kq.c,v 1.23 2019/07/10 16:43:20 anton Exp $ */ +/* $OpenBSD: nfs_kq.c,v 1.22 2014/11/15 00:03:12 tedu Exp $ */ /* $NetBSD: nfs_kq.c,v 1.7 2003/10/30 01:43:10 simonb Exp $ */ /*- @@ -226,7 +226,7 @@ filt_nfsread(struct knote *kn, long hint return (1); } - kn->kn_data = np->n_size - foffset_get(kn->kn_fp); + kn->kn_data = np->n_size - kn->kn_fp->f_offset; #ifdef DEBUG printf("nfsread event. %lld\n", kn->kn_data); #endif Index: sys/file.h =================================================================== RCS file: /cvs/src/sys/sys/file.h,v retrieving revision 1.56 diff -u -p -r1.56 file.h --- sys/file.h 11 Jul 2019 06:15:02 -0000 1.56 +++ sys/file.h 12 Jul 2019 10:27:32 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: file.h,v 1.56 2019/07/11 06:15:02 anton Exp $ */ +/* $OpenBSD: file.h,v 1.54 2019/06/22 06:48:25 semarie Exp $ */ /* $NetBSD: file.h,v 1.11 1995/03/26 20:24:13 jtc Exp $ */ /* @@ -64,7 +64,6 @@ struct fileops { int (*fo_seek)(struct file *, off_t *, int, struct proc *); }; #define FO_POSITION 0x00000001 /* positioned read/write */ -#define FO_NOUPDATE 0x00000002 /* don't update file offset */ /* * Kernel descriptor table. @@ -90,9 +89,8 @@ struct file { u_int f_count; /* [a] reference count */ struct ucred *f_cred; /* [I] credentials associated with descriptor */ struct fileops *f_ops; /* [I] file operation pointers */ - off_t f_offset; /* [f] */ + off_t f_offset; /* [k] */ void *f_data; /* [I] private data */ - u_int f_olock; /* [f] offset lock */ int f_iflags; /* [k] internal flags */ uint64_t f_rxfer; /* [f] total number of read transfers */ uint64_t f_wxfer; /* [f] total number of write transfers */ @@ -117,13 +115,6 @@ struct file { #define FDUP_MAX_COUNT (UINT_MAX - 2 * MAXCPUS) int fdrop(struct file *, struct proc *); - -off_t foffset_get(struct file *); -off_t foffset_enter(struct file *); -void foffset_leave(struct file *, off_t, int); - -#define FOL_NWAIT 0x7fffffffu /* number of waiters */ -#define FOL_LOCKED 0x80000000u /* file offset is locked */ LIST_HEAD(filelist, file); extern int maxfiles; /* kernel limit on number of open files */ Index: tmpfs/tmpfs_vnops.c =================================================================== RCS file: /cvs/src/sys/tmpfs/tmpfs_vnops.c,v retrieving revision 1.34 diff -u -p -r1.34 tmpfs_vnops.c --- tmpfs/tmpfs_vnops.c 10 Jul 2019 16:43:20 -0000 1.34 +++ tmpfs/tmpfs_vnops.c 12 Jul 2019 10:27:32 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: tmpfs_vnops.c,v 1.34 2019/07/10 16:43:20 anton Exp $ */ +/* $OpenBSD: tmpfs_vnops.c,v 1.33 2018/10/22 17:31:25 krw Exp $ */ /* $NetBSD: tmpfs_vnops.c,v 1.100 2012/11/05 17:27:39 dholland Exp $ */ /* @@ -2645,7 +2645,7 @@ filt_tmpfsread(struct knote *kn, long hi return (1); } - kn->kn_data = node->tn_size - foffset_get(kn->kn_fp); + kn->kn_data = node->tn_size - kn->kn_fp->f_offset; if (kn->kn_data == 0 && kn->kn_sfflags & NOTE_EOF) { kn->kn_fflags |= NOTE_EOF; return (1); Index: ufs/ufs/ufs_vnops.c =================================================================== RCS file: /cvs/src/sys/ufs/ufs/ufs_vnops.c,v retrieving revision 1.144 diff -u -p -r1.144 ufs_vnops.c --- ufs/ufs/ufs_vnops.c 10 Jul 2019 16:43:20 -0000 1.144 +++ ufs/ufs/ufs_vnops.c 12 Jul 2019 10:27:32 -0000 @@ -1,4 +1,4 @@ -/* $OpenBSD: ufs_vnops.c,v 1.144 2019/07/10 16:43:20 anton Exp $ */ +/* $OpenBSD: ufs_vnops.c,v 1.143 2018/12/23 10:46:51 natano Exp $ */ /* $NetBSD: ufs_vnops.c,v 1.18 1996/05/11 18:28:04 mycroft Exp $ */ /* @@ -1952,10 +1952,10 @@ filt_ufsread(struct knote *kn, long hint #ifdef EXT2FS if (IS_EXT2_VNODE(ip->i_vnode)) - kn->kn_data = ext2fs_size(ip) - foffset_get(kn->kn_fp); + kn->kn_data = ext2fs_size(ip) - kn->kn_fp->f_offset; else #endif - kn->kn_data = DIP(ip, size) - foffset_get(kn->kn_fp); + kn->kn_data = DIP(ip, size) - kn->kn_fp->f_offset; if (kn->kn_data == 0 && kn->kn_sfflags & NOTE_EOF) { kn->kn_fflags |= NOTE_EOF; return (1);
