- Replace lnc(4) driver with NetBSD's le(4), which gives us better performance,
[dragonfly.git] / share / man / man9 / VOP_RDWR.9
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
46 These entry points read or write the contents of a file
47 .Pp
48 The arguments are:
49 .Bl -tag -width ioflag
50 .It Fa vp
51 the vnode of the file
52 .It Fa uio
53 the location of the data to be read or written
54 .It Fa ioflag
55 various flags
56 .It Fa cnp
57 the credentials of the caller
58 .El
59 .Pp
60 The
61 .Fa ioflag
62 argument is used to give directives and hints to the filesystem.
63 When attempting a read, the high 16 bits are used to provide a
64 read-ahead hint (in units of filesystem blocks) that the filesystem
65 should attempt.  The low 16 bits are a bit mask which can contain
66 the following flags:
67 .Bl -tag -width IO_NODELOCKED
68 .It Dv IO_UNIT
69 do I/O as atomic unit
70 .It Dv IO_APPEND
71 append write to end
72 .It Dv IO_SYNC
73 do I/O synchronously
74 .It Dv IO_NODELOCKED
75 underlying node already locked
76 .It Dv IO_NDELAY
77 .Dv FNDELAY
78 flag set in file table
79 .It Dv IO_VMIO
80 data already in VMIO space
81 .El
82 .Sh LOCKS
83 The file should be locked on entry and will still be locked on exit.
84 .Sh RETURN VALUES
85 Zero is returned on success, otherwise an error code is returned.
86 .Sh PSEUDOCODE
87 .Bd -literal
88 int
89 vop_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
146 int
147 vop_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
223 The filesystem is full.
224 .El
225 .Sh SEE ALSO
226 .Xr uiomove 9 ,
227 .Xr vnode 9
228 .Sh AUTHORS
229 This man page was written by
230 .An Doug Rabson .