vfs_vnops.c revision 1.140.10.2 1 1.140.10.2 pooka /* $NetBSD: vfs_vnops.c,v 1.140.10.2 2007/07/22 19:16:06 pooka Exp $ */
2 1.140.10.2 pooka
3 1.140.10.2 pooka /*
4 1.140.10.2 pooka * Copyright (c) 1982, 1986, 1989, 1993
5 1.140.10.2 pooka * The Regents of the University of California. All rights reserved.
6 1.140.10.2 pooka * (c) UNIX System Laboratories, Inc.
7 1.140.10.2 pooka * All or some portions of this file are derived from material licensed
8 1.140.10.2 pooka * to the University of California by American Telephone and Telegraph
9 1.140.10.2 pooka * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 1.140.10.2 pooka * the permission of UNIX System Laboratories, Inc.
11 1.140.10.2 pooka *
12 1.140.10.2 pooka * Redistribution and use in source and binary forms, with or without
13 1.140.10.2 pooka * modification, are permitted provided that the following conditions
14 1.140.10.2 pooka * are met:
15 1.140.10.2 pooka * 1. Redistributions of source code must retain the above copyright
16 1.140.10.2 pooka * notice, this list of conditions and the following disclaimer.
17 1.140.10.2 pooka * 2. Redistributions in binary form must reproduce the above copyright
18 1.140.10.2 pooka * notice, this list of conditions and the following disclaimer in the
19 1.140.10.2 pooka * documentation and/or other materials provided with the distribution.
20 1.140.10.2 pooka * 3. Neither the name of the University nor the names of its contributors
21 1.140.10.2 pooka * may be used to endorse or promote products derived from this software
22 1.140.10.2 pooka * without specific prior written permission.
23 1.140.10.2 pooka *
24 1.140.10.2 pooka * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 1.140.10.2 pooka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 1.140.10.2 pooka * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 1.140.10.2 pooka * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 1.140.10.2 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 1.140.10.2 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 1.140.10.2 pooka * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 1.140.10.2 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 1.140.10.2 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 1.140.10.2 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 1.140.10.2 pooka * SUCH DAMAGE.
35 1.140.10.2 pooka *
36 1.140.10.2 pooka * @(#)vfs_vnops.c 8.14 (Berkeley) 6/15/95
37 1.140.10.2 pooka */
38 1.140.10.2 pooka
39 1.140.10.2 pooka #include <sys/cdefs.h>
40 1.140.10.2 pooka __KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.140.10.2 2007/07/22 19:16:06 pooka Exp $");
41 1.140.10.2 pooka
42 1.140.10.2 pooka #include "fs_union.h"
43 1.140.10.2 pooka #include "veriexec.h"
44 1.140.10.2 pooka
45 1.140.10.2 pooka #include <sys/param.h>
46 1.140.10.2 pooka #include <sys/systm.h>
47 1.140.10.2 pooka #include <sys/kernel.h>
48 1.140.10.2 pooka #include <sys/file.h>
49 1.140.10.2 pooka #include <sys/stat.h>
50 1.140.10.2 pooka #include <sys/buf.h>
51 1.140.10.2 pooka #include <sys/proc.h>
52 1.140.10.2 pooka #include <sys/malloc.h>
53 1.140.10.2 pooka #include <sys/mount.h>
54 1.140.10.2 pooka #include <sys/namei.h>
55 1.140.10.2 pooka #include <sys/vnode.h>
56 1.140.10.2 pooka #include <sys/ioctl.h>
57 1.140.10.2 pooka #include <sys/tty.h>
58 1.140.10.2 pooka #include <sys/poll.h>
59 1.140.10.2 pooka #include <sys/kauth.h>
60 1.140.10.2 pooka #include <sys/syslog.h>
61 1.140.10.2 pooka
62 1.140.10.2 pooka #include <miscfs/specfs/specdev.h>
63 1.140.10.2 pooka
64 1.140.10.2 pooka #include <uvm/uvm_extern.h>
65 1.140.10.2 pooka #include <uvm/uvm_readahead.h>
66 1.140.10.2 pooka
67 1.140.10.2 pooka #ifdef UNION
68 1.140.10.2 pooka #include <fs/union/union.h>
69 1.140.10.2 pooka #endif
70 1.140.10.2 pooka
71 1.140.10.2 pooka #if defined(LKM) || defined(UNION)
72 1.140.10.2 pooka int (*vn_union_readdir_hook) (struct vnode **, struct file *, struct lwp *);
73 1.140.10.2 pooka #endif
74 1.140.10.2 pooka
75 1.140.10.2 pooka #include <sys/verified_exec.h>
76 1.140.10.2 pooka
77 1.140.10.2 pooka static int vn_read(struct file *fp, off_t *offset, struct uio *uio,
78 1.140.10.2 pooka kauth_cred_t cred, int flags);
79 1.140.10.2 pooka static int vn_write(struct file *fp, off_t *offset, struct uio *uio,
80 1.140.10.2 pooka kauth_cred_t cred, int flags);
81 1.140.10.2 pooka static int vn_closefile(struct file *fp, struct lwp *l);
82 1.140.10.2 pooka static int vn_poll(struct file *fp, int events, struct lwp *l);
83 1.140.10.2 pooka static int vn_fcntl(struct file *fp, u_int com, void *data, struct lwp *l);
84 1.140.10.2 pooka static int vn_statfile(struct file *fp, struct stat *sb, struct lwp *l);
85 1.140.10.2 pooka static int vn_ioctl(struct file *fp, u_long com, void *data, struct lwp *l);
86 1.140.10.2 pooka
87 1.140.10.2 pooka const struct fileops vnops = {
88 1.140.10.2 pooka vn_read, vn_write, vn_ioctl, vn_fcntl, vn_poll,
89 1.140.10.2 pooka vn_statfile, vn_closefile, vn_kqfilter
90 1.140.10.2 pooka };
91 1.140.10.2 pooka
92 1.140.10.2 pooka /*
93 1.140.10.2 pooka * Common code for vnode open operations.
94 1.140.10.2 pooka * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
95 1.140.10.2 pooka */
96 1.140.10.2 pooka int
97 1.140.10.2 pooka vn_open(struct nameidata *ndp, int fmode, int cmode)
98 1.140.10.2 pooka {
99 1.140.10.2 pooka struct vnode *vp;
100 1.140.10.2 pooka struct lwp *l = ndp->ni_cnd.cn_lwp;
101 1.140.10.2 pooka kauth_cred_t cred = l->l_cred;
102 1.140.10.2 pooka struct vattr va;
103 1.140.10.2 pooka int error;
104 1.140.10.2 pooka char *path;
105 1.140.10.2 pooka
106 1.140.10.2 pooka ndp->ni_cnd.cn_flags &= TRYEMULROOT;
107 1.140.10.2 pooka
108 1.140.10.2 pooka if (fmode & O_CREAT) {
109 1.140.10.2 pooka ndp->ni_cnd.cn_nameiop = CREATE;
110 1.140.10.2 pooka ndp->ni_cnd.cn_flags |= LOCKPARENT | LOCKLEAF;
111 1.140.10.2 pooka if ((fmode & O_EXCL) == 0 &&
112 1.140.10.2 pooka ((fmode & O_NOFOLLOW) == 0))
113 1.140.10.2 pooka ndp->ni_cnd.cn_flags |= FOLLOW;
114 1.140.10.2 pooka } else {
115 1.140.10.2 pooka ndp->ni_cnd.cn_nameiop = LOOKUP;
116 1.140.10.2 pooka ndp->ni_cnd.cn_flags |= LOCKLEAF;
117 1.140.10.2 pooka if ((fmode & O_NOFOLLOW) == 0)
118 1.140.10.2 pooka ndp->ni_cnd.cn_flags |= FOLLOW;
119 1.140.10.2 pooka }
120 1.140.10.2 pooka
121 1.140.10.2 pooka VERIEXEC_PATH_GET(ndp->ni_dirp, ndp->ni_segflg, ndp->ni_dirp, path);
122 1.140.10.2 pooka
123 1.140.10.2 pooka error = namei(ndp);
124 1.140.10.2 pooka if (error)
125 1.140.10.2 pooka goto out;
126 1.140.10.2 pooka
127 1.140.10.2 pooka vp = ndp->ni_vp;
128 1.140.10.2 pooka
129 1.140.10.2 pooka #if NVERIEXEC > 0
130 1.140.10.2 pooka error = veriexec_openchk(l, ndp->ni_vp, ndp->ni_dirp, fmode);
131 1.140.10.2 pooka if (error)
132 1.140.10.2 pooka goto bad;
133 1.140.10.2 pooka #endif /* NVERIEXEC > 0 */
134 1.140.10.2 pooka
135 1.140.10.2 pooka if (fmode & O_CREAT) {
136 1.140.10.2 pooka if (ndp->ni_vp == NULL) {
137 1.140.10.2 pooka VATTR_NULL(&va);
138 1.140.10.2 pooka va.va_type = VREG;
139 1.140.10.2 pooka va.va_mode = cmode;
140 1.140.10.2 pooka if (fmode & O_EXCL)
141 1.140.10.2 pooka va.va_vaflags |= VA_EXCLUSIVE;
142 1.140.10.2 pooka VOP_LEASE(ndp->ni_dvp, l, cred, LEASE_WRITE);
143 1.140.10.2 pooka error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
144 1.140.10.2 pooka &ndp->ni_cnd, &va);
145 1.140.10.2 pooka if (error)
146 1.140.10.2 pooka goto out;
147 1.140.10.2 pooka fmode &= ~O_TRUNC;
148 1.140.10.2 pooka vp = ndp->ni_vp;
149 1.140.10.2 pooka } else {
150 1.140.10.2 pooka VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd);
151 1.140.10.2 pooka if (ndp->ni_dvp == ndp->ni_vp)
152 1.140.10.2 pooka vrele(ndp->ni_dvp);
153 1.140.10.2 pooka else
154 1.140.10.2 pooka vput(ndp->ni_dvp);
155 1.140.10.2 pooka ndp->ni_dvp = NULL;
156 1.140.10.2 pooka vp = ndp->ni_vp;
157 1.140.10.2 pooka if (fmode & O_EXCL) {
158 1.140.10.2 pooka error = EEXIST;
159 1.140.10.2 pooka goto bad;
160 1.140.10.2 pooka }
161 1.140.10.2 pooka fmode &= ~O_CREAT;
162 1.140.10.2 pooka }
163 1.140.10.2 pooka } else {
164 1.140.10.2 pooka vp = ndp->ni_vp;
165 1.140.10.2 pooka }
166 1.140.10.2 pooka if (vp->v_type == VSOCK) {
167 1.140.10.2 pooka error = EOPNOTSUPP;
168 1.140.10.2 pooka goto bad;
169 1.140.10.2 pooka }
170 1.140.10.2 pooka if (ndp->ni_vp->v_type == VLNK) {
171 1.140.10.2 pooka error = EFTYPE;
172 1.140.10.2 pooka goto bad;
173 1.140.10.2 pooka }
174 1.140.10.2 pooka
175 1.140.10.2 pooka if ((fmode & O_CREAT) == 0) {
176 1.140.10.2 pooka if (fmode & FREAD) {
177 1.140.10.2 pooka if ((error = VOP_ACCESS(vp, VREAD, cred, l)) != 0)
178 1.140.10.2 pooka goto bad;
179 1.140.10.2 pooka }
180 1.140.10.2 pooka
181 1.140.10.2 pooka if (fmode & (FWRITE | O_TRUNC)) {
182 1.140.10.2 pooka if (vp->v_type == VDIR) {
183 1.140.10.2 pooka error = EISDIR;
184 1.140.10.2 pooka goto bad;
185 1.140.10.2 pooka }
186 1.140.10.2 pooka if ((error = vn_writechk(vp)) != 0 ||
187 1.140.10.2 pooka (error = VOP_ACCESS(vp, VWRITE, cred, l)) != 0)
188 1.140.10.2 pooka goto bad;
189 1.140.10.2 pooka }
190 1.140.10.2 pooka }
191 1.140.10.2 pooka
192 1.140.10.2 pooka if (fmode & O_TRUNC) {
193 1.140.10.2 pooka VOP_UNLOCK(vp, 0); /* XXX */
194 1.140.10.2 pooka
195 1.140.10.2 pooka VOP_LEASE(vp, l, cred, LEASE_WRITE);
196 1.140.10.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); /* XXX */
197 1.140.10.2 pooka VATTR_NULL(&va);
198 1.140.10.2 pooka va.va_size = 0;
199 1.140.10.2 pooka error = VOP_SETATTR(vp, &va, cred, l);
200 1.140.10.2 pooka if (error != 0)
201 1.140.10.2 pooka goto bad;
202 1.140.10.2 pooka }
203 1.140.10.2 pooka if ((error = VOP_OPEN(vp, fmode, cred, l)) != 0)
204 1.140.10.2 pooka goto bad;
205 1.140.10.2 pooka if (fmode & FWRITE)
206 1.140.10.2 pooka vp->v_writecount++;
207 1.140.10.2 pooka
208 1.140.10.2 pooka bad:
209 1.140.10.2 pooka if (error)
210 1.140.10.2 pooka vput(vp);
211 1.140.10.2 pooka out:
212 1.140.10.2 pooka VERIEXEC_PATH_PUT(path);
213 1.140.10.2 pooka return (error);
214 1.140.10.2 pooka }
215 1.140.10.2 pooka
216 1.140.10.2 pooka /*
217 1.140.10.2 pooka * Check for write permissions on the specified vnode.
218 1.140.10.2 pooka * Prototype text segments cannot be written.
219 1.140.10.2 pooka */
220 1.140.10.2 pooka int
221 1.140.10.2 pooka vn_writechk(struct vnode *vp)
222 1.140.10.2 pooka {
223 1.140.10.2 pooka
224 1.140.10.2 pooka /*
225 1.140.10.2 pooka * If the vnode is in use as a process's text,
226 1.140.10.2 pooka * we can't allow writing.
227 1.140.10.2 pooka */
228 1.140.10.2 pooka if (vp->v_flag & VTEXT)
229 1.140.10.2 pooka return (ETXTBSY);
230 1.140.10.2 pooka return (0);
231 1.140.10.2 pooka }
232 1.140.10.2 pooka
233 1.140.10.2 pooka /*
234 1.140.10.2 pooka * Mark a vnode as having executable mappings.
235 1.140.10.2 pooka */
236 1.140.10.2 pooka void
237 1.140.10.2 pooka vn_markexec(struct vnode *vp)
238 1.140.10.2 pooka {
239 1.140.10.2 pooka if ((vp->v_flag & VEXECMAP) == 0) {
240 1.140.10.2 pooka uvmexp.filepages -= vp->v_uobj.uo_npages;
241 1.140.10.2 pooka uvmexp.execpages += vp->v_uobj.uo_npages;
242 1.140.10.2 pooka }
243 1.140.10.2 pooka vp->v_flag |= VEXECMAP;
244 1.140.10.2 pooka }
245 1.140.10.2 pooka
246 1.140.10.2 pooka /*
247 1.140.10.2 pooka * Mark a vnode as being the text of a process.
248 1.140.10.2 pooka * Fail if the vnode is currently writable.
249 1.140.10.2 pooka */
250 1.140.10.2 pooka int
251 1.140.10.2 pooka vn_marktext(struct vnode *vp)
252 1.140.10.2 pooka {
253 1.140.10.2 pooka
254 1.140.10.2 pooka if (vp->v_writecount != 0) {
255 1.140.10.2 pooka KASSERT((vp->v_flag & VTEXT) == 0);
256 1.140.10.2 pooka return (ETXTBSY);
257 1.140.10.2 pooka }
258 1.140.10.2 pooka vp->v_flag |= VTEXT;
259 1.140.10.2 pooka vn_markexec(vp);
260 1.140.10.2 pooka return (0);
261 1.140.10.2 pooka }
262 1.140.10.2 pooka
263 1.140.10.2 pooka /*
264 1.140.10.2 pooka * Vnode close call
265 1.140.10.2 pooka *
266 1.140.10.2 pooka * Note: takes an unlocked vnode, while VOP_CLOSE takes a locked node.
267 1.140.10.2 pooka */
268 1.140.10.2 pooka int
269 1.140.10.2 pooka vn_close(struct vnode *vp, int flags, kauth_cred_t cred, struct lwp *l)
270 1.140.10.2 pooka {
271 1.140.10.2 pooka int error;
272 1.140.10.2 pooka
273 1.140.10.2 pooka if (flags & FWRITE)
274 1.140.10.2 pooka vp->v_writecount--;
275 1.140.10.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
276 1.140.10.2 pooka error = VOP_CLOSE(vp, flags, cred, l);
277 1.140.10.2 pooka vput(vp);
278 1.140.10.2 pooka return (error);
279 1.140.10.2 pooka }
280 1.140.10.2 pooka
281 1.140.10.2 pooka /*
282 1.140.10.2 pooka * Package up an I/O request on a vnode into a uio and do it.
283 1.140.10.2 pooka */
284 1.140.10.2 pooka int
285 1.140.10.2 pooka vn_rdwr(enum uio_rw rw, struct vnode *vp, void *base, int len, off_t offset,
286 1.140.10.2 pooka enum uio_seg segflg, int ioflg, kauth_cred_t cred, size_t *aresid,
287 1.140.10.2 pooka struct lwp *l)
288 1.140.10.2 pooka {
289 1.140.10.2 pooka struct uio auio;
290 1.140.10.2 pooka struct iovec aiov;
291 1.140.10.2 pooka int error;
292 1.140.10.2 pooka
293 1.140.10.2 pooka if ((ioflg & IO_NODELOCKED) == 0) {
294 1.140.10.2 pooka if (rw == UIO_READ) {
295 1.140.10.2 pooka vn_lock(vp, LK_SHARED | LK_RETRY);
296 1.140.10.2 pooka } else /* UIO_WRITE */ {
297 1.140.10.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
298 1.140.10.2 pooka }
299 1.140.10.2 pooka }
300 1.140.10.2 pooka auio.uio_iov = &aiov;
301 1.140.10.2 pooka auio.uio_iovcnt = 1;
302 1.140.10.2 pooka aiov.iov_base = base;
303 1.140.10.2 pooka aiov.iov_len = len;
304 1.140.10.2 pooka auio.uio_resid = len;
305 1.140.10.2 pooka auio.uio_offset = offset;
306 1.140.10.2 pooka auio.uio_rw = rw;
307 1.140.10.2 pooka if (segflg == UIO_SYSSPACE) {
308 1.140.10.2 pooka UIO_SETUP_SYSSPACE(&auio);
309 1.140.10.2 pooka } else {
310 1.140.10.2 pooka auio.uio_vmspace = l->l_proc->p_vmspace;
311 1.140.10.2 pooka }
312 1.140.10.2 pooka if (rw == UIO_READ) {
313 1.140.10.2 pooka error = VOP_READ(vp, &auio, ioflg, cred);
314 1.140.10.2 pooka } else {
315 1.140.10.2 pooka error = VOP_WRITE(vp, &auio, ioflg, cred);
316 1.140.10.2 pooka }
317 1.140.10.2 pooka if (aresid)
318 1.140.10.2 pooka *aresid = auio.uio_resid;
319 1.140.10.2 pooka else
320 1.140.10.2 pooka if (auio.uio_resid && error == 0)
321 1.140.10.2 pooka error = EIO;
322 1.140.10.2 pooka if ((ioflg & IO_NODELOCKED) == 0) {
323 1.140.10.2 pooka VOP_UNLOCK(vp, 0);
324 1.140.10.2 pooka }
325 1.140.10.2 pooka return (error);
326 1.140.10.2 pooka }
327 1.140.10.2 pooka
328 1.140.10.2 pooka int
329 1.140.10.2 pooka vn_readdir(struct file *fp, char *bf, int segflg, u_int count, int *done,
330 1.140.10.2 pooka struct lwp *l, off_t **cookies, int *ncookies)
331 1.140.10.2 pooka {
332 1.140.10.2 pooka struct vnode *vp = (struct vnode *)fp->f_data;
333 1.140.10.2 pooka struct iovec aiov;
334 1.140.10.2 pooka struct uio auio;
335 1.140.10.2 pooka int error, eofflag;
336 1.140.10.2 pooka
337 1.140.10.2 pooka /* Limit the size on any kernel buffers used by VOP_READDIR */
338 1.140.10.2 pooka count = min(MAXBSIZE, count);
339 1.140.10.2 pooka
340 1.140.10.2 pooka unionread:
341 1.140.10.2 pooka if (vp->v_type != VDIR)
342 1.140.10.2 pooka return (EINVAL);
343 1.140.10.2 pooka aiov.iov_base = bf;
344 1.140.10.2 pooka aiov.iov_len = count;
345 1.140.10.2 pooka auio.uio_iov = &aiov;
346 1.140.10.2 pooka auio.uio_iovcnt = 1;
347 1.140.10.2 pooka auio.uio_rw = UIO_READ;
348 1.140.10.2 pooka if (segflg == UIO_SYSSPACE) {
349 1.140.10.2 pooka UIO_SETUP_SYSSPACE(&auio);
350 1.140.10.2 pooka } else {
351 1.140.10.2 pooka KASSERT(l == curlwp);
352 1.140.10.2 pooka auio.uio_vmspace = l->l_proc->p_vmspace;
353 1.140.10.2 pooka }
354 1.140.10.2 pooka auio.uio_resid = count;
355 1.140.10.2 pooka vn_lock(vp, LK_SHARED | LK_RETRY);
356 1.140.10.2 pooka auio.uio_offset = fp->f_offset;
357 1.140.10.2 pooka error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookies,
358 1.140.10.2 pooka ncookies);
359 1.140.10.2 pooka fp->f_offset = auio.uio_offset;
360 1.140.10.2 pooka VOP_UNLOCK(vp, 0);
361 1.140.10.2 pooka if (error)
362 1.140.10.2 pooka return (error);
363 1.140.10.2 pooka
364 1.140.10.2 pooka #if defined(UNION) || defined(LKM)
365 1.140.10.2 pooka if (count == auio.uio_resid && vn_union_readdir_hook) {
366 1.140.10.2 pooka struct vnode *ovp = vp;
367 1.140.10.2 pooka
368 1.140.10.2 pooka error = (*vn_union_readdir_hook)(&vp, fp, l);
369 1.140.10.2 pooka if (error)
370 1.140.10.2 pooka return (error);
371 1.140.10.2 pooka if (vp != ovp)
372 1.140.10.2 pooka goto unionread;
373 1.140.10.2 pooka }
374 1.140.10.2 pooka #endif /* UNION || LKM */
375 1.140.10.2 pooka
376 1.140.10.2 pooka if (count == auio.uio_resid && (vp->v_flag & VROOT) &&
377 1.140.10.2 pooka (vp->v_mount->mnt_flag & MNT_UNION)) {
378 1.140.10.2 pooka struct vnode *tvp = vp;
379 1.140.10.2 pooka vp = vp->v_mount->mnt_vnodecovered;
380 1.140.10.2 pooka VREF(vp);
381 1.140.10.2 pooka fp->f_data = vp;
382 1.140.10.2 pooka fp->f_offset = 0;
383 1.140.10.2 pooka vrele(tvp);
384 1.140.10.2 pooka goto unionread;
385 1.140.10.2 pooka }
386 1.140.10.2 pooka *done = count - auio.uio_resid;
387 1.140.10.2 pooka return error;
388 1.140.10.2 pooka }
389 1.140.10.2 pooka
390 1.140.10.2 pooka /*
391 1.140.10.2 pooka * File table vnode read routine.
392 1.140.10.2 pooka */
393 1.140.10.2 pooka static int
394 1.140.10.2 pooka vn_read(struct file *fp, off_t *offset, struct uio *uio, kauth_cred_t cred,
395 1.140.10.2 pooka int flags)
396 1.140.10.2 pooka {
397 1.140.10.2 pooka struct vnode *vp = (struct vnode *)fp->f_data;
398 1.140.10.2 pooka int count, error, ioflag;
399 1.140.10.2 pooka struct lwp *l = curlwp;
400 1.140.10.2 pooka
401 1.140.10.2 pooka VOP_LEASE(vp, l, cred, LEASE_READ);
402 1.140.10.2 pooka ioflag = IO_ADV_ENCODE(fp->f_advice);
403 1.140.10.2 pooka if (fp->f_flag & FNONBLOCK)
404 1.140.10.2 pooka ioflag |= IO_NDELAY;
405 1.140.10.2 pooka if ((fp->f_flag & (FFSYNC | FRSYNC)) == (FFSYNC | FRSYNC))
406 1.140.10.2 pooka ioflag |= IO_SYNC;
407 1.140.10.2 pooka if (fp->f_flag & FALTIO)
408 1.140.10.2 pooka ioflag |= IO_ALTSEMANTICS;
409 1.140.10.2 pooka if (fp->f_flag & FDIRECT)
410 1.140.10.2 pooka ioflag |= IO_DIRECT;
411 1.140.10.2 pooka vn_lock(vp, LK_SHARED | LK_RETRY);
412 1.140.10.2 pooka uio->uio_offset = *offset;
413 1.140.10.2 pooka count = uio->uio_resid;
414 1.140.10.2 pooka error = VOP_READ(vp, uio, ioflag, cred);
415 1.140.10.2 pooka if (flags & FOF_UPDATE_OFFSET)
416 1.140.10.2 pooka *offset += count - uio->uio_resid;
417 1.140.10.2 pooka VOP_UNLOCK(vp, 0);
418 1.140.10.2 pooka return (error);
419 1.140.10.2 pooka }
420 1.140.10.2 pooka
421 1.140.10.2 pooka /*
422 1.140.10.2 pooka * File table vnode write routine.
423 1.140.10.2 pooka */
424 1.140.10.2 pooka static int
425 1.140.10.2 pooka vn_write(struct file *fp, off_t *offset, struct uio *uio, kauth_cred_t cred,
426 1.140.10.2 pooka int flags)
427 1.140.10.2 pooka {
428 1.140.10.2 pooka struct vnode *vp = (struct vnode *)fp->f_data;
429 1.140.10.2 pooka int count, error, ioflag = IO_UNIT;
430 1.140.10.2 pooka struct lwp *l = curlwp;
431 1.140.10.2 pooka
432 1.140.10.2 pooka if (vp->v_type == VREG && (fp->f_flag & O_APPEND))
433 1.140.10.2 pooka ioflag |= IO_APPEND;
434 1.140.10.2 pooka if (fp->f_flag & FNONBLOCK)
435 1.140.10.2 pooka ioflag |= IO_NDELAY;
436 1.140.10.2 pooka if (fp->f_flag & FFSYNC ||
437 1.140.10.2 pooka (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
438 1.140.10.2 pooka ioflag |= IO_SYNC;
439 1.140.10.2 pooka else if (fp->f_flag & FDSYNC)
440 1.140.10.2 pooka ioflag |= IO_DSYNC;
441 1.140.10.2 pooka if (fp->f_flag & FALTIO)
442 1.140.10.2 pooka ioflag |= IO_ALTSEMANTICS;
443 1.140.10.2 pooka if (fp->f_flag & FDIRECT)
444 1.140.10.2 pooka ioflag |= IO_DIRECT;
445 1.140.10.2 pooka VOP_LEASE(vp, l, cred, LEASE_WRITE);
446 1.140.10.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
447 1.140.10.2 pooka uio->uio_offset = *offset;
448 1.140.10.2 pooka count = uio->uio_resid;
449 1.140.10.2 pooka error = VOP_WRITE(vp, uio, ioflag, cred);
450 1.140.10.2 pooka if (flags & FOF_UPDATE_OFFSET) {
451 1.140.10.2 pooka if (ioflag & IO_APPEND)
452 1.140.10.2 pooka *offset = uio->uio_offset;
453 1.140.10.2 pooka else
454 1.140.10.2 pooka *offset += count - uio->uio_resid;
455 1.140.10.2 pooka }
456 1.140.10.2 pooka VOP_UNLOCK(vp, 0);
457 1.140.10.2 pooka return (error);
458 1.140.10.2 pooka }
459 1.140.10.2 pooka
460 1.140.10.2 pooka /*
461 1.140.10.2 pooka * File table vnode stat routine.
462 1.140.10.2 pooka */
463 1.140.10.2 pooka static int
464 1.140.10.2 pooka vn_statfile(struct file *fp, struct stat *sb, struct lwp *l)
465 1.140.10.2 pooka {
466 1.140.10.2 pooka struct vnode *vp = (struct vnode *)fp->f_data;
467 1.140.10.2 pooka
468 1.140.10.2 pooka return vn_stat(vp, sb, l);
469 1.140.10.2 pooka }
470 1.140.10.2 pooka
471 1.140.10.2 pooka int
472 1.140.10.2 pooka vn_stat(struct vnode *vp, struct stat *sb, struct lwp *l)
473 1.140.10.2 pooka {
474 1.140.10.2 pooka struct vattr va;
475 1.140.10.2 pooka int error;
476 1.140.10.2 pooka mode_t mode;
477 1.140.10.2 pooka
478 1.140.10.2 pooka error = VOP_GETATTR(vp, &va, l->l_cred, l);
479 1.140.10.2 pooka if (error)
480 1.140.10.2 pooka return (error);
481 1.140.10.2 pooka /*
482 1.140.10.2 pooka * Copy from vattr table
483 1.140.10.2 pooka */
484 1.140.10.2 pooka sb->st_dev = va.va_fsid;
485 1.140.10.2 pooka sb->st_ino = va.va_fileid;
486 1.140.10.2 pooka mode = va.va_mode;
487 1.140.10.2 pooka switch (vp->v_type) {
488 1.140.10.2 pooka case VREG:
489 1.140.10.2 pooka mode |= S_IFREG;
490 1.140.10.2 pooka break;
491 1.140.10.2 pooka case VDIR:
492 1.140.10.2 pooka mode |= S_IFDIR;
493 1.140.10.2 pooka break;
494 1.140.10.2 pooka case VBLK:
495 1.140.10.2 pooka mode |= S_IFBLK;
496 1.140.10.2 pooka break;
497 1.140.10.2 pooka case VCHR:
498 1.140.10.2 pooka mode |= S_IFCHR;
499 1.140.10.2 pooka break;
500 1.140.10.2 pooka case VLNK:
501 1.140.10.2 pooka mode |= S_IFLNK;
502 1.140.10.2 pooka break;
503 1.140.10.2 pooka case VSOCK:
504 1.140.10.2 pooka mode |= S_IFSOCK;
505 1.140.10.2 pooka break;
506 1.140.10.2 pooka case VFIFO:
507 1.140.10.2 pooka mode |= S_IFIFO;
508 1.140.10.2 pooka break;
509 1.140.10.2 pooka default:
510 1.140.10.2 pooka return (EBADF);
511 1.140.10.2 pooka };
512 1.140.10.2 pooka sb->st_mode = mode;
513 1.140.10.2 pooka sb->st_nlink = va.va_nlink;
514 1.140.10.2 pooka sb->st_uid = va.va_uid;
515 1.140.10.2 pooka sb->st_gid = va.va_gid;
516 1.140.10.2 pooka sb->st_rdev = va.va_rdev;
517 1.140.10.2 pooka sb->st_size = va.va_size;
518 1.140.10.2 pooka sb->st_atimespec = va.va_atime;
519 1.140.10.2 pooka sb->st_mtimespec = va.va_mtime;
520 1.140.10.2 pooka sb->st_ctimespec = va.va_ctime;
521 1.140.10.2 pooka sb->st_birthtimespec = va.va_birthtime;
522 1.140.10.2 pooka sb->st_blksize = va.va_blocksize;
523 1.140.10.2 pooka sb->st_flags = va.va_flags;
524 1.140.10.2 pooka sb->st_gen = 0;
525 1.140.10.2 pooka sb->st_blocks = va.va_bytes / S_BLKSIZE;
526 1.140.10.2 pooka return (0);
527 1.140.10.2 pooka }
528 1.140.10.2 pooka
529 1.140.10.2 pooka /*
530 1.140.10.2 pooka * File table vnode fcntl routine.
531 1.140.10.2 pooka */
532 1.140.10.2 pooka static int
533 1.140.10.2 pooka vn_fcntl(struct file *fp, u_int com, void *data, struct lwp *l)
534 1.140.10.2 pooka {
535 1.140.10.2 pooka struct vnode *vp = ((struct vnode *)fp->f_data);
536 1.140.10.2 pooka int error;
537 1.140.10.2 pooka
538 1.140.10.2 pooka error = VOP_FCNTL(vp, com, data, fp->f_flag, l->l_cred, l);
539 1.140.10.2 pooka return (error);
540 1.140.10.2 pooka }
541 1.140.10.2 pooka
542 1.140.10.2 pooka /*
543 1.140.10.2 pooka * File table vnode ioctl routine.
544 1.140.10.2 pooka */
545 1.140.10.2 pooka static int
546 1.140.10.2 pooka vn_ioctl(struct file *fp, u_long com, void *data, struct lwp *l)
547 1.140.10.2 pooka {
548 1.140.10.2 pooka struct vnode *vp = ((struct vnode *)fp->f_data), *ovp;
549 1.140.10.2 pooka struct proc *p = l->l_proc;
550 1.140.10.2 pooka struct vattr vattr;
551 1.140.10.2 pooka int error;
552 1.140.10.2 pooka
553 1.140.10.2 pooka switch (vp->v_type) {
554 1.140.10.2 pooka
555 1.140.10.2 pooka case VREG:
556 1.140.10.2 pooka case VDIR:
557 1.140.10.2 pooka if (com == FIONREAD) {
558 1.140.10.2 pooka error = VOP_GETATTR(vp, &vattr, l->l_cred, l);
559 1.140.10.2 pooka if (error)
560 1.140.10.2 pooka return (error);
561 1.140.10.2 pooka *(int *)data = vattr.va_size - fp->f_offset;
562 1.140.10.2 pooka return (0);
563 1.140.10.2 pooka }
564 1.140.10.2 pooka if ((com == FIONWRITE) || (com == FIONSPACE)) {
565 1.140.10.2 pooka /*
566 1.140.10.2 pooka * Files don't have send queues, so there never
567 1.140.10.2 pooka * are any bytes in them, nor is there any
568 1.140.10.2 pooka * open space in them.
569 1.140.10.2 pooka */
570 1.140.10.2 pooka *(int *)data = 0;
571 1.140.10.2 pooka return (0);
572 1.140.10.2 pooka }
573 1.140.10.2 pooka if (com == FIOGETBMAP) {
574 1.140.10.2 pooka daddr_t *block;
575 1.140.10.2 pooka
576 1.140.10.2 pooka if (*(daddr_t *)data < 0)
577 1.140.10.2 pooka return (EINVAL);
578 1.140.10.2 pooka block = (daddr_t *)data;
579 1.140.10.2 pooka return (VOP_BMAP(vp, *block, NULL, block, NULL));
580 1.140.10.2 pooka }
581 1.140.10.2 pooka if (com == OFIOGETBMAP) {
582 1.140.10.2 pooka daddr_t ibn, obn;
583 1.140.10.2 pooka
584 1.140.10.2 pooka if (*(int32_t *)data < 0)
585 1.140.10.2 pooka return (EINVAL);
586 1.140.10.2 pooka ibn = (daddr_t)*(int32_t *)data;
587 1.140.10.2 pooka error = VOP_BMAP(vp, ibn, NULL, &obn, NULL);
588 1.140.10.2 pooka *(int32_t *)data = (int32_t)obn;
589 1.140.10.2 pooka return error;
590 1.140.10.2 pooka }
591 1.140.10.2 pooka if (com == FIONBIO || com == FIOASYNC) /* XXX */
592 1.140.10.2 pooka return (0); /* XXX */
593 1.140.10.2 pooka /* fall into ... */
594 1.140.10.2 pooka case VFIFO:
595 1.140.10.2 pooka case VCHR:
596 1.140.10.2 pooka case VBLK:
597 1.140.10.2 pooka error = VOP_IOCTL(vp, com, data, fp->f_flag,
598 1.140.10.2 pooka l->l_cred, l);
599 1.140.10.2 pooka if (error == 0 && com == TIOCSCTTY) {
600 1.140.10.2 pooka VREF(vp);
601 1.140.10.2 pooka mutex_enter(&proclist_lock);
602 1.140.10.2 pooka ovp = p->p_session->s_ttyvp;
603 1.140.10.2 pooka p->p_session->s_ttyvp = vp;
604 1.140.10.2 pooka mutex_exit(&proclist_lock);
605 1.140.10.2 pooka if (ovp != NULL)
606 1.140.10.2 pooka vrele(ovp);
607 1.140.10.2 pooka }
608 1.140.10.2 pooka return (error);
609 1.140.10.2 pooka
610 1.140.10.2 pooka default:
611 1.140.10.2 pooka return (EPASSTHROUGH);
612 1.140.10.2 pooka }
613 1.140.10.2 pooka }
614 1.140.10.2 pooka
615 1.140.10.2 pooka /*
616 1.140.10.2 pooka * File table vnode poll routine.
617 1.140.10.2 pooka */
618 1.140.10.2 pooka static int
619 1.140.10.2 pooka vn_poll(struct file *fp, int events, struct lwp *l)
620 1.140.10.2 pooka {
621 1.140.10.2 pooka
622 1.140.10.2 pooka return (VOP_POLL(((struct vnode *)fp->f_data), events, l));
623 1.140.10.2 pooka }
624 1.140.10.2 pooka
625 1.140.10.2 pooka /*
626 1.140.10.2 pooka * File table vnode kqfilter routine.
627 1.140.10.2 pooka */
628 1.140.10.2 pooka int
629 1.140.10.2 pooka vn_kqfilter(struct file *fp, struct knote *kn)
630 1.140.10.2 pooka {
631 1.140.10.2 pooka
632 1.140.10.2 pooka return (VOP_KQFILTER((struct vnode *)fp->f_data, kn));
633 1.140.10.2 pooka }
634 1.140.10.2 pooka
635 1.140.10.2 pooka /*
636 1.140.10.2 pooka * Check that the vnode is still valid, and if so
637 1.140.10.2 pooka * acquire requested lock.
638 1.140.10.2 pooka */
639 1.140.10.2 pooka int
640 1.140.10.2 pooka vn_lock(struct vnode *vp, int flags)
641 1.140.10.2 pooka {
642 1.140.10.2 pooka int error;
643 1.140.10.2 pooka
644 1.140.10.2 pooka #if 0
645 1.140.10.2 pooka KASSERT(vp->v_usecount > 0 || (flags & LK_INTERLOCK) != 0
646 1.140.10.2 pooka || (vp->v_flag & VONWORKLST) != 0);
647 1.140.10.2 pooka #endif
648 1.140.10.2 pooka KASSERT((flags &
649 1.140.10.2 pooka ~(LK_INTERLOCK|LK_SHARED|LK_EXCLUSIVE|LK_DRAIN|LK_NOWAIT|LK_RETRY|
650 1.140.10.2 pooka LK_SETRECURSE|LK_CANRECURSE))
651 1.140.10.2 pooka == 0);
652 1.140.10.2 pooka
653 1.140.10.2 pooka do {
654 1.140.10.2 pooka if ((flags & LK_INTERLOCK) == 0)
655 1.140.10.2 pooka simple_lock(&vp->v_interlock);
656 1.140.10.2 pooka if (vp->v_flag & VXLOCK) {
657 1.140.10.2 pooka if (flags & LK_NOWAIT) {
658 1.140.10.2 pooka simple_unlock(&vp->v_interlock);
659 1.140.10.2 pooka return EBUSY;
660 1.140.10.2 pooka }
661 1.140.10.2 pooka vp->v_flag |= VXWANT;
662 1.140.10.2 pooka ltsleep(vp, PINOD | PNORELOCK,
663 1.140.10.2 pooka "vn_lock", 0, &vp->v_interlock);
664 1.140.10.2 pooka error = ENOENT;
665 1.140.10.2 pooka } else {
666 1.140.10.2 pooka error = VOP_LOCK(vp,
667 1.140.10.2 pooka (flags & ~LK_RETRY) | LK_INTERLOCK);
668 1.140.10.2 pooka if (error == 0 || error == EDEADLK || error == EBUSY)
669 1.140.10.2 pooka return (error);
670 1.140.10.2 pooka }
671 1.140.10.2 pooka flags &= ~LK_INTERLOCK;
672 1.140.10.2 pooka } while (flags & LK_RETRY);
673 1.140.10.2 pooka return (error);
674 1.140.10.2 pooka }
675 1.140.10.2 pooka
676 1.140.10.2 pooka /*
677 1.140.10.2 pooka * File table vnode close routine.
678 1.140.10.2 pooka */
679 1.140.10.2 pooka static int
680 1.140.10.2 pooka vn_closefile(struct file *fp, struct lwp *l)
681 1.140.10.2 pooka {
682 1.140.10.2 pooka
683 1.140.10.2 pooka return (vn_close(((struct vnode *)fp->f_data), fp->f_flag,
684 1.140.10.2 pooka fp->f_cred, l));
685 1.140.10.2 pooka }
686 1.140.10.2 pooka
687 1.140.10.2 pooka /*
688 1.140.10.2 pooka * Enable LK_CANRECURSE on lock. Return prior status.
689 1.140.10.2 pooka */
690 1.140.10.2 pooka u_int
691 1.140.10.2 pooka vn_setrecurse(struct vnode *vp)
692 1.140.10.2 pooka {
693 1.140.10.2 pooka struct lock *lkp = &vp->v_lock;
694 1.140.10.2 pooka u_int retval = lkp->lk_flags & LK_CANRECURSE;
695 1.140.10.2 pooka
696 1.140.10.2 pooka lkp->lk_flags |= LK_CANRECURSE;
697 1.140.10.2 pooka return retval;
698 1.140.10.2 pooka }
699 1.140.10.2 pooka
700 1.140.10.2 pooka /*
701 1.140.10.2 pooka * Called when done with locksetrecurse.
702 1.140.10.2 pooka */
703 1.140.10.2 pooka void
704 1.140.10.2 pooka vn_restorerecurse(struct vnode *vp, u_int flags)
705 1.140.10.2 pooka {
706 1.140.10.2 pooka struct lock *lkp = &vp->v_lock;
707 1.140.10.2 pooka
708 1.140.10.2 pooka lkp->lk_flags &= ~LK_CANRECURSE;
709 1.140.10.2 pooka lkp->lk_flags |= flags;
710 1.140.10.2 pooka }
711 1.140.10.2 pooka
712 1.140.10.2 pooka int
713 1.140.10.2 pooka vn_cow_establish(struct vnode *vp,
714 1.140.10.2 pooka int (*func)(void *, struct buf *), void *cookie)
715 1.140.10.2 pooka {
716 1.140.10.2 pooka int s;
717 1.140.10.2 pooka struct spec_cow_entry *e;
718 1.140.10.2 pooka
719 1.140.10.2 pooka MALLOC(e, struct spec_cow_entry *, sizeof(struct spec_cow_entry),
720 1.140.10.2 pooka M_DEVBUF, M_WAITOK);
721 1.140.10.2 pooka e->ce_func = func;
722 1.140.10.2 pooka e->ce_cookie = cookie;
723 1.140.10.2 pooka
724 1.140.10.2 pooka SPEC_COW_LOCK(vp->v_specinfo, s);
725 1.140.10.2 pooka vp->v_spec_cow_req++;
726 1.140.10.2 pooka while (vp->v_spec_cow_count > 0)
727 1.140.10.2 pooka ltsleep(&vp->v_spec_cow_req, PRIBIO, "cowlist", 0,
728 1.140.10.2 pooka &vp->v_spec_cow_slock);
729 1.140.10.2 pooka
730 1.140.10.2 pooka SLIST_INSERT_HEAD(&vp->v_spec_cow_head, e, ce_list);
731 1.140.10.2 pooka
732 1.140.10.2 pooka vp->v_spec_cow_req--;
733 1.140.10.2 pooka if (vp->v_spec_cow_req == 0)
734 1.140.10.2 pooka wakeup(&vp->v_spec_cow_req);
735 1.140.10.2 pooka SPEC_COW_UNLOCK(vp->v_specinfo, s);
736 1.140.10.2 pooka
737 1.140.10.2 pooka return 0;
738 1.140.10.2 pooka }
739 1.140.10.2 pooka
740 1.140.10.2 pooka int
741 1.140.10.2 pooka vn_cow_disestablish(struct vnode *vp,
742 1.140.10.2 pooka int (*func)(void *, struct buf *), void *cookie)
743 1.140.10.2 pooka {
744 1.140.10.2 pooka int s;
745 1.140.10.2 pooka struct spec_cow_entry *e;
746 1.140.10.2 pooka
747 1.140.10.2 pooka SPEC_COW_LOCK(vp->v_specinfo, s);
748 1.140.10.2 pooka vp->v_spec_cow_req++;
749 1.140.10.2 pooka while (vp->v_spec_cow_count > 0)
750 1.140.10.2 pooka ltsleep(&vp->v_spec_cow_req, PRIBIO, "cowlist", 0,
751 1.140.10.2 pooka &vp->v_spec_cow_slock);
752 1.140.10.2 pooka
753 1.140.10.2 pooka SLIST_FOREACH(e, &vp->v_spec_cow_head, ce_list)
754 1.140.10.2 pooka if (e->ce_func == func && e->ce_cookie == cookie) {
755 1.140.10.2 pooka SLIST_REMOVE(&vp->v_spec_cow_head, e,
756 1.140.10.2 pooka spec_cow_entry, ce_list);
757 1.140.10.2 pooka FREE(e, M_DEVBUF);
758 1.140.10.2 pooka break;
759 1.140.10.2 pooka }
760 1.140.10.2 pooka
761 1.140.10.2 pooka vp->v_spec_cow_req--;
762 1.140.10.2 pooka if (vp->v_spec_cow_req == 0)
763 1.140.10.2 pooka wakeup(&vp->v_spec_cow_req);
764 1.140.10.2 pooka SPEC_COW_UNLOCK(vp->v_specinfo, s);
765 1.140.10.2 pooka
766 1.140.10.2 pooka return e ? 0 : EINVAL;
767 1.140.10.2 pooka }
768 1.140.10.2 pooka
769 1.140.10.2 pooka /*
770 1.140.10.2 pooka * Simplified in-kernel wrapper calls for extended attribute access.
771 1.140.10.2 pooka * Both calls pass in a NULL credential, authorizing a "kernel" access.
772 1.140.10.2 pooka * Set IO_NODELOCKED in ioflg if the vnode is already locked.
773 1.140.10.2 pooka */
774 1.140.10.2 pooka int
775 1.140.10.2 pooka vn_extattr_get(struct vnode *vp, int ioflg, int attrnamespace,
776 1.140.10.2 pooka const char *attrname, size_t *buflen, void *bf, struct lwp *l)
777 1.140.10.2 pooka {
778 1.140.10.2 pooka struct uio auio;
779 1.140.10.2 pooka struct iovec aiov;
780 1.140.10.2 pooka int error;
781 1.140.10.2 pooka
782 1.140.10.2 pooka aiov.iov_len = *buflen;
783 1.140.10.2 pooka aiov.iov_base = bf;
784 1.140.10.2 pooka
785 1.140.10.2 pooka auio.uio_iov = &aiov;
786 1.140.10.2 pooka auio.uio_iovcnt = 1;
787 1.140.10.2 pooka auio.uio_rw = UIO_READ;
788 1.140.10.2 pooka auio.uio_offset = 0;
789 1.140.10.2 pooka auio.uio_resid = *buflen;
790 1.140.10.2 pooka UIO_SETUP_SYSSPACE(&auio);
791 1.140.10.2 pooka
792 1.140.10.2 pooka if ((ioflg & IO_NODELOCKED) == 0)
793 1.140.10.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
794 1.140.10.2 pooka
795 1.140.10.2 pooka error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio, NULL, NULL,
796 1.140.10.2 pooka l);
797 1.140.10.2 pooka
798 1.140.10.2 pooka if ((ioflg & IO_NODELOCKED) == 0)
799 1.140.10.2 pooka VOP_UNLOCK(vp, 0);
800 1.140.10.2 pooka
801 1.140.10.2 pooka if (error == 0)
802 1.140.10.2 pooka *buflen = *buflen - auio.uio_resid;
803 1.140.10.2 pooka
804 1.140.10.2 pooka return (error);
805 1.140.10.2 pooka }
806 1.140.10.2 pooka
807 1.140.10.2 pooka /*
808 1.140.10.2 pooka * XXX Failure mode if partially written?
809 1.140.10.2 pooka */
810 1.140.10.2 pooka int
811 1.140.10.2 pooka vn_extattr_set(struct vnode *vp, int ioflg, int attrnamespace,
812 1.140.10.2 pooka const char *attrname, size_t buflen, const void *bf, struct lwp *l)
813 1.140.10.2 pooka {
814 1.140.10.2 pooka struct uio auio;
815 1.140.10.2 pooka struct iovec aiov;
816 1.140.10.2 pooka int error;
817 1.140.10.2 pooka
818 1.140.10.2 pooka aiov.iov_len = buflen;
819 1.140.10.2 pooka aiov.iov_base = __UNCONST(bf); /* XXXUNCONST kills const */
820 1.140.10.2 pooka
821 1.140.10.2 pooka auio.uio_iov = &aiov;
822 1.140.10.2 pooka auio.uio_iovcnt = 1;
823 1.140.10.2 pooka auio.uio_rw = UIO_WRITE;
824 1.140.10.2 pooka auio.uio_offset = 0;
825 1.140.10.2 pooka auio.uio_resid = buflen;
826 1.140.10.2 pooka UIO_SETUP_SYSSPACE(&auio);
827 1.140.10.2 pooka
828 1.140.10.2 pooka if ((ioflg & IO_NODELOCKED) == 0) {
829 1.140.10.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
830 1.140.10.2 pooka }
831 1.140.10.2 pooka
832 1.140.10.2 pooka error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio, NULL, l);
833 1.140.10.2 pooka
834 1.140.10.2 pooka if ((ioflg & IO_NODELOCKED) == 0) {
835 1.140.10.2 pooka VOP_UNLOCK(vp, 0);
836 1.140.10.2 pooka }
837 1.140.10.2 pooka
838 1.140.10.2 pooka return (error);
839 1.140.10.2 pooka }
840 1.140.10.2 pooka
841 1.140.10.2 pooka int
842 1.140.10.2 pooka vn_extattr_rm(struct vnode *vp, int ioflg, int attrnamespace,
843 1.140.10.2 pooka const char *attrname, struct lwp *l)
844 1.140.10.2 pooka {
845 1.140.10.2 pooka int error;
846 1.140.10.2 pooka
847 1.140.10.2 pooka if ((ioflg & IO_NODELOCKED) == 0) {
848 1.140.10.2 pooka vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
849 1.140.10.2 pooka }
850 1.140.10.2 pooka
851 1.140.10.2 pooka error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, NULL, l);
852 1.140.10.2 pooka if (error == EOPNOTSUPP)
853 1.140.10.2 pooka error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
854 1.140.10.2 pooka NULL, l);
855 1.140.10.2 pooka
856 1.140.10.2 pooka if ((ioflg & IO_NODELOCKED) == 0) {
857 1.140.10.2 pooka VOP_UNLOCK(vp, 0);
858 1.140.10.2 pooka }
859 1.140.10.2 pooka
860 1.140.10.2 pooka return (error);
861 1.140.10.2 pooka }
862 1.140.10.2 pooka
863 1.140.10.2 pooka void
864 1.140.10.2 pooka vn_ra_allocctx(struct vnode *vp)
865 1.140.10.2 pooka {
866 1.140.10.2 pooka struct uvm_ractx *ra = NULL;
867 1.140.10.2 pooka
868 1.140.10.2 pooka if (vp->v_type != VREG) {
869 1.140.10.2 pooka return;
870 1.140.10.2 pooka }
871 1.140.10.2 pooka if (vp->v_ractx != NULL) {
872 1.140.10.2 pooka return;
873 1.140.10.2 pooka }
874 1.140.10.2 pooka simple_lock(&vp->v_interlock);
875 1.140.10.2 pooka if (vp->v_ractx == NULL) {
876 1.140.10.2 pooka simple_unlock(&vp->v_interlock);
877 1.140.10.2 pooka ra = uvm_ra_allocctx();
878 1.140.10.2 pooka simple_lock(&vp->v_interlock);
879 1.140.10.2 pooka if (ra != NULL && vp->v_ractx == NULL) {
880 1.140.10.2 pooka vp->v_ractx = ra;
881 1.140.10.2 pooka ra = NULL;
882 1.140.10.2 pooka }
883 1.140.10.2 pooka }
884 1.140.10.2 pooka simple_unlock(&vp->v_interlock);
885 1.140.10.2 pooka if (ra != NULL) {
886 1.140.10.2 pooka uvm_ra_freectx(ra);
887 1.140.10.2 pooka }
888 1.140.10.2 pooka }
889