summaryrefslogtreecommitdiffstats
path: root/contrib/gcc
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2012-06-21 09:19:41 +0000
committerkib <kib@FreeBSD.org>2012-06-21 09:19:41 +0000
commitdf9f3d2faa1df2bb13d274183876fe227e259a65 (patch)
treef333c89c12a01492f7498427b3750b2549eacc1b /contrib/gcc
parent2a52af28e66573a140482815c762bae088491ab9 (diff)
downloadFreeBSD-src-df9f3d2faa1df2bb13d274183876fe227e259a65.zip
FreeBSD-src-df9f3d2faa1df2bb13d274183876fe227e259a65.tar.gz
Fix locking for f_offset, vn_read() and vn_write() cases only, for now.
It seems that intended locking protocol for struct file f_offset field was as follows: f_offset should always be changed under the vnode lock (except fcntl(2) and lseek(2) did not followed the rules). Since read(2) uses shared vnode lock, FOFFSET_LOCKED block is additionally taken to serialize shared vnode lock owners. This was broken first by enabling shared lock on writes, then by fadvise changes, which moved f_offset assigned from under vnode lock, and last by vn_io_fault() doing chunked i/o. More, due to uio_offset not yet valid in vn_io_fault(), the range lock for reads was taken on the wrong region. Change the locking for f_offset to always use FOFFSET_LOCKED block, which is placed before rangelocks in the lock order. Extract foffset_lock() and foffset_unlock() functions which implements FOFFSET_LOCKED lock, and consistently lock f_offset with it in the vn_io_fault() both for reads and writes, even if MNTK_NO_IOPF flag is not set for the vnode mount. Indicate that f_offset is already valid for vn_read() and vn_write() calls from vn_io_fault() with FOF_OFFSET flag, and assert that all callers of vn_read() and vn_write() follow this protocol. Extract get_advice() function to calculate the POSIX_FADV_XXX value for the i/o region, and use it were appropriate. Reviewed by: jhb Tested by: pho MFC after: 2 weeks
Diffstat (limited to 'contrib/gcc')
0 files changed, 0 insertions, 0 deletions
OpenPOWER on IntegriCloud