]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - share/man/man9/VOP_RDWR.9
mdoc(7) police: Use the new .In macro for #include statements.
[FreeBSD/FreeBSD.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 Ar vp
52 the vnode of the file
53 .It Ar uio
54 the location of the data to be read or written
55 .It Ar ioflag
56 various flags
57 .It Ar 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 filesystem.
64 When attempting a read, the high 16 bits are used to provide a
65 read-ahead hint (in units of filesystem blocks) that the filesystem
66 should attempt.  The low 16 bits are a bit mask which can contain
67 the following flags:
68 .Bl -tag -width IO_NODELOCKED
69 .It Dv IO_UNIT
70 do I/O as atomic unit
71 .It Dv IO_APPEND
72 append write to end
73 .It Dv IO_SYNC
74 do I/O synchronously
75 .It Dv IO_NODELOCKED
76 underlying node already locked
77 .It Dv IO_NDELAY
78 .Dv FNDELAY
79 flag set in file table
80 .It Dv IO_VMIO
81 data already in VMIO space
82 .El
83 .Sh LOCKS
84 The file should be locked on entry and will still be locked on exit.
85 .Sh RETURN VALUES
86 Zero is returned on success, otherwise an error code is returned.
87 .Sh PSEUDOCODE
88 .Bd -literal
89 int
90 vop_read(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
91 {
92     struct buf *bp;
93     off_t bytesinfile;
94     daddr_t lbn, nextlbn;
95     long size, xfersize, blkoffset;
96     int error;
97
98     size = block size of filesystem;
99
100     for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
101         bytesinfile = size of file - uio->uio_offset;
102         if (bytesinfile <= 0)
103             break;
104
105         lbn = uio->uio_offset / size;
106         blkoffset = uio->uio_offset - lbn * size;
107
108         xfersize = size - blkoffset;
109         if (uio->uio_resid < xfersize)
110             xfersize = uio->uio_resid;
111         if (bytesinfile < xfersize)
112             xfersize = bytesinfile;
113
114         error = bread(vp, lbn, size, NOCRED, &bp);
115         if (error) {
116             brelse(bp);
117             bp = NULL;
118             break;
119         }
120
121         /*
122          * We should only get non-zero b_resid when an I/O error
123          * has occurred, which should cause us to break above.
124          * However, if the short read did not cause an error,
125          * then we want to ensure that we do not uiomove bad
126          * or uninitialized data.
127          */
128         size -= bp->b_resid;
129         if (size < xfersize) {
130             if (size == 0)
131                 break;
132             xfersize = size;
133         }
134
135         error = uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio);
136         if (error)
137             break;
138
139         bqrelse(bp);
140     }
141     if (bp != NULL)
142         bqrelse(bp);
143
144     return error;
145 }
146
147 int
148 vop_write(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
149 {
150     struct buf *bp;
151     off_t bytesinfile;
152     daddr_t lbn, nextlbn;
153     off_t osize;
154     long size, resid, xfersize, blkoffset;
155     int flags;
156     int error;
157
158     osize = size of file;
159     size = block size of filesystem;
160     resid = uio->uio_resid;
161     if (ioflag & IO_SYNC)
162         flags = B_SYNC;
163     else
164         flags = 0;
165
166     for (error = 0; uio->uio_resid > 0;) {
167         lbn = uio->uio_offset / size;
168         blkoffset = uio->uio_offset - lbn * size;
169
170         xfersize = size - blkoffset;
171         if (uio->uio_resid < xfersize)
172             xfersize = uio->uio_resid;
173
174         if (uio->uio_offset + xfersize > size of file)
175             vnode_pager_setsize(vp, uio->uio_offset + xfersize);
176
177         if (size > xfersize)
178             flags |= B_CLRBUF;
179         else
180             flags &= ~B_CLRBUF;
181
182         error = find_block_in_file(vp, lbn, blkoffset + xfersize,
183                                    cred, &bp, flags);
184         if (error)
185             break;
186
187         if (uio->uio_offset + xfersize > size of file)
188             set size of file to uio->uio_offset + xfersize;
189
190         error = uiomove((char *)bp->b_data + blkoffset, (int) xfersize, uio);
191         /* XXX ufs does not check the error here.  Why? */
192
193         if (ioflag & IO_VMIO)
194             bp->b_flags |= B_RELBUF; /* ??? */
195
196         if (ioflag & IO_SYNC)
197             bwrite(bp);
198         else if (xfersize + blkoffset == size)
199             bawrite(bp);
200         else
201             bdwrite(bp);
202
203         if (error || xfersize == 0)
204             break;
205     }
206
207     if (error) {
208         if (ioflag & IO_UNIT) {
209             VOP_TRUNCATE(vp, osize, ioflag & IO_SYNC, cred, uio->uio_procp);
210             uio->uio_offset -= resid - uio->uio_resid;
211             uio->uio_resid = resid;
212         }
213     } else if (resid > uio->uio_resid && (ioflag & IO_SYNC)) {
214         struct timeval tv;
215         error = VOP_UPDATE(vp, &tv, &tv, 1); /* XXX what does this do? */
216     }
217
218     return error;
219 }
220 .Ed
221 .Sh ERRORS
222 .Bl -tag -width Er
223 .It Bq Er EFBIG
224 An attempt was made to write a file that exceeds the process's file size
225 limit or the maximum file size.
226 .It Bq Er ENOSPC
227 The filesystem is full.
228 .It Bq Er EPERM
229 An append-only flag is set on the file, but the caller is attempting to
230 write before the current end of file.
231 .El
232 .Sh SEE ALSO
233 .Xr uiomove 9 ,
234 .Xr vnode 9
235 .Sh AUTHORS
236 This man page was written by
237 .An Doug Rabson .