xref: /dragonfly/share/man/man9/VOP_RDWR.9 (revision 71126e33)
1.\" Copyright (c) 1996 Doug Rabson
2.\"
3.\" All rights reserved.
4.\"
5.\" This program is free software.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\"    notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\"    notice, this list of conditions and the following disclaimer in the
14.\"    documentation and/or other materials provided with the distribution.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
17.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
20.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26.\"
27.\" $FreeBSD: src/share/man/man9/VOP_RDWR.9,v 1.9.2.2 2001/12/17 11:30:18 ru Exp $
28.\" $DragonFly: src/share/man/man9/VOP_RDWR.9,v 1.4 2004/06/01 11:36:53 hmp Exp $
29.\"
30.Dd July 24, 1996
31.Os
32.Dt VOP_RDWR 9
33.Sh NAME
34.Nm VOP_READ ,
35.Nm VOP_WRITE
36.Nd read or write a file
37.Sh SYNOPSIS
38.In sys/param.h
39.In sys/vnode.h
40.In sys/uio.h
41.Ft int
42.Fn VOP_READ "struct vnode *vp" "struct uio *uio" "int ioflag" "struct ucred *cred"
43.Ft int
44.Fn VOP_WRITE "struct vnode *vp" "struct uio *uio" "int ioflag" "struct ucred *cred"
45.Sh DESCRIPTION
46These entry points read or write the contents of a file
47.Pp
48The arguments are:
49.Bl -tag -width ioflag
50.It Fa vp
51the vnode of the file
52.It Fa uio
53the location of the data to be read or written
54.It Fa ioflag
55various flags
56.It Fa cnp
57the credentials of the caller
58.El
59.Pp
60The
61.Fa ioflag
62argument is used to give directives and hints to the filesystem.
63When attempting a read, the high 16 bits are used to provide a
64read-ahead hint (in units of filesystem blocks) that the filesystem
65should attempt.  The low 16 bits are a bit mask which can contain
66the following flags:
67.Bl -tag -width IO_NODELOCKED
68.It Dv IO_UNIT
69do I/O as atomic unit
70.It Dv IO_APPEND
71append write to end
72.It Dv IO_SYNC
73do I/O synchronously
74.It Dv IO_NODELOCKED
75underlying node already locked
76.It Dv IO_NDELAY
77.Dv FNDELAY
78flag set in file table
79.It Dv IO_VMIO
80data already in VMIO space
81.El
82.Sh LOCKS
83The file should be locked on entry and will still be locked on exit.
84.Sh RETURN VALUES
85Zero is returned on success, otherwise an error code is returned.
86.Sh PSEUDOCODE
87.Bd -literal
88int
89vop_read(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
90{
91    struct buf *bp;
92    off_t bytesinfile;
93    daddr_t lbn, nextlbn;
94    long size, xfersize, blkoffset;
95    int error;
96
97    size = block size of filesystem;
98
99    for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
100	bytesinfile = size of file - uio->uio_offset;
101	if (bytesinfile <= 0)
102	    break;
103
104	lbn = uio->uio_offset / size;
105	blkoffset = uio->uio_offset - lbn * size;
106
107	xfersize = size - blkoffset;
108	if (uio->uio_resid < xfersize)
109	    xfersize = uio->uio_resid;
110	if (bytesinfile < xfersize)
111	    xfersize = bytesinfile;
112
113	error = bread(vp, lbn, size, NOCRED, &bp);
114	if (error) {
115	    brelse(bp);
116	    bp = NULL;
117	    break;
118	}
119
120	/*
121	 * We should only get non-zero b_resid when an I/O error
122	 * has occurred, which should cause us to break above.
123	 * However, if the short read did not cause an error,
124	 * then we want to ensure that we do not uiomove bad
125	 * or uninitialized data.
126	 */
127	size -= bp->b_resid;
128	if (size < xfersize) {
129	    if (size == 0)
130		break;
131	    xfersize = size;
132	}
133
134	error = uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio);
135	if (error)
136	    break;
137
138	bqrelse(bp);
139    }
140    if (bp != NULL)
141	bqrelse(bp);
142
143    return error;
144}
145
146int
147vop_write(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
148{
149    struct buf *bp;
150    off_t bytesinfile;
151    daddr_t lbn, nextlbn;
152    off_t osize;
153    long size, resid, xfersize, blkoffset;
154    int flags;
155    int error;
156
157    osize = size of file;
158    size = block size of filesystem;
159    resid = uio->uio_resid;
160    if (ioflag & IO_SYNC)
161	flags = B_SYNC;
162    else
163	flags = 0;
164
165    for (error = 0; uio->uio_resid > 0;) {
166	lbn = uio->uio_offset / size;
167	blkoffset = uio->uio_offset - lbn * size;
168
169	xfersize = size - blkoffset;
170	if (uio->uio_resid < xfersize)
171	    xfersize = uio->uio_resid;
172
173	if (uio->uio_offset + xfersize > size of file)
174	    vnode_pager_setsize(vp, uio->uio_offset + xfersize);
175
176	if (size > xfersize)
177	    flags |= B_CLRBUF;
178	else
179	    flags &= ~B_CLRBUF;
180
181	error = find_block_in_file(vp, lbn, blkoffset + xfersize,
182				   cred, &bp, flags);
183	if (error)
184	    break;
185
186	if (uio->uio_offset + xfersize > size of file)
187	    set size of file to uio->uio_offset + xfersize;
188
189	error = uiomove((char *)bp->b_data + blkoffset, (int) xfersize, uio);
190	/* XXX ufs does not check the error here.  Why? */
191
192	if (ioflag & IO_VMIO)
193	    bp->b_flags |= B_RELBUF; /* ??? */
194
195	if (ioflag & IO_SYNC)
196	    bwrite(bp);
197	else if (xfersize + blkoffset == size)
198	    bawrite(bp);
199	else
200	    bdwrite(bp);
201
202	if (error || xfersize == 0)
203	    break;
204    }
205
206    if (error) {
207	if (ioflag & IO_UNIT) {
208	    VOP_TRUNCATE(vp, osize, ioflag & IO_SYNC, cred, uio->uio_procp);
209	    uio->uio_offset -= resid - uio->uio_resid;
210	    uio->uio_resid = resid;
211	}
212    } else if (resid > uio->uio_resid && (ioflag & IO_SYNC)) {
213	struct timeval tv;
214	error = VOP_UPDATE(vp, &tv, &tv, 1); /* XXX what does this do? */
215    }
216
217    return error;
218}
219.Ed
220.Sh ERRORS
221.Bl -tag -width Er
222.It Bq Er ENOSPC
223The filesystem is full.
224.El
225.Sh SEE ALSO
226.Xr uiomove 9 ,
227.Xr vnode 9
228.Sh AUTHORS
229This man page was written by
230.An Doug Rabson .
231