]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - share/man/man9/VOP_RDWR.9
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / share / man / man9 / VOP_RDWR.9
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
47 These entry points read or write the contents of a file
48 .Pp
49 The arguments are:
50 .Bl -tag -width ioflag
51 .It Fa vp
52 The vnode of the file.
53 .It Fa uio
54 The location of the data to be read or written.
55 .It Fa ioflag
56 Various flags.
57 .It Fa cnp
58 The credentials of the caller.
59 .El
60 .Pp
61 The
62 .Fa ioflag
63 argument is used to give directives and hints to the file system.
64 When attempting a read, the high 16 bits are used to provide a
65 read-ahead hint (in units of file system blocks) that the file system
66 should attempt.
67 The low 16 bits are a bit mask which can contain
68 the following flags:
69 .Bl -tag -width ".Dv IO_NODELOCKED"
70 .It Dv IO_UNIT
71 Do I/O as atomic unit.
72 .It Dv IO_APPEND
73 Append write to end.
74 .It Dv IO_SYNC
75 Do I/O synchronously.
76 .It Dv IO_NODELOCKED
77 Underlying node already locked.
78 .It Dv IO_NDELAY
79 .Dv FNDELAY
80 flag set in file table.
81 .It Dv IO_VMIO
82 Data already in VMIO space.
83 .El
84 .Sh LOCKS
85 The file should be locked on entry and will still be locked on exit.
86 .Sh RETURN VALUES
87 Zero is returned on success, otherwise an error code is returned.
88 .Sh PSEUDOCODE
89 .Bd -literal
90 int
91 vop_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
148 int
149 vop_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
226 An attempt was made to write a file that exceeds the process's file size
227 limit or the maximum file size.
228 .It Bq Er ENOSPC
229 The file system is full.
230 .It Bq Er EPERM
231 An append-only flag is set on the file, but the caller is attempting to
232 write before the current end of file.
233 .El
234 .Sh SEE ALSO
235 .Xr uiomove 9 ,
236 .Xr vnode 9
237 .Sh AUTHORS
238 This manual page was written by
239 .An Doug Rabson .