vop_rdwr(9)
NAME
VOP_READ, VOP_WRITE - read or write a file
SYNOPSIS
#include <sys/param.h> #include <sys/vnode.h> #include <sys/uio.h> int VOP_READ(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred); int VOP_WRITE(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred);
DESCRIPTION
These entry points read or write the contents of a file
The arguments are:
vp The vnode of the file.
uio The location of the data to be read or written.
ioflag Various flags.
cnp The credentials of the caller.
- The ioflag argument is used to give directives and hints to
- the file system. When attempting a read, the high 16 bits are used to
- provide a
read-ahead hint (in units of file system blocks) that the - file system
should attempt. The low 16 bits are a bit mask which can - contain the
following flags: - IO_UNIT Do I/O as atomic unit.
- IO_APPEND Append write to end.
- IO_SYNC Do I/O synchronously.
- IO_NODELOCKED Underlying node already locked.
- IO_NDELAY FNDELAY flag set in file table.
- IO_VMIO Data already in VMIO space.
LOCKS
- The file should be locked on entry and will still be locked
- on exit.
RETURN VALUES
- Zero is returned on success, otherwise an error code is re
- turned.
PSEUDOCODE
- int
vop_read(struct vnode *vp, struct uio *uio, int ioflag, - struct ucred *cred)
{ - struct buf *bp;
off_t bytesinfile;
daddr_t lbn, nextlbn;
long size, xfersize, blkoffset;
int error; - size = block size of file system;
- for (error = 0, bp = NULL; uio->uio_resid > 0; bp =
- NULL) {
bytesinfile = size of file - uio->uio_offset;
if (bytesinfile <= 0)break;lbn = uio->uio_offset / size;
blkoffset = uio->uio_offset - lbn * size;xfersize = size - blkoffset;
if (uio->uio_resid < xfersize)xfersize = uio->uio_resid;if (bytesinfile < xfersize)xfersize = bytesinfile;error = bread(vp, lbn, size, NOCRED, &bp);
if (error) {brelse(bp);
bp = NULL;
break;}/** We should only get non-zero b_resid when an I/Oerror
* has occurred, which should cause us to breakabove.
* However, if the short read did not cause an error,
* then we want to ensure that we do not uiomove bad
* or uninitialized data.
*/size -= bp->b_resid;
if (size < xfersize) {if (size == 0)break;xfersize = size;}error = uiomove((char *)bp->b_data + blkoffset,(int)xfersize, uio);
if (error)break;bqrelse(bp); - }
if (bp != NULL)bqrelse(bp); - return (error);
- }
- int
vop_write(struct vnode *vp, struct uio *uio, int ioflag, - struct ucred *cred)
{ - struct buf *bp;
off_t bytesinfile;
daddr_t lbn, nextlbn;
off_t osize;
long size, resid, xfersize, blkoffset;
int flags;
int error; - osize = size of file;
size = block size of file system;
resid = uio->uio_resid;
if (ioflag & IO_SYNC)flags = B_SYNC; - else
flags = 0;
- for (error = 0; uio->uio_resid > 0;) {
lbn = uio->uio_offset / size;
blkoffset = uio->uio_offset - lbn * size;xfersize = size - blkoffset;
if (uio->uio_resid < xfersize)xfersize = uio->uio_resid;if (uio->uio_offset + xfersize > size of file)vnode_pager_setsize(vp, uio->uio_offset + xfersize);if (size > xfersize)flags |= B_CLRBUF;elseflags &= ~B_CLRBUF;error = find_block_in_file(vp, lbn, blkoffset +xfersize,cred, &bp, flags);if (error)break;if (uio->uio_offset + xfersize > size of file)set size of file to uio->uio_offset + xfersize;error = uiomove((char *)bp->b_data + blkoffset,(int) xfersize, uio);
/* XXX ufs does not check the error here. Why? */if (ioflag & IO_VMIO)bp->b_flags |= B_RELBUF; /* ??? */if (ioflag & IO_SYNC)bwrite(bp);else if (xfersize + blkoffset == size)bawrite(bp);elsebdwrite(bp);if (error || xfersize == 0)break;}if (error) {if (ioflag & IO_UNIT) {/* call private routine to truncate file. */
your_truncate(vp, osize, ioflag & IO_SYNC, cred,uio->uio_td);
uio->uio_offset -= resid - uio->uio_resid;
uio->uio_resid = resid;}} else if (resid > uio->uio_resid && (ioflag & IO_SYNC)){struct timeval tv;
error = VOP_UPDATE(vp, &tv, &tv, 1); /* XXX whatdoes this do? */}return (error); - }
ERRORS
- [EFBIG] An attempt was made to write a file that
- exceeds the
- process's file size limit or the maximum
- file size.
- [ENOSPC] The file system is full.
- [EPERM] An append-only flag is set on the file,
- but the caller
- is attempting to write before the current
- end of file.
SEE ALSO
AUTHORS
- This manual page was written by Doug Rabson.
- BSD July 24, 1996