Commit | Line | Data |
---|---|---|
805e021f CE |
1 | /* |
2 | * OpenBSD specific vnodeops + other misc interface glue | |
3 | * Original NetBSD version for Transarc afs by John Kohl <jtk@MIT.EDU> | |
4 | * OpenBSD version by Jim Rees <rees@umich.edu> | |
5 | * | |
6 | * $Id$ | |
7 | */ | |
8 | ||
9 | /* | |
10 | copyright 2002 | |
11 | the regents of the university of michigan | |
12 | all rights reserved | |
13 | ||
14 | permission is granted to use, copy, create derivative works | |
15 | and redistribute this software and such derivative works | |
16 | for any purpose, so long as the name of the university of | |
17 | michigan is not used in any advertising or publicity | |
18 | pertaining to the use or distribution of this software | |
19 | without specific, written prior authorization. if the | |
20 | above copyright notice or any other identification of the | |
21 | university of michigan is included in any copy of any | |
22 | portion of this software, then the disclaimer below must | |
23 | also be included. | |
24 | ||
25 | this software is provided as is, without representation | |
26 | from the university of michigan as to its fitness for any | |
27 | purpose, and without warranty by the university of | |
28 | michigan of any kind, either express or implied, including | |
29 | without limitation the implied warranties of | |
30 | merchantability and fitness for a particular purpose. the | |
31 | regents of the university of michigan shall not be liable | |
32 | for any damages, including special, indirect, incidental, or | |
33 | consequential damages, with respect to any claim arising | |
34 | out of or in connection with the use of the software, even | |
35 | if it has been or is hereafter advised of the possibility of | |
36 | such damages. | |
37 | */ | |
38 | ||
39 | /* | |
40 | Copyright 1995 Massachusetts Institute of Technology. All Rights | |
41 | Reserved. | |
42 | ||
43 | You are hereby granted a worldwide, irrevocable, paid-up, right and | |
44 | license to use, execute, display, modify, copy and distribute MIT's | |
45 | Modifications, provided that (i) you abide by the terms and conditions | |
46 | of your OpenAFS License Agreement, and (ii) you do not use the name | |
47 | of MIT in any advertising or publicity without the prior written consent | |
48 | of MIT. MIT disclaims all liability for your use of MIT's | |
49 | Modifications. MIT's Modifications are provided "AS IS" WITHOUT | |
50 | WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, | |
51 | ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR | |
52 | NONINFRINGEMENT. | |
53 | */ | |
54 | ||
55 | /* | |
56 | * A bunch of code cribbed from NetBSD ufs_vnops.c, ffs_vnops.c, and | |
57 | * nfs_vnops.c which carry this copyright: | |
58 | */ | |
59 | /* | |
60 | * Copyright (c) 1982, 1986, 1989, 1993 | |
61 | * The Regents of the University of California. All rights reserved. | |
62 | * (c) UNIX System Laboratories, Inc. | |
63 | * All or some portions of this file are derived from material licensed | |
64 | * to the University of California by American Telephone and Telegraph | |
65 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | |
66 | * the permission of UNIX System Laboratories, Inc. | |
67 | * | |
68 | * Redistribution and use in source and binary forms, with or without | |
69 | * modification, are permitted provided that the following conditions | |
70 | * are met: | |
71 | * 1. Redistributions of source code must retain the above copyright | |
72 | * notice, this list of conditions and the following disclaimer. | |
73 | * 2. Redistributions in binary form must reproduce the above copyright | |
74 | * notice, this list of conditions and the following disclaimer in the | |
75 | * documentation and/or other materials provided with the distribution. | |
76 | * 3. All advertising materials mentioning features or use of this software | |
77 | * must display the following acknowledgement: | |
78 | * This product includes software developed by the University of | |
79 | * California, Berkeley and its contributors. | |
80 | * 4. Neither the name of the University nor the names of its contributors | |
81 | * may be used to endorse or promote products derived from this software | |
82 | * without specific prior written permission. | |
83 | * | |
84 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
85 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
86 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
87 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
88 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
89 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
90 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
91 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
92 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
93 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
94 | * SUCH DAMAGE. | |
95 | * | |
96 | */ | |
97 | ||
98 | #include <afsconfig.h> | |
99 | #include "afs/param.h" | |
100 | ||
101 | ||
102 | #include "afs/sysincludes.h" /* Standard vendor system headers */ | |
103 | #include "afs/afsincludes.h" /* Afs-based standard headers */ | |
104 | #include "afs/afs_stats.h" /* statistics */ | |
105 | ||
106 | #include <sys/malloc.h> | |
107 | #include <sys/namei.h> | |
108 | #ifdef AFS_OBSD36_ENV | |
109 | #include <sys/pool.h> | |
110 | #endif | |
111 | ||
112 | #include "afs/afs_cbqueue.h" | |
113 | #include "afs/nfsclient.h" | |
114 | #include "afs/afs_osidnlc.h" | |
115 | ||
116 | #define M_AFSNODE (M_TEMP-1) /* XXX */ | |
117 | ||
118 | int afs_obsd_lookup(void *); | |
119 | int afs_obsd_create(void *); | |
120 | int afs_obsd_mknod(void *); | |
121 | int afs_obsd_open(void *); | |
122 | int afs_obsd_close(void *); | |
123 | int afs_obsd_access(void *); | |
124 | int afs_obsd_getattr(void *); | |
125 | int afs_obsd_setattr(void *); | |
126 | int afs_obsd_read(void *); | |
127 | int afs_obsd_write(void *); | |
128 | int afs_obsd_ioctl(void *); | |
129 | int afs_obsd_select(void *); | |
130 | int afs_obsd_fsync(void *); | |
131 | int afs_obsd_remove(void *); | |
132 | int afs_obsd_link(void *); | |
133 | int afs_obsd_rename(void *); | |
134 | int afs_obsd_mkdir(void *); | |
135 | int afs_obsd_rmdir(void *); | |
136 | int afs_obsd_symlink(void *); | |
137 | int afs_obsd_readdir(void *); | |
138 | int afs_obsd_readlink(void *); | |
139 | int afs_obsd_inactive(void *); | |
140 | int afs_obsd_reclaim(void *); | |
141 | int afs_obsd_lock(void *); | |
142 | int afs_obsd_unlock(void *); | |
143 | int afs_obsd_bmap(void *); | |
144 | int afs_obsd_strategy(void *); | |
145 | int afs_obsd_print(void *); | |
146 | int afs_obsd_islocked(void *); | |
147 | int afs_obsd_pathconf(void *); | |
148 | int afs_obsd_advlock(void *); | |
149 | ||
150 | #define afs_obsd_opnotsupp \ | |
151 | ((int (*) __P((void *)))eopnotsupp) | |
152 | #define afs_obsd_reallocblks afs_obsd_opnotsupp | |
153 | ||
154 | #if defined(AFS_OBSD49_ENV) | |
155 | ||
156 | struct vops afs_vops = { | |
157 | .vop_lookup = afs_obsd_lookup, | |
158 | .vop_create = afs_obsd_create, | |
159 | .vop_mknod = afs_obsd_mknod, | |
160 | .vop_open = afs_obsd_open, | |
161 | .vop_close = afs_obsd_close, | |
162 | .vop_access = afs_obsd_access, | |
163 | .vop_getattr = afs_obsd_getattr, | |
164 | .vop_setattr = afs_obsd_setattr, | |
165 | .vop_read = afs_obsd_read, | |
166 | .vop_write = afs_obsd_write, | |
167 | .vop_ioctl = afs_obsd_ioctl, | |
168 | .vop_poll = afs_obsd_select, | |
169 | .vop_fsync = afs_obsd_fsync, | |
170 | .vop_remove = afs_obsd_remove, | |
171 | .vop_link = afs_obsd_link, | |
172 | .vop_rename = afs_obsd_rename, | |
173 | .vop_mkdir = afs_obsd_mkdir, | |
174 | .vop_rmdir = afs_obsd_rmdir, | |
175 | .vop_symlink = afs_obsd_symlink, | |
176 | .vop_readdir = afs_obsd_readdir, | |
177 | .vop_readlink = afs_obsd_readlink, | |
178 | .vop_abortop = vop_generic_abortop, | |
179 | .vop_inactive = afs_obsd_inactive, | |
180 | .vop_reclaim = afs_obsd_reclaim, | |
181 | .vop_lock = afs_obsd_lock, | |
182 | .vop_unlock = afs_obsd_unlock, | |
183 | .vop_bmap = afs_obsd_bmap, | |
184 | .vop_strategy = afs_obsd_strategy, | |
185 | .vop_print = afs_obsd_print, | |
186 | .vop_islocked = afs_obsd_islocked, | |
187 | .vop_pathconf = afs_obsd_pathconf, | |
188 | .vop_advlock = afs_obsd_advlock, | |
189 | .vop_bwrite = vop_generic_bwrite, | |
190 | }; | |
191 | ||
192 | #else | |
193 | ||
194 | /* Global vfs data structures for AFS. */ | |
195 | int (**afs_vnodeop_p) __P((void *)); | |
196 | struct vnodeopv_entry_desc afs_vnodeop_entries[] = { | |
197 | #ifdef AFS_OBSD44_ENV /* feel free to zero in on this */ | |
198 | {&vop_default_desc, eopnotsupp}, | |
199 | #else | |
200 | {&vop_default_desc, vn_default_error}, | |
201 | #endif | |
202 | {&vop_lookup_desc, afs_obsd_lookup}, /* lookup */ | |
203 | {&vop_create_desc, afs_obsd_create}, /* create */ | |
204 | {&vop_mknod_desc, afs_obsd_mknod}, /* mknod */ | |
205 | {&vop_open_desc, afs_obsd_open}, /* open */ | |
206 | {&vop_close_desc, afs_obsd_close}, /* close */ | |
207 | {&vop_access_desc, afs_obsd_access}, /* access */ | |
208 | {&vop_getattr_desc, afs_obsd_getattr}, /* getattr */ | |
209 | {&vop_setattr_desc, afs_obsd_setattr}, /* setattr */ | |
210 | {&vop_read_desc, afs_obsd_read}, /* read */ | |
211 | {&vop_write_desc, afs_obsd_write}, /* write */ | |
212 | {&vop_ioctl_desc, afs_obsd_ioctl}, /* XXX ioctl */ | |
213 | #ifdef AFS_OBSD35_ENV | |
214 | {&vop_poll_desc, afs_obsd_select}, /* select */ | |
215 | #else | |
216 | {&vop_select_desc, afs_obsd_select}, /* select */ | |
217 | #endif | |
218 | {&vop_fsync_desc, afs_obsd_fsync}, /* fsync */ | |
219 | {&vop_remove_desc, afs_obsd_remove}, /* remove */ | |
220 | {&vop_link_desc, afs_obsd_link}, /* link */ | |
221 | {&vop_rename_desc, afs_obsd_rename}, /* rename */ | |
222 | {&vop_mkdir_desc, afs_obsd_mkdir}, /* mkdir */ | |
223 | {&vop_rmdir_desc, afs_obsd_rmdir}, /* rmdir */ | |
224 | {&vop_symlink_desc, afs_obsd_symlink}, /* symlink */ | |
225 | {&vop_readdir_desc, afs_obsd_readdir}, /* readdir */ | |
226 | {&vop_readlink_desc, afs_obsd_readlink}, /* readlink */ | |
227 | {&vop_abortop_desc, vop_generic_abortop}, /* abortop */ | |
228 | {&vop_inactive_desc, afs_obsd_inactive}, /* inactive */ | |
229 | {&vop_reclaim_desc, afs_obsd_reclaim}, /* reclaim */ | |
230 | {&vop_lock_desc, afs_obsd_lock}, /* lock */ | |
231 | {&vop_unlock_desc, afs_obsd_unlock}, /* unlock */ | |
232 | {&vop_bmap_desc, afs_obsd_bmap}, /* bmap */ | |
233 | {&vop_strategy_desc, afs_obsd_strategy}, /* strategy */ | |
234 | {&vop_print_desc, afs_obsd_print}, /* print */ | |
235 | {&vop_islocked_desc, afs_obsd_islocked}, /* islocked */ | |
236 | {&vop_pathconf_desc, afs_obsd_pathconf}, /* pathconf */ | |
237 | {&vop_advlock_desc, afs_obsd_advlock}, /* advlock */ | |
238 | {&vop_reallocblks_desc, afs_obsd_reallocblks}, /* reallocblks */ | |
239 | {&vop_bwrite_desc, vop_generic_bwrite}, | |
240 | {NULL, (int (*)__P((void *)))NULL} | |
241 | }; | |
242 | struct vnodeopv_desc afs_vnodeop_opv_desc = | |
243 | { &afs_vnodeop_p, afs_vnodeop_entries }; | |
244 | ||
245 | #endif | |
246 | ||
247 | #define GETNAME() \ | |
248 | struct componentname *cnp = ap->a_cnp; \ | |
249 | char *name; \ | |
250 | BSD_KMALLOC(name, char *, cnp->cn_namelen+1, M_TEMP, M_WAITOK); \ | |
251 | bcopy(cnp->cn_nameptr, name, cnp->cn_namelen); \ | |
252 | name[cnp->cn_namelen] = '\0' | |
253 | ||
254 | #define DROPNAME() BSD_KFREE(name, M_TEMP) | |
255 | ||
256 | #ifdef AFS_OBSD36_ENV | |
257 | #define DROPCNP(cnp) pool_put(&namei_pool, (cnp)->cn_pnbuf) | |
258 | #else | |
259 | #define DROPCNP(cnp) FREE((cnp)->cn_pnbuf, M_NAMEI) | |
260 | #endif | |
261 | ||
262 | int afs_debug; | |
263 | ||
264 | int | |
265 | afs_obsd_lookup(void *v) | |
266 | { | |
267 | struct vop_lookup_args /* { | |
268 | * struct vnodeop_desc * a_desc; | |
269 | * struct vnode *a_dvp; | |
270 | * struct vnode **a_vpp; | |
271 | * struct componentname *a_cnp; | |
272 | * } */ *ap = v; | |
273 | int code; | |
274 | struct vcache *vcp; | |
275 | struct vnode *vp, *dvp; | |
276 | int flags = ap->a_cnp->cn_flags; | |
277 | int lockparent; /* 1 => lockparent flag is set */ | |
278 | int wantparent; /* 1 => wantparent or lockparent flag */ | |
279 | ||
280 | GETNAME(); | |
281 | lockparent = flags & LOCKPARENT; | |
282 | wantparent = flags & (LOCKPARENT | WANTPARENT); | |
283 | #ifdef PDIRUNLOCK | |
284 | cnp->cn_flags &= ~PDIRUNLOCK; | |
285 | #endif | |
286 | ||
287 | if (ap->a_dvp->v_type != VDIR) { | |
288 | *ap->a_vpp = NULL; | |
289 | DROPNAME(); | |
290 | return ENOTDIR; | |
291 | } | |
292 | dvp = ap->a_dvp; | |
293 | if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_flag & VROOT)) | |
294 | printf("nbsd_lookup dvp %p flags %x name %s cnt %d\n", dvp, flags, | |
295 | name, dvp->v_usecount); | |
296 | AFS_GLOCK(); | |
297 | code = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred); | |
298 | AFS_GUNLOCK(); | |
299 | if (code) { | |
300 | if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) | |
301 | && (flags & ISLASTCN) && code == ENOENT) | |
302 | code = EJUSTRETURN; | |
303 | if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) | |
304 | cnp->cn_flags |= SAVENAME; | |
305 | DROPNAME(); | |
306 | *ap->a_vpp = NULL; | |
307 | return (code); | |
308 | } | |
309 | vp = AFSTOV(vcp); /* always get a node if no error */ | |
310 | ||
311 | /* | |
312 | * The parent directory comes in locked. We unlock it on return | |
313 | * unless the caller wants it left locked. | |
314 | * we also always return the vnode locked. | |
315 | */ | |
316 | ||
317 | if (vp == dvp) { | |
318 | /* they're the same; afs_lookup() already ref'ed the leaf. | |
319 | * It came in locked, so we don't need to ref OR lock it */ | |
320 | if (afs_debug & AFSDEB_VNLAYER) | |
321 | printf("ref'ed %p as .\n", dvp); | |
322 | } else { | |
323 | if (!lockparent || !(flags & ISLASTCN)) { | |
324 | VOP_UNLOCK(dvp, 0, curproc); /* done with parent. */ | |
325 | #ifdef PDIRUNLOCK | |
326 | cnp->cn_flags |= PDIRUNLOCK; | |
327 | #endif | |
328 | } | |
329 | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc); /* always return the child locked */ | |
330 | if (afs_debug & AFSDEB_VNLAYER) | |
331 | printf("locked ret %p from lookup\n", vp); | |
332 | } | |
333 | *ap->a_vpp = vp; | |
334 | ||
335 | if (((cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) | |
336 | || (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)))) | |
337 | cnp->cn_flags |= SAVENAME; | |
338 | ||
339 | DROPNAME(); | |
340 | if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_flag & VROOT)) | |
341 | printf("nbsd_lookup done dvp %p cnt %d\n", dvp, dvp->v_usecount); | |
342 | return code; | |
343 | } | |
344 | ||
345 | int | |
346 | afs_obsd_create(void *v) | |
347 | { | |
348 | struct vop_create_args /* { | |
349 | * struct vnode *a_dvp; | |
350 | * struct vnode **a_vpp; | |
351 | * struct componentname *a_cnp; | |
352 | * struct vattr *a_vap; | |
353 | * } */ *ap = v; | |
354 | int code = 0; | |
355 | struct vcache *vcp; | |
356 | struct vnode *dvp = ap->a_dvp; | |
357 | GETNAME(); | |
358 | ||
359 | if (afs_debug & AFSDEB_VNLAYER) | |
360 | printf("nbsd_create dvp %p cnt %d\n", dvp, dvp->v_usecount); | |
361 | ||
362 | /* vnode layer handles excl/nonexcl */ | |
363 | ||
364 | AFS_GLOCK(); | |
365 | code = | |
366 | afs_create(VTOAFS(dvp), name, ap->a_vap, NONEXCL, ap->a_vap->va_mode, | |
367 | &vcp, cnp->cn_cred); | |
368 | AFS_GUNLOCK(); | |
369 | if (code) { | |
370 | VOP_ABORTOP(dvp, cnp); | |
371 | vput(dvp); | |
372 | DROPNAME(); | |
373 | return (code); | |
374 | } | |
375 | ||
376 | if (vcp) { | |
377 | *ap->a_vpp = AFSTOV(vcp); | |
378 | vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY, curproc); | |
379 | } else | |
380 | *ap->a_vpp = 0; | |
381 | ||
382 | if ((cnp->cn_flags & SAVESTART) == 0) | |
383 | DROPCNP(cnp); | |
384 | vput(dvp); | |
385 | DROPNAME(); | |
386 | if (afs_debug & AFSDEB_VNLAYER) | |
387 | printf("nbsd_create done dvp %p cnt %d\n", dvp, dvp->v_usecount); | |
388 | return code; | |
389 | } | |
390 | ||
391 | int | |
392 | afs_obsd_mknod(void *v) | |
393 | { | |
394 | struct vop_mknod_args /* { | |
395 | * struct vnode *a_dvp; | |
396 | * struct vnode **a_vpp; | |
397 | * struct componentname *a_cnp; | |
398 | * struct vattr *a_vap; | |
399 | * } */ *ap = v; | |
400 | DROPCNP(ap->a_cnp); | |
401 | vput(ap->a_dvp); | |
402 | return (ENODEV); | |
403 | } | |
404 | ||
405 | int | |
406 | afs_obsd_open(void *v) | |
407 | { | |
408 | struct vop_open_args /* { | |
409 | * struct vnode *a_vp; | |
410 | * int a_mode; | |
411 | * struct ucred *a_cred; | |
412 | * struct proc *a_p; | |
413 | * } */ *ap = v; | |
414 | int code; | |
415 | struct vcache *vc = VTOAFS(ap->a_vp); | |
416 | ||
417 | AFS_GLOCK(); | |
418 | code = afs_open(&vc, ap->a_mode, ap->a_cred); | |
419 | #ifdef DIAGNOSTIC | |
420 | if (AFSTOV(vc) != ap->a_vp) | |
421 | panic("AFS open changed vnode!"); | |
422 | #endif | |
423 | AFS_GUNLOCK(); | |
424 | return code; | |
425 | } | |
426 | ||
427 | int | |
428 | afs_obsd_close(void *v) | |
429 | { | |
430 | struct vop_close_args /* { | |
431 | * struct vnode *a_vp; | |
432 | * int a_fflag; | |
433 | * struct ucred *a_cred; | |
434 | * struct proc *a_p; | |
435 | * } */ *ap = v; | |
436 | int code; | |
437 | ||
438 | AFS_GLOCK(); | |
439 | code = afs_close(VTOAFS(ap->a_vp), ap->a_fflag, ap->a_cred); | |
440 | AFS_GUNLOCK(); | |
441 | return code; | |
442 | } | |
443 | ||
444 | int | |
445 | afs_obsd_access(void *v) | |
446 | { | |
447 | struct vop_access_args /* { | |
448 | * struct vnode *a_vp; | |
449 | * int a_mode; | |
450 | * struct ucred *a_cred; | |
451 | * struct proc *a_p; | |
452 | * } */ *ap = v; | |
453 | int code; | |
454 | ||
455 | AFS_GLOCK(); | |
456 | code = afs_access(VTOAFS(ap->a_vp), ap->a_mode, ap->a_cred); | |
457 | AFS_GUNLOCK(); | |
458 | return code; | |
459 | } | |
460 | ||
461 | int | |
462 | afs_obsd_getattr(void *v) | |
463 | { | |
464 | struct vop_getattr_args /* { | |
465 | * struct vnode *a_vp; | |
466 | * struct vattr *a_vap; | |
467 | * struct ucred *a_cred; | |
468 | * struct proc *a_p; | |
469 | * } */ *ap = v; | |
470 | int code; | |
471 | ||
472 | AFS_GLOCK(); | |
473 | code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred); | |
474 | AFS_GUNLOCK(); | |
475 | return code; | |
476 | } | |
477 | ||
478 | int | |
479 | afs_obsd_setattr(void *v) | |
480 | { | |
481 | struct vop_setattr_args /* { | |
482 | * struct vnode *a_vp; | |
483 | * struct vattr *a_vap; | |
484 | * struct ucred *a_cred; | |
485 | * struct proc *a_p; | |
486 | * } */ *ap = v; | |
487 | int code; | |
488 | ||
489 | AFS_GLOCK(); | |
490 | code = afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred); | |
491 | AFS_GUNLOCK(); | |
492 | return code; | |
493 | } | |
494 | ||
495 | int | |
496 | afs_obsd_read(void *v) | |
497 | { | |
498 | struct vop_read_args /* { | |
499 | * struct vnode *a_vp; | |
500 | * struct uio *a_uio; | |
501 | * int a_ioflag; | |
502 | * struct ucred *a_cred; | |
503 | * } */ *ap = v; | |
504 | int code; | |
505 | ||
506 | AFS_GLOCK(); | |
507 | code = afs_read(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, 0); | |
508 | AFS_GUNLOCK(); | |
509 | return code; | |
510 | } | |
511 | ||
512 | int | |
513 | afs_obsd_write(void *v) | |
514 | { | |
515 | struct vop_write_args /* { | |
516 | * struct vnode *a_vp; | |
517 | * struct uio *a_uio; | |
518 | * int a_ioflag; | |
519 | * struct ucred *a_cred; | |
520 | * } */ *ap = v; | |
521 | int code; | |
522 | ||
523 | #ifdef UVM | |
524 | (void)uvm_vnp_uncache(ap->a_vp); /* toss stale pages */ | |
525 | #else | |
526 | vnode_pager_uncache(ap->a_vp); | |
527 | #endif | |
528 | AFS_GLOCK(); | |
529 | code = | |
530 | afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred, 0); | |
531 | AFS_GUNLOCK(); | |
532 | return code; | |
533 | } | |
534 | ||
535 | int | |
536 | afs_obsd_ioctl(void *v) | |
537 | { | |
538 | struct vop_ioctl_args /* { | |
539 | * struct vnode *a_vp; | |
540 | * int a_command; | |
541 | * caddr_t a_data; | |
542 | * int a_fflag; | |
543 | * struct ucred *a_cred; | |
544 | * struct proc *a_p; | |
545 | * } */ *ap = v; | |
546 | int code; | |
547 | ||
548 | /* in case we ever get in here... */ | |
549 | ||
550 | AFS_STATCNT(afs_ioctl); | |
551 | AFS_GLOCK(); | |
552 | if (((ap->a_command >> 8) & 0xff) == 'V') | |
553 | /* This is a VICEIOCTL call */ | |
554 | code = | |
555 | HandleIoctl(VTOAFS(ap->a_vp), ap->a_command, | |
556 | (struct afs_ioctl *)ap->a_data); | |
557 | else | |
558 | /* No-op call; just return. */ | |
559 | code = ENOTTY; | |
560 | AFS_GUNLOCK(); | |
561 | return code; | |
562 | } | |
563 | ||
564 | int | |
565 | afs_obsd_select(void *v) | |
566 | { | |
567 | return 1; | |
568 | } | |
569 | ||
570 | int | |
571 | afs_obsd_fsync(void *v) | |
572 | { | |
573 | struct vop_fsync_args /* { | |
574 | * struct vnode *a_vp; | |
575 | * struct ucred *a_cred; | |
576 | * int a_waitfor; | |
577 | * struct proc *a_p; | |
578 | * } */ *ap = v; | |
579 | int wait = ap->a_waitfor == MNT_WAIT; | |
580 | struct vnode *vp = ap->a_vp; | |
581 | int code; | |
582 | ||
583 | AFS_GLOCK(); | |
584 | vflushbuf(vp, wait); | |
585 | code = afs_fsync(VTOAFS(vp), ap->a_cred); | |
586 | AFS_GUNLOCK(); | |
587 | return code; | |
588 | } | |
589 | ||
590 | int | |
591 | afs_obsd_remove(void *v) | |
592 | { | |
593 | struct vop_remove_args /* { | |
594 | * struct vnode *a_dvp; | |
595 | * struct vnode *a_vp; | |
596 | * struct componentname *a_cnp; | |
597 | * } */ *ap = v; | |
598 | int code; | |
599 | struct vnode *vp = ap->a_vp; | |
600 | struct vnode *dvp = ap->a_dvp; | |
601 | ||
602 | GETNAME(); | |
603 | AFS_GLOCK(); | |
604 | code = afs_remove(VTOAFS(dvp), name, cnp->cn_cred); | |
605 | AFS_GUNLOCK(); | |
606 | if (dvp == vp) | |
607 | vrele(vp); | |
608 | else | |
609 | vput(vp); | |
610 | vput(dvp); | |
611 | DROPCNP(cnp); | |
612 | DROPNAME(); | |
613 | return code; | |
614 | } | |
615 | ||
616 | int | |
617 | afs_obsd_link(void *v) | |
618 | { | |
619 | struct vop_link_args /* { | |
620 | * struct vnode *a_vp; | |
621 | * struct vnode *a_tdvp; | |
622 | * struct componentname *a_cnp; | |
623 | * } */ *ap = v; | |
624 | int code; | |
625 | struct vnode *dvp = ap->a_dvp; | |
626 | struct vnode *vp = ap->a_vp; | |
627 | ||
628 | GETNAME(); | |
629 | if (dvp->v_mount != vp->v_mount) { | |
630 | VOP_ABORTOP(vp, cnp); | |
631 | code = EXDEV; | |
632 | goto out; | |
633 | } | |
634 | if (vp->v_type == VDIR) { | |
635 | VOP_ABORTOP(vp, cnp); | |
636 | code = EISDIR; | |
637 | goto out; | |
638 | } | |
639 | if ((code = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc))) { | |
640 | VOP_ABORTOP(dvp, cnp); | |
641 | goto out; | |
642 | } | |
643 | ||
644 | AFS_GLOCK(); | |
645 | code = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred); | |
646 | AFS_GUNLOCK(); | |
647 | DROPCNP(cnp); | |
648 | if (dvp != vp) | |
649 | VOP_UNLOCK(vp, 0, curproc); | |
650 | ||
651 | out: | |
652 | vput(dvp); | |
653 | DROPNAME(); | |
654 | return code; | |
655 | } | |
656 | ||
657 | int | |
658 | afs_obsd_rename(void *v) | |
659 | { | |
660 | struct vop_rename_args /* { | |
661 | * struct vnode *a_fdvp; | |
662 | * struct vnode *a_fvp; | |
663 | * struct componentname *a_fcnp; | |
664 | * struct vnode *a_tdvp; | |
665 | * struct vnode *a_tvp; | |
666 | * struct componentname *a_tcnp; | |
667 | * } */ *ap = v; | |
668 | int code = 0; | |
669 | struct componentname *fcnp = ap->a_fcnp; | |
670 | char *fname; | |
671 | struct componentname *tcnp = ap->a_tcnp; | |
672 | char *tname; | |
673 | struct vnode *tvp = ap->a_tvp; | |
674 | struct vnode *tdvp = ap->a_tdvp; | |
675 | struct vnode *fvp = ap->a_fvp; | |
676 | struct vnode *fdvp = ap->a_fdvp; | |
677 | ||
678 | /* | |
679 | * Check for cross-device rename. | |
680 | */ | |
681 | if ((fvp->v_mount != tdvp->v_mount) | |
682 | || (tvp && (fvp->v_mount != tvp->v_mount))) { | |
683 | code = EXDEV; | |
684 | abortit: | |
685 | VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */ | |
686 | if (tdvp == tvp) | |
687 | vrele(tdvp); | |
688 | else | |
689 | vput(tdvp); | |
690 | if (tvp) | |
691 | vput(tvp); | |
692 | VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */ | |
693 | vrele(fdvp); | |
694 | vrele(fvp); | |
695 | return (code); | |
696 | } | |
697 | /* | |
698 | * if fvp == tvp, we're just removing one name of a pair of | |
699 | * directory entries for the same element. convert call into rename. | |
700 | ( (pinched from NetBSD 1.0's ufs_rename()) | |
701 | */ | |
702 | if (fvp == tvp) { | |
703 | if (fvp->v_type == VDIR) { | |
704 | code = EINVAL; | |
705 | goto abortit; | |
706 | } | |
707 | ||
708 | /* Release destination completely. */ | |
709 | VOP_ABORTOP(tdvp, tcnp); | |
710 | vput(tdvp); | |
711 | vput(tvp); | |
712 | ||
713 | /* Delete source. */ | |
714 | vrele(fdvp); | |
715 | vrele(fvp); | |
716 | fcnp->cn_flags &= ~MODMASK; | |
717 | fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; | |
718 | if ((fcnp->cn_flags & SAVESTART) == 0) | |
719 | panic("afs_rename: lost from startdir"); | |
720 | fcnp->cn_nameiop = DELETE; | |
721 | #if defined(AFS_OBSD49_ENV) | |
722 | (void)vfs_relookup(fdvp, &fvp, fcnp); | |
723 | #else | |
724 | (void)relookup(fdvp, &fvp, fcnp); | |
725 | #endif | |
726 | return (VOP_REMOVE(fdvp, fvp, fcnp)); | |
727 | } | |
728 | ||
729 | if ((code = vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, curproc))) | |
730 | goto abortit; | |
731 | ||
732 | BSD_KMALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK); | |
733 | bcopy(fcnp->cn_nameptr, fname, fcnp->cn_namelen); | |
734 | fname[fcnp->cn_namelen] = '\0'; | |
735 | BSD_KMALLOC(tname, char *, tcnp->cn_namelen + 1, M_TEMP, M_WAITOK); | |
736 | bcopy(tcnp->cn_nameptr, tname, tcnp->cn_namelen); | |
737 | tname[tcnp->cn_namelen] = '\0'; | |
738 | ||
739 | ||
740 | AFS_GLOCK(); | |
741 | /* XXX use "from" or "to" creds? NFS uses "to" creds */ | |
742 | code = | |
743 | afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname, tcnp->cn_cred); | |
744 | AFS_GUNLOCK(); | |
745 | ||
746 | VOP_UNLOCK(fvp, 0, curproc); | |
747 | BSD_KFREE(fname, M_TEMP); | |
748 | BSD_KFREE(tname, M_TEMP); | |
749 | if (code) | |
750 | goto abortit; /* XXX */ | |
751 | if (tdvp == tvp) | |
752 | vrele(tdvp); | |
753 | else | |
754 | vput(tdvp); | |
755 | if (tvp) | |
756 | vput(tvp); | |
757 | vrele(fdvp); | |
758 | vrele(fvp); | |
759 | return code; | |
760 | } | |
761 | ||
762 | int | |
763 | afs_obsd_mkdir(void *v) | |
764 | { | |
765 | struct vop_mkdir_args /* { | |
766 | * struct vnode *a_dvp; | |
767 | * struct vnode **a_vpp; | |
768 | * struct componentname *a_cnp; | |
769 | * struct vattr *a_vap; | |
770 | * } */ *ap = v; | |
771 | struct vnode *dvp = ap->a_dvp; | |
772 | struct vattr *vap = ap->a_vap; | |
773 | int code; | |
774 | struct vcache *vcp; | |
775 | ||
776 | GETNAME(); | |
777 | #ifdef DIAGNOSTIC | |
778 | if ((cnp->cn_flags & HASBUF) == 0) | |
779 | panic("afs_obsd_mkdir: no name"); | |
780 | #endif | |
781 | AFS_GLOCK(); | |
782 | code = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, cnp->cn_cred); | |
783 | AFS_GUNLOCK(); | |
784 | if (code) { | |
785 | VOP_ABORTOP(dvp, cnp); | |
786 | vput(dvp); | |
787 | DROPNAME(); | |
788 | return (code); | |
789 | } | |
790 | if (vcp) { | |
791 | *ap->a_vpp = AFSTOV(vcp); | |
792 | vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY, curproc); | |
793 | } else | |
794 | *ap->a_vpp = 0; | |
795 | DROPCNP(cnp); | |
796 | DROPNAME(); | |
797 | vput(dvp); | |
798 | return code; | |
799 | } | |
800 | ||
801 | int | |
802 | afs_obsd_rmdir(void *v) | |
803 | { | |
804 | struct vop_rmdir_args /* { | |
805 | * struct vnode *a_dvp; | |
806 | * struct vnode *a_vp; | |
807 | * struct componentname *a_cnp; | |
808 | * } */ *ap = v; | |
809 | int code; | |
810 | struct vnode *vp = ap->a_vp; | |
811 | struct vnode *dvp = ap->a_dvp; | |
812 | ||
813 | GETNAME(); | |
814 | if (dvp == vp) { | |
815 | vrele(dvp); | |
816 | vput(vp); | |
817 | DROPCNP(cnp); | |
818 | DROPNAME(); | |
819 | return (EINVAL); | |
820 | } | |
821 | ||
822 | AFS_GLOCK(); | |
823 | code = afs_rmdir(VTOAFS(dvp), name, cnp->cn_cred); | |
824 | AFS_GUNLOCK(); | |
825 | DROPNAME(); | |
826 | vput(dvp); | |
827 | vput(vp); | |
828 | return code; | |
829 | } | |
830 | ||
831 | int | |
832 | afs_obsd_symlink(void *v) | |
833 | { | |
834 | struct vop_symlink_args /* { | |
835 | * struct vnode *a_dvp; | |
836 | * struct vnode **a_vpp; | |
837 | * struct componentname *a_cnp; | |
838 | * struct vattr *a_vap; | |
839 | * char *a_target; | |
840 | * } */ *ap = v; | |
841 | struct vnode *dvp = ap->a_dvp; | |
842 | int code; | |
843 | /* NFS ignores a_vpp; so do we. */ | |
844 | ||
845 | GETNAME(); | |
846 | AFS_GLOCK(); | |
847 | code = | |
848 | afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, NULL, | |
849 | cnp->cn_cred); | |
850 | AFS_GUNLOCK(); | |
851 | DROPCNP(cnp); | |
852 | DROPNAME(); | |
853 | vput(dvp); | |
854 | return code; | |
855 | } | |
856 | ||
857 | int | |
858 | afs_obsd_readdir(void *v) | |
859 | { | |
860 | struct vop_readdir_args /* { | |
861 | * struct vnode *a_vp; | |
862 | * struct uio *a_uio; | |
863 | * struct ucred *a_cred; | |
864 | * int *a_eofflag; | |
865 | * int *a_ncookies; | |
866 | * u_long **a_cookies; | |
867 | * } */ *ap = v; | |
868 | int code; | |
869 | ||
870 | AFS_GLOCK(); | |
871 | #ifdef AFS_HAVE_COOKIES | |
872 | printf("readdir %p cookies %p ncookies %d\n", ap->a_vp, ap->a_cookies, | |
873 | ap->a_ncookies); | |
874 | code = | |
875 | afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, ap->a_eofflag, | |
876 | ap->a_ncookies, ap->a_cookies); | |
877 | #else | |
878 | code = | |
879 | afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, ap->a_eofflag); | |
880 | #endif | |
881 | AFS_GUNLOCK(); | |
882 | return code; | |
883 | } | |
884 | ||
885 | int | |
886 | afs_obsd_readlink(void *v) | |
887 | { | |
888 | struct vop_readlink_args /* { | |
889 | * struct vnode *a_vp; | |
890 | * struct uio *a_uio; | |
891 | * struct ucred *a_cred; | |
892 | * } */ *ap = v; | |
893 | int code; | |
894 | ||
895 | AFS_GLOCK(); | |
896 | code = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred); | |
897 | AFS_GUNLOCK(); | |
898 | return code; | |
899 | } | |
900 | ||
901 | extern int prtactive; | |
902 | ||
903 | int | |
904 | afs_obsd_inactive(void *v) | |
905 | { | |
906 | struct vop_inactive_args /* { | |
907 | * struct vnode *a_vp; | |
908 | * } */ *ap = v; | |
909 | struct vnode *vp = ap->a_vp; | |
910 | struct vcache *vc = VTOAFS(vp); | |
911 | int haveGlock = ISAFS_GLOCK(); | |
912 | ||
913 | AFS_STATCNT(afs_inactive); | |
914 | ||
915 | if (prtactive && vp->v_usecount != 0) | |
916 | vprint("afs_obsd_inactive(): pushing active", vp); | |
917 | ||
918 | if (!haveGlock) | |
919 | AFS_GLOCK(); | |
920 | afs_InactiveVCache(vc, 0); /* decrs ref counts */ | |
921 | if (!haveGlock) | |
922 | AFS_GUNLOCK(); | |
923 | ||
924 | lockinit(&vc->rwlock, PINOD, "vcache", 0, 0); | |
925 | return 0; | |
926 | } | |
927 | ||
928 | int | |
929 | afs_obsd_reclaim(void *v) | |
930 | { | |
931 | struct vop_reclaim_args /* { | |
932 | * struct vnode *a_vp; | |
933 | * } */ *ap = v; | |
934 | int code, slept; | |
935 | struct vnode *vp = ap->a_vp; | |
936 | struct vcache *avc = VTOAFS(vp); | |
937 | int haveGlock = ISAFS_GLOCK(); | |
938 | int haveVlock = CheckLock(&afs_xvcache); | |
939 | ||
940 | #if 0 | |
941 | printf("reclaim usecount %d\n", vp->v_usecount); | |
942 | /* OK, there are no internal vrefCounts, so there shouldn't | |
943 | * be any more refs here. */ | |
944 | vp->v_data = NULL; /* remove from vnode */ | |
945 | avc->v = NULL; /* also drop the ptr to vnode */ | |
946 | return 0; | |
947 | #else | |
948 | if (!haveGlock) | |
949 | AFS_GLOCK(); | |
950 | if (!haveVlock) | |
951 | ObtainWriteLock(&afs_xvcache, 901); | |
952 | /* reclaim the vnode and the in-memory vcache, but keep the on-disk vcache */ | |
953 | code = afs_FlushVCache(avc, &slept); | |
954 | if (!haveVlock) | |
955 | ReleaseWriteLock(&afs_xvcache); | |
956 | if (!haveGlock) | |
957 | AFS_GUNLOCK(); | |
958 | return code; | |
959 | #endif | |
960 | } | |
961 | ||
962 | #ifdef AFS_OBSD42_ENV | |
963 | #define VP_INTERLOCK NULL | |
964 | #else | |
965 | #define VP_INTERLOCK (&vp->v_interlock) | |
966 | #endif | |
967 | ||
968 | int | |
969 | afs_obsd_lock(void *v) | |
970 | { | |
971 | struct vop_lock_args /* { | |
972 | * struct vnode *a_vp; | |
973 | * int a_flags; | |
974 | * sturct proc *a_p; | |
975 | * } */ *ap = v; | |
976 | struct vnode *vp = ap->a_vp; | |
977 | struct vcache *vc = VTOAFS(vp); | |
978 | ||
979 | if (!vc) | |
980 | panic("afs_obsd_lock: null vcache"); | |
981 | return afs_osi_lockmgr(&vc->rwlock, | |
982 | (ap->a_flags & LK_RECURSEFAIL) ? ap->a_flags : ap->a_flags | LK_CANRECURSE, | |
983 | VP_INTERLOCK, ap->a_p); | |
984 | } | |
985 | ||
986 | int | |
987 | afs_obsd_unlock(void *v) | |
988 | { | |
989 | struct vop_unlock_args /* { | |
990 | * struct vnode *a_vp; | |
991 | * int a_flags; | |
992 | * struct proc *a_p; | |
993 | * } */ *ap = v; | |
994 | struct vnode *vp = ap->a_vp; | |
995 | struct vcache *vc = VTOAFS(vp); | |
996 | ||
997 | if (!vc) | |
998 | panic("afs_obsd_unlock: null vcache"); | |
999 | return afs_osi_lockmgr(&vc->rwlock, ap->a_flags | LK_RELEASE, VP_INTERLOCK, ap->a_p); | |
1000 | } | |
1001 | ||
1002 | int | |
1003 | afs_obsd_bmap(void *v) | |
1004 | { | |
1005 | struct vop_bmap_args /* { | |
1006 | * struct vnode *a_vp; | |
1007 | * daddr_t a_bn; | |
1008 | * struct vnode **a_vpp; | |
1009 | * daddr_t *a_bnp; | |
1010 | * int *a_runp; | |
1011 | * } */ *ap = v; | |
1012 | struct vcache *vcp = VTOAFS(ap->a_vp); | |
1013 | ||
1014 | AFS_STATCNT(afs_bmap); | |
1015 | if (ap->a_bnp) | |
1016 | *ap->a_bnp = ap->a_bn * btodb(8192); | |
1017 | if (ap->a_vpp) | |
1018 | *ap->a_vpp = (vcp) ? AFSTOV(vcp) : NULL; | |
1019 | return 0; | |
1020 | } | |
1021 | ||
1022 | int | |
1023 | afs_obsd_strategy(void *v) | |
1024 | { | |
1025 | struct vop_strategy_args /* { | |
1026 | * struct buf *a_bp; | |
1027 | * } */ *ap = v; | |
1028 | struct buf *abp = ap->a_bp; | |
1029 | struct uio tuio; | |
1030 | struct iovec tiovec[1]; | |
1031 | struct vcache *tvc = VTOAFS(abp->b_vp); | |
1032 | struct ucred *credp = osi_curcred(); | |
1033 | long len = abp->b_bcount; | |
1034 | int code; | |
1035 | ||
1036 | memset(&tuio, 0, sizeof(tuio)); | |
1037 | memset(&tiovec, 0, sizeof(tiovec)); | |
1038 | ||
1039 | AFS_STATCNT(afs_strategy); | |
1040 | ||
1041 | tuio.afsio_iov = tiovec; | |
1042 | tuio.afsio_iovcnt = 1; | |
1043 | tuio.afsio_seg = AFS_UIOSYS; | |
1044 | tuio.afsio_resid = len; | |
1045 | tiovec[0].iov_base = abp->b_data; | |
1046 | tiovec[0].iov_len = len; | |
1047 | ||
1048 | AFS_GLOCK(); | |
1049 | if ((abp->b_flags & B_READ) == B_READ) { | |
1050 | code = afs_rdwr(tvc, &tuio, UIO_READ, 0, credp); | |
1051 | if (code == 0 && tuio.afsio_resid > 0) | |
1052 | bzero(abp->b_data + len - tuio.afsio_resid, tuio.afsio_resid); | |
1053 | } else | |
1054 | code = afs_rdwr(tvc, &tuio, UIO_WRITE, 0, credp); | |
1055 | AFS_GUNLOCK(); | |
1056 | ||
1057 | ReleaseWriteLock(&tvc->lock); | |
1058 | AFS_RELE(AFSTOV(tvc)); | |
1059 | return code; | |
1060 | } | |
1061 | ||
1062 | int | |
1063 | afs_obsd_print(void *v) | |
1064 | { | |
1065 | struct vop_print_args /* { | |
1066 | * struct vnode *a_vp; | |
1067 | * } */ *ap = v; | |
1068 | struct vnode *vp = ap->a_vp; | |
1069 | struct vcache *vc = VTOAFS(ap->a_vp); | |
1070 | ||
1071 | printf("tag %d, fid: %d.%x.%x.%x, ", vp->v_tag, vc->f.fid.Cell, | |
1072 | (int)vc->f.fid.Fid.Volume, (int)vc->f.fid.Fid.Vnode, | |
1073 | (int)vc->f.fid.Fid.Unique); | |
1074 | lockmgr_printinfo(&vc->rwlock); | |
1075 | printf("\n"); | |
1076 | return 0; | |
1077 | } | |
1078 | ||
1079 | int | |
1080 | afs_obsd_islocked(void *v) | |
1081 | { | |
1082 | struct vop_islocked_args /* { | |
1083 | * struct vnode *a_vp; | |
1084 | * } */ *ap = v; | |
1085 | return lockstatus(&VTOAFS(ap->a_vp)->rwlock); | |
1086 | } | |
1087 | ||
1088 | /* | |
1089 | * Return POSIX pathconf information applicable to ufs filesystems. | |
1090 | */ | |
1091 | int | |
1092 | afs_obsd_pathconf(void *v) | |
1093 | { | |
1094 | struct vop_pathconf_args /* { | |
1095 | * struct vnode *a_vp; | |
1096 | * int a_name; | |
1097 | * int *a_retval; | |
1098 | * } */ *ap = v; | |
1099 | AFS_STATCNT(afs_cntl); | |
1100 | switch (ap->a_name) { | |
1101 | case _PC_LINK_MAX: | |
1102 | *ap->a_retval = LINK_MAX; | |
1103 | break; | |
1104 | case _PC_NAME_MAX: | |
1105 | *ap->a_retval = NAME_MAX; | |
1106 | break; | |
1107 | case _PC_PATH_MAX: | |
1108 | *ap->a_retval = PATH_MAX; | |
1109 | break; | |
1110 | case _PC_CHOWN_RESTRICTED: | |
1111 | *ap->a_retval = 1; | |
1112 | break; | |
1113 | case _PC_NO_TRUNC: | |
1114 | *ap->a_retval = 1; | |
1115 | break; | |
1116 | case _PC_PIPE_BUF: | |
1117 | return EINVAL; | |
1118 | break; | |
1119 | default: | |
1120 | return EINVAL; | |
1121 | } | |
1122 | return 0; | |
1123 | } | |
1124 | ||
1125 | extern int | |
1126 | afs_lockctl(struct vcache *avc, struct AFS_FLOCK *af, int acmd, | |
1127 | afs_ucred_t *acred, pid_t clid); | |
1128 | ||
1129 | /* | |
1130 | * Advisory record locking support (fcntl() POSIX style) | |
1131 | */ | |
1132 | int | |
1133 | afs_obsd_advlock(void *v) | |
1134 | { | |
1135 | struct vop_advlock_args /* { | |
1136 | * struct vnode *a_vp; | |
1137 | * caddr_t a_id; | |
1138 | * int a_op; | |
1139 | * struct flock *a_fl; | |
1140 | * int a_flags; | |
1141 | * } */ *ap = v; | |
1142 | int code; | |
1143 | ||
1144 | AFS_GLOCK(); | |
1145 | code = | |
1146 | afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, osi_curcred(), | |
1147 | (int)ap->a_id); | |
1148 | AFS_GUNLOCK(); | |
1149 | return code; | |
1150 | } |