xref: /dragonfly/share/man/man9/VOP_RDWR.9 (revision 1975d09e)
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.\"
29.Dd July 24, 1996
30.Dt VOP_RDWR 9
31.Os
32.Sh NAME
33.Nm VOP_READ ,
34.Nm VOP_WRITE
35.Nd read or write a file
36.Sh SYNOPSIS
37.In sys/param.h
38.In sys/vnode.h
39.In sys/uio.h
40.Ft int
41.Fn VOP_READ "struct vnode *vp" "struct uio *uio" "int ioflag" "struct ucred *cred"
42.Ft int
43.Fn VOP_WRITE "struct vnode *vp" "struct uio *uio" "int ioflag" "struct ucred *cred"
44.Sh DESCRIPTION
45These entry points read or write the contents of a file
46.Pp
47The arguments are:
48.Bl -tag -width ioflag
49.It Fa vp
50the vnode of the file
51.It Fa uio
52the location of the data to be read or written
53.It Fa ioflag
54various flags
55.It Fa cnp
56the credentials of the caller
57.El
58.Pp
59The
60.Fa ioflag
61argument is used to give directives and hints to the filesystem.
62When attempting a read, the high 16 bits are used to provide a
63read-ahead hint (in units of filesystem blocks) that the filesystem
64should attempt.  The low 16 bits are a bit mask which can contain
65the following flags:
66.Bl -tag -width ".Dv IO_NODELOCKED"
67.It Dv IO_UNIT
68do I/O as atomic unit
69.It Dv IO_APPEND
70append write to end
71.It Dv IO_SYNC
72do I/O synchronously
73.It Dv IO_NODELOCKED
74underlying node already locked
75.It Dv IO_NDELAY
76.Dv FNDELAY
77flag set in file table
78.It Dv IO_VMIO
79data already in VMIO space
80.El
81.Sh LOCKS
82The file should be locked on entry and will still be locked on exit.
83.Sh RETURN VALUES
84Zero is returned on success, otherwise an error code is returned.
85.Sh PSEUDOCODE
86.Bd -literal
87int
88vop_read(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
89{
90    struct buf *bp;
91    off_t bytesinfile;
92    daddr_t lbn, nextlbn;
93    long size, xfersize, blkoffset;
94    int error;
95
96    size = block size of filesystem;
97
98    for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
99	bytesinfile = size of file - uio->uio_offset;
100	if (bytesinfile <= 0)
101	    break;
102
103	lbn = uio->uio_offset / size;
104	blkoffset = uio->uio_offset - lbn * size;
105
106	xfersize = size - blkoffset;
107	if (uio->uio_resid < xfersize)
108	    xfersize = uio->uio_resid;
109	if (bytesinfile < xfersize)
110	    xfersize = bytesinfile;
111
112	error = bread(vp, lbn, size, NOCRED, &bp);
113	if (error) {
114	    brelse(bp);
115	    bp = NULL;
116	    break;
117	}
118
119	/*
120	 * We should only get non-zero b_resid when an I/O error
121	 * has occurred, which should cause us to break above.
122	 * However, if the short read did not cause an error,
123	 * then we want to ensure that we do not uiomove bad
124	 * or uninitialized data.
125	 */
126	size -= bp->b_resid;
127	if (size < xfersize) {
128	    if (size == 0)
129		break;
130	    xfersize = size;
131	}
132
133	error = uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio);
134	if (error)
135	    break;
136
137	bqrelse(bp);
138    }
139    if (bp != NULL)
140	bqrelse(bp);
141
142    return error;
143}
144
145int
146vop_write(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
147{
148    struct buf *bp;
149    off_t bytesinfile;
150    daddr_t lbn, nextlbn;
151    off_t osize;
152    long size, resid, xfersize, blkoffset;
153    int flags;
154    int error;
155
156    osize = size of file;
157    size = block size of filesystem;
158    resid = uio->uio_resid;
159    if (ioflag & IO_SYNC)
160	flags = B_SYNC;
161    else
162	flags = 0;
163
164    for (error = 0; uio->uio_resid > 0;) {
165	lbn = uio->uio_offset / size;
166	blkoffset = uio->uio_offset - lbn * size;
167
168	xfersize = size - blkoffset;
169	if (uio->uio_resid < xfersize)
170	    xfersize = uio->uio_resid;
171
172	if (uio->uio_offset + xfersize > size of file)
173	    vnode_pager_setsize(vp, uio->uio_offset + xfersize);
174
175	if (size > xfersize)
176	    flags |= B_CLRBUF;
177	else
178	    flags &= ~B_CLRBUF;
179
180	error = find_block_in_file(vp, lbn, blkoffset + xfersize,
181				   cred, &bp, flags);
182	if (error)
183	    break;
184
185	if (uio->uio_offset + xfersize > size of file)
186	    set size of file to uio->uio_offset + xfersize;
187
188	error = uiomove((char *)bp->b_data + blkoffset, (int) xfersize, uio);
189	/* XXX ufs does not check the error here.  Why? */
190
191	if (ioflag & IO_VMIO)
192	    bp->b_flags |= B_RELBUF; /* ??? */
193
194	if (ioflag & IO_SYNC)
195	    bwrite(bp);
196	else if (xfersize + blkoffset == size)
197	    bawrite(bp);
198	else
199	    bdwrite(bp);
200
201	if (error || xfersize == 0)
202	    break;
203    }
204
205    if (error) {
206	if (ioflag & IO_UNIT) {
207	    VOP_TRUNCATE(vp, osize, ioflag & IO_SYNC, cred, uio->uio_procp);
208	    uio->uio_offset -= resid - uio->uio_resid;
209	    uio->uio_resid = resid;
210	}
211    } else if (resid > uio->uio_resid && (ioflag & IO_SYNC)) {
212	struct timeval tv;
213	error = VOP_UPDATE(vp, &tv, &tv, 1); /* XXX what does this do? */
214    }
215
216    return error;
217}
218.Ed
219.Sh ERRORS
220.Bl -tag -width Er
221.It Bq Er ENOSPC
222The filesystem is full.
223.El
224.Sh SEE ALSO
225.Xr uiomove 9 ,
226.Xr vnode 9
227.Sh AUTHORS
228This man page was written by
229.An Doug Rabson .
230