diff options
author | kib <kib@FreeBSD.org> | 2012-07-02 21:01:03 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2012-07-02 21:01:03 +0000 |
commit | 53224f018aac13056c11af9d1233317b1754149c (patch) | |
tree | 26c1ae1ac3dde3bf8b9b01fad04caad427a4ef48 /sys/compat | |
parent | 293bf50336e246390039b341f229e30d00d97d27 (diff) | |
download | FreeBSD-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/compat')
-rw-r--r-- | sys/compat/linux/linux_file.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c index 67b1b38..b0c2e4a 100644 --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -357,15 +357,16 @@ getdents_common(struct thread *td, struct linux_getdents64_args *args, return (EBADF); } + off = foffset_lock(fp, 0); vp = fp->f_vnode; vfslocked = VFS_LOCK_GIANT(vp->v_mount); if (vp->v_type != VDIR) { VFS_UNLOCK_GIANT(vfslocked); + foffset_unlock(fp, off, 0); fdrop(fp, td); return (EINVAL); } - off = fp->f_offset; buflen = max(LINUX_DIRBLKSIZ, nbytes); buflen = min(buflen, MAXBSIZE); @@ -514,7 +515,6 @@ getdents_common(struct thread *td, struct linux_getdents64_args *args, goto eof; } - fp->f_offset = off; if (justone) nbytes = resid + linuxreclen; @@ -527,6 +527,7 @@ out: VOP_UNLOCK(vp, 0); VFS_UNLOCK_GIANT(vfslocked); + foffset_unlock(fp, off, 0); fdrop(fp, td); free(buf, M_TEMP); free(lbuf, M_TEMP); |