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