summaryrefslogtreecommitdiffstats
path: root/sys/fs/devfs
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2012-07-02 21:01:03 +0000
committerkib <kib@FreeBSD.org>2012-07-02 21:01:03 +0000
commit53224f018aac13056c11af9d1233317b1754149c (patch)
tree26c1ae1ac3dde3bf8b9b01fad04caad427a4ef48 /sys/fs/devfs
parent293bf50336e246390039b341f229e30d00d97d27 (diff)
downloadFreeBSD-src-53224f018aac13056c11af9d1233317b1754149c.zip
FreeBSD-src-53224f018aac13056c11af9d1233317b1754149c.tar.gz
Extend the KPI to lock and unlock f_offset member of struct file. It
now fully encapsulates all accesses to f_offset, and extends f_offset locking to other consumers that need it, in particular, to lseek() and variants of getdirentries(). Ensure that on 32bit architectures f_offset, which is 64bit quantity, always read and written under the mtxpool protection. This fixes apparently easy to trigger race when parallel lseek()s or lseek() and read/write could destroy file offset. The already broken ABI emulations, including iBCS and SysV, are not converted (yet). Tested by: pho No objections from: jhb MFC after: 3 weeks
Diffstat (limited to 'sys/fs/devfs')
-rw-r--r--sys/fs/devfs/devfs_vnops.c15
1 files changed, 4 insertions, 11 deletions
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index 4a58a42..d3e6cf5 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -1170,18 +1170,14 @@ devfs_read_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, st
if (ioflag & O_DIRECT)
ioflag |= IO_DIRECT;
- if ((flags & FOF_OFFSET) == 0)
- uio->uio_offset = fp->f_offset;
-
+ foffset_lock_uio(fp, uio, flags | FOF_NOLOCK);
error = dsw->d_read(dev, uio, ioflag);
if (uio->uio_resid != resid || (error == 0 && resid != 0))
vfs_timestamp(&dev->si_atime);
td->td_fpop = fpop;
dev_relthread(dev, ref);
- if ((flags & FOF_OFFSET) == 0)
- fp->f_offset = uio->uio_offset;
- fp->f_nextoff = uio->uio_offset;
+ foffset_unlock_uio(fp, uio, flags | FOF_NOLOCK | FOF_NEXTOFF);
return (error);
}
@@ -1648,8 +1644,7 @@ devfs_write_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, s
ioflag = fp->f_flag & (O_NONBLOCK | O_DIRECT | O_FSYNC);
if (ioflag & O_DIRECT)
ioflag |= IO_DIRECT;
- if ((flags & FOF_OFFSET) == 0)
- uio->uio_offset = fp->f_offset;
+ foffset_lock_uio(fp, uio, flags | FOF_NOLOCK);
resid = uio->uio_resid;
@@ -1661,9 +1656,7 @@ devfs_write_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, s
td->td_fpop = fpop;
dev_relthread(dev, ref);
- if ((flags & FOF_OFFSET) == 0)
- fp->f_offset = uio->uio_offset;
- fp->f_nextoff = uio->uio_offset;
+ foffset_unlock_uio(fp, uio, flags | FOF_NOLOCK | FOF_NEXTOFF);
return (error);
}
OpenPOWER on IntegriCloud