xref: /dflybsd-src/share/man/man9/VOP_RDWR.9 (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino.\" Copyright (c) 1996 Doug Rabson
286d7f5d3SJohn Marino.\"
386d7f5d3SJohn Marino.\" All rights reserved.
486d7f5d3SJohn Marino.\"
586d7f5d3SJohn Marino.\" This program is free software.
686d7f5d3SJohn Marino.\"
786d7f5d3SJohn Marino.\" Redistribution and use in source and binary forms, with or without
886d7f5d3SJohn Marino.\" modification, are permitted provided that the following conditions
986d7f5d3SJohn Marino.\" are met:
1086d7f5d3SJohn Marino.\" 1. Redistributions of source code must retain the above copyright
1186d7f5d3SJohn Marino.\"    notice, this list of conditions and the following disclaimer.
1286d7f5d3SJohn Marino.\" 2. Redistributions in binary form must reproduce the above copyright
1386d7f5d3SJohn Marino.\"    notice, this list of conditions and the following disclaimer in the
1486d7f5d3SJohn Marino.\"    documentation and/or other materials provided with the distribution.
1586d7f5d3SJohn Marino.\"
1686d7f5d3SJohn Marino.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
1786d7f5d3SJohn Marino.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1886d7f5d3SJohn Marino.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1986d7f5d3SJohn Marino.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
2086d7f5d3SJohn Marino.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2186d7f5d3SJohn Marino.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2286d7f5d3SJohn Marino.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2386d7f5d3SJohn Marino.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2486d7f5d3SJohn Marino.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2586d7f5d3SJohn Marino.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2686d7f5d3SJohn Marino.\"
2786d7f5d3SJohn Marino.\" $FreeBSD: src/share/man/man9/VOP_RDWR.9,v 1.9.2.2 2001/12/17 11:30:18 ru Exp $
2886d7f5d3SJohn Marino.\"
2986d7f5d3SJohn Marino.Dd July 24, 1996
3086d7f5d3SJohn Marino.Dt VOP_RDWR 9
3186d7f5d3SJohn Marino.Os
3286d7f5d3SJohn Marino.Sh NAME
3386d7f5d3SJohn Marino.Nm VOP_READ ,
3486d7f5d3SJohn Marino.Nm VOP_WRITE
3586d7f5d3SJohn Marino.Nd read or write a file
3686d7f5d3SJohn Marino.Sh SYNOPSIS
3786d7f5d3SJohn Marino.In sys/param.h
3886d7f5d3SJohn Marino.In sys/vnode.h
3986d7f5d3SJohn Marino.In sys/uio.h
4086d7f5d3SJohn Marino.Ft int
4186d7f5d3SJohn Marino.Fn VOP_READ "struct vnode *vp" "struct uio *uio" "int ioflag" "struct ucred *cred"
4286d7f5d3SJohn Marino.Ft int
4386d7f5d3SJohn Marino.Fn VOP_WRITE "struct vnode *vp" "struct uio *uio" "int ioflag" "struct ucred *cred"
4486d7f5d3SJohn Marino.Sh DESCRIPTION
4586d7f5d3SJohn MarinoThese entry points read or write the contents of a file
4686d7f5d3SJohn Marino.Pp
4786d7f5d3SJohn MarinoThe arguments are:
4886d7f5d3SJohn Marino.Bl -tag -width ioflag
4986d7f5d3SJohn Marino.It Fa vp
5086d7f5d3SJohn Marinothe vnode of the file
5186d7f5d3SJohn Marino.It Fa uio
5286d7f5d3SJohn Marinothe location of the data to be read or written
5386d7f5d3SJohn Marino.It Fa ioflag
5486d7f5d3SJohn Marinovarious flags
5586d7f5d3SJohn Marino.It Fa cnp
5686d7f5d3SJohn Marinothe credentials of the caller
5786d7f5d3SJohn Marino.El
5886d7f5d3SJohn Marino.Pp
5986d7f5d3SJohn MarinoThe
6086d7f5d3SJohn Marino.Fa ioflag
6186d7f5d3SJohn Marinoargument is used to give directives and hints to the filesystem.
6286d7f5d3SJohn MarinoWhen attempting a read, the high 16 bits are used to provide a
6386d7f5d3SJohn Marinoread-ahead hint (in units of filesystem blocks) that the filesystem
6486d7f5d3SJohn Marinoshould attempt.  The low 16 bits are a bit mask which can contain
6586d7f5d3SJohn Marinothe following flags:
6686d7f5d3SJohn Marino.Bl -tag -width ".Dv IO_NODELOCKED"
6786d7f5d3SJohn Marino.It Dv IO_UNIT
6886d7f5d3SJohn Marinodo I/O as atomic unit
6986d7f5d3SJohn Marino.It Dv IO_APPEND
7086d7f5d3SJohn Marinoappend write to end
7186d7f5d3SJohn Marino.It Dv IO_SYNC
7286d7f5d3SJohn Marinodo I/O synchronously
7386d7f5d3SJohn Marino.It Dv IO_NODELOCKED
7486d7f5d3SJohn Marinounderlying node already locked
7586d7f5d3SJohn Marino.It Dv IO_NDELAY
7686d7f5d3SJohn Marino.Dv FNDELAY
7786d7f5d3SJohn Marinoflag set in file table
7886d7f5d3SJohn Marino.It Dv IO_VMIO
7986d7f5d3SJohn Marinodata already in VMIO space
8086d7f5d3SJohn Marino.El
8186d7f5d3SJohn Marino.Sh LOCKS
8286d7f5d3SJohn MarinoThe file should be locked on entry and will still be locked on exit.
8386d7f5d3SJohn Marino.Sh RETURN VALUES
8486d7f5d3SJohn MarinoZero is returned on success, otherwise an error code is returned.
8586d7f5d3SJohn Marino.Sh PSEUDOCODE
8686d7f5d3SJohn Marino.Bd -literal
8786d7f5d3SJohn Marinoint
8886d7f5d3SJohn Marinovop_read(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
8986d7f5d3SJohn Marino{
9086d7f5d3SJohn Marino    struct buf *bp;
9186d7f5d3SJohn Marino    off_t bytesinfile;
9286d7f5d3SJohn Marino    daddr_t lbn, nextlbn;
9386d7f5d3SJohn Marino    long size, xfersize, blkoffset;
9486d7f5d3SJohn Marino    int error;
9586d7f5d3SJohn Marino
9686d7f5d3SJohn Marino    size = block size of filesystem;
9786d7f5d3SJohn Marino
9886d7f5d3SJohn Marino    for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
9986d7f5d3SJohn Marino	bytesinfile = size of file - uio->uio_offset;
10086d7f5d3SJohn Marino	if (bytesinfile <= 0)
10186d7f5d3SJohn Marino	    break;
10286d7f5d3SJohn Marino
10386d7f5d3SJohn Marino	lbn = uio->uio_offset / size;
10486d7f5d3SJohn Marino	blkoffset = uio->uio_offset - lbn * size;
10586d7f5d3SJohn Marino
10686d7f5d3SJohn Marino	xfersize = size - blkoffset;
10786d7f5d3SJohn Marino	if (uio->uio_resid < xfersize)
10886d7f5d3SJohn Marino	    xfersize = uio->uio_resid;
10986d7f5d3SJohn Marino	if (bytesinfile < xfersize)
11086d7f5d3SJohn Marino	    xfersize = bytesinfile;
11186d7f5d3SJohn Marino
11286d7f5d3SJohn Marino	error = bread(vp, lbn, size, NOCRED, &bp);
11386d7f5d3SJohn Marino	if (error) {
11486d7f5d3SJohn Marino	    brelse(bp);
11586d7f5d3SJohn Marino	    bp = NULL;
11686d7f5d3SJohn Marino	    break;
11786d7f5d3SJohn Marino	}
11886d7f5d3SJohn Marino
11986d7f5d3SJohn Marino	/*
12086d7f5d3SJohn Marino	 * We should only get non-zero b_resid when an I/O error
12186d7f5d3SJohn Marino	 * has occurred, which should cause us to break above.
12286d7f5d3SJohn Marino	 * However, if the short read did not cause an error,
12386d7f5d3SJohn Marino	 * then we want to ensure that we do not uiomove bad
12486d7f5d3SJohn Marino	 * or uninitialized data.
12586d7f5d3SJohn Marino	 */
12686d7f5d3SJohn Marino	size -= bp->b_resid;
12786d7f5d3SJohn Marino	if (size < xfersize) {
12886d7f5d3SJohn Marino	    if (size == 0)
12986d7f5d3SJohn Marino		break;
13086d7f5d3SJohn Marino	    xfersize = size;
13186d7f5d3SJohn Marino	}
13286d7f5d3SJohn Marino
13386d7f5d3SJohn Marino	error = uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio);
13486d7f5d3SJohn Marino	if (error)
13586d7f5d3SJohn Marino	    break;
13686d7f5d3SJohn Marino
13786d7f5d3SJohn Marino	bqrelse(bp);
13886d7f5d3SJohn Marino    }
13986d7f5d3SJohn Marino    if (bp != NULL)
14086d7f5d3SJohn Marino	bqrelse(bp);
14186d7f5d3SJohn Marino
14286d7f5d3SJohn Marino    return error;
14386d7f5d3SJohn Marino}
14486d7f5d3SJohn Marino
14586d7f5d3SJohn Marinoint
14686d7f5d3SJohn Marinovop_write(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
14786d7f5d3SJohn Marino{
14886d7f5d3SJohn Marino    struct buf *bp;
14986d7f5d3SJohn Marino    off_t bytesinfile;
15086d7f5d3SJohn Marino    daddr_t lbn, nextlbn;
15186d7f5d3SJohn Marino    off_t osize;
15286d7f5d3SJohn Marino    long size, resid, xfersize, blkoffset;
15386d7f5d3SJohn Marino    int flags;
15486d7f5d3SJohn Marino    int error;
15586d7f5d3SJohn Marino
15686d7f5d3SJohn Marino    osize = size of file;
15786d7f5d3SJohn Marino    size = block size of filesystem;
15886d7f5d3SJohn Marino    resid = uio->uio_resid;
15986d7f5d3SJohn Marino    if (ioflag & IO_SYNC)
16086d7f5d3SJohn Marino	flags = B_SYNC;
16186d7f5d3SJohn Marino    else
16286d7f5d3SJohn Marino	flags = 0;
16386d7f5d3SJohn Marino
16486d7f5d3SJohn Marino    for (error = 0; uio->uio_resid > 0;) {
16586d7f5d3SJohn Marino	lbn = uio->uio_offset / size;
16686d7f5d3SJohn Marino	blkoffset = uio->uio_offset - lbn * size;
16786d7f5d3SJohn Marino
16886d7f5d3SJohn Marino	xfersize = size - blkoffset;
16986d7f5d3SJohn Marino	if (uio->uio_resid < xfersize)
17086d7f5d3SJohn Marino	    xfersize = uio->uio_resid;
17186d7f5d3SJohn Marino
17286d7f5d3SJohn Marino	if (uio->uio_offset + xfersize > size of file)
17386d7f5d3SJohn Marino	    vnode_pager_setsize(vp, uio->uio_offset + xfersize);
17486d7f5d3SJohn Marino
17586d7f5d3SJohn Marino	if (size > xfersize)
17686d7f5d3SJohn Marino	    flags |= B_CLRBUF;
17786d7f5d3SJohn Marino	else
17886d7f5d3SJohn Marino	    flags &= ~B_CLRBUF;
17986d7f5d3SJohn Marino
18086d7f5d3SJohn Marino	error = find_block_in_file(vp, lbn, blkoffset + xfersize,
18186d7f5d3SJohn Marino				   cred, &bp, flags);
18286d7f5d3SJohn Marino	if (error)
18386d7f5d3SJohn Marino	    break;
18486d7f5d3SJohn Marino
18586d7f5d3SJohn Marino	if (uio->uio_offset + xfersize > size of file)
18686d7f5d3SJohn Marino	    set size of file to uio->uio_offset + xfersize;
18786d7f5d3SJohn Marino
18886d7f5d3SJohn Marino	error = uiomove((char *)bp->b_data + blkoffset, (int) xfersize, uio);
18986d7f5d3SJohn Marino	/* XXX ufs does not check the error here.  Why? */
19086d7f5d3SJohn Marino
19186d7f5d3SJohn Marino	if (ioflag & IO_VMIO)
19286d7f5d3SJohn Marino	    bp->b_flags |= B_RELBUF; /* ??? */
19386d7f5d3SJohn Marino
19486d7f5d3SJohn Marino	if (ioflag & IO_SYNC)
19586d7f5d3SJohn Marino	    bwrite(bp);
19686d7f5d3SJohn Marino	else if (xfersize + blkoffset == size)
19786d7f5d3SJohn Marino	    bawrite(bp);
19886d7f5d3SJohn Marino	else
19986d7f5d3SJohn Marino	    bdwrite(bp);
20086d7f5d3SJohn Marino
20186d7f5d3SJohn Marino	if (error || xfersize == 0)
20286d7f5d3SJohn Marino	    break;
20386d7f5d3SJohn Marino    }
20486d7f5d3SJohn Marino
20586d7f5d3SJohn Marino    if (error) {
20686d7f5d3SJohn Marino	if (ioflag & IO_UNIT) {
20786d7f5d3SJohn Marino	    VOP_TRUNCATE(vp, osize, ioflag & IO_SYNC, cred, uio->uio_procp);
20886d7f5d3SJohn Marino	    uio->uio_offset -= resid - uio->uio_resid;
20986d7f5d3SJohn Marino	    uio->uio_resid = resid;
21086d7f5d3SJohn Marino	}
21186d7f5d3SJohn Marino    } else if (resid > uio->uio_resid && (ioflag & IO_SYNC)) {
21286d7f5d3SJohn Marino	struct timeval tv;
21386d7f5d3SJohn Marino	error = VOP_UPDATE(vp, &tv, &tv, 1); /* XXX what does this do? */
21486d7f5d3SJohn Marino    }
21586d7f5d3SJohn Marino
21686d7f5d3SJohn Marino    return error;
21786d7f5d3SJohn Marino}
21886d7f5d3SJohn Marino.Ed
21986d7f5d3SJohn Marino.Sh ERRORS
22086d7f5d3SJohn Marino.Bl -tag -width Er
22186d7f5d3SJohn Marino.It Bq Er ENOSPC
22286d7f5d3SJohn MarinoThe filesystem is full.
22386d7f5d3SJohn Marino.El
22486d7f5d3SJohn Marino.Sh SEE ALSO
22586d7f5d3SJohn Marino.Xr uiomove 9 ,
22686d7f5d3SJohn Marino.Xr vnode 9
22786d7f5d3SJohn Marino.Sh AUTHORS
22886d7f5d3SJohn MarinoThis man page was written by
22986d7f5d3SJohn Marino.An Doug Rabson .
230