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