]> git.saurik.com Git - apple/xnu.git/blame - bsd/miscfs/synthfs/synthfs_vnops.c
xnu-792.10.96.tar.gz
[apple/xnu.git] / bsd / miscfs / synthfs / synthfs_vnops.c
CommitLineData
1c79356b 1/*
91447636 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
37839358
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
1c79356b 11 *
37839358
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
37839358
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * Copyright (c) 1998-1999 Apple Computer, Inc. All Rights Reserved.
24 *
25 * Modification History:
26 *
27 * 02-Feb-2000 Clark Warner Added copyfile to table
28 * 17-Aug-1999 Pat Dirks New today.
29 */
30
31#include <mach/mach_types.h>
32#include <mach/machine/boolean.h>
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/kernel.h>
36#include <sys/file.h>
37#include <sys/stat.h>
1c79356b 38#include <sys/proc.h>
91447636 39#include <sys/kauth.h>
1c79356b 40#include <sys/conf.h>
91447636
A
41#include <sys/mount_internal.h>
42#include <sys/vnode_internal.h>
1c79356b
A
43#include <sys/malloc.h>
44#include <sys/dirent.h>
45#include <sys/namei.h>
46#include <sys/attr.h>
91447636 47#include <sys/uio_internal.h>
1c79356b
A
48
49#include <sys/vm.h>
50#include <sys/errno.h>
51#include <vfs/vfs_support.h>
52
53#include "synthfs.h"
54
55#define RWSUPPORT 0
56
57#if RWSUPPORT
58#error NOT PORTED FOR UBC
1c79356b
A
59#include <sys/ubc.h>
60#endif
61
91447636
A
62static int synthfs_remove_internal(struct vnode *dvp, struct vnode *vp,
63 struct componentname *cnp, vfs_context_t context);
64
1c79356b
A
65
66#define VOPFUNC int (*)(void *)
67
68/* Global vfs data structures for synthfs. */
69int (**synthfs_vnodeop_p) (void *);
70struct vnodeopv_entry_desc synthfs_vnodeop_entries[] = {
91447636
A
71 {&vnop_default_desc, (VOPFUNC)vn_default_error},
72 {&vnop_strategy_desc, (VOPFUNC)err_strategy}, /* strategy - not supported */
73 {&vnop_bwrite_desc, (VOPFUNC)err_bwrite}, /* bwrite - not supported */
74 {&vnop_lookup_desc, (VOPFUNC)synthfs_cached_lookup}, /* cached lookup */
75 {&vnop_create_desc, (VOPFUNC)synthfs_create}, /* create - DEBUGGER */
76 {&vnop_whiteout_desc, (VOPFUNC)err_whiteout}, /* whiteout - not supported */
77 {&vnop_mknod_desc, (VOPFUNC)err_mknod}, /* mknod - not supported */
78 {&vnop_open_desc, (VOPFUNC)synthfs_open}, /* open - DEBUGGER */
79 {&vnop_close_desc, (VOPFUNC)nop_close}, /* close - NOP */
80 {&vnop_getattr_desc, (VOPFUNC)synthfs_getattr}, /* getattr */
81 {&vnop_setattr_desc, (VOPFUNC)synthfs_setattr}, /* setattr */
82 {&vnop_getattrlist_desc, (VOPFUNC)err_getattrlist}, /* getattrlist - not supported */
83 {&vnop_setattrlist_desc, (VOPFUNC)err_setattrlist}, /* setattrlist - not supported */
84 {&vnop_read_desc, (VOPFUNC)err_read}, /* read - not supported */
85 {&vnop_write_desc, (VOPFUNC)err_write}, /* write - not supported */
86 {&vnop_ioctl_desc, (VOPFUNC)err_ioctl}, /* ioctl - not supported */
87 {&vnop_select_desc, (VOPFUNC)synthfs_select}, /* select */
88 {&vnop_exchange_desc, (VOPFUNC)err_exchange}, /* exchange - not supported */
89 {&vnop_revoke_desc, (VOPFUNC)nop_revoke}, /* revoke - NOP */
90 {&vnop_mmap_desc, (VOPFUNC)synthfs_mmap}, /* mmap - DEBUGGER */
91 {&vnop_fsync_desc, (VOPFUNC)nop_fsync}, /* fsync - NOP */
92 {&vnop_remove_desc, (VOPFUNC)synthfs_remove}, /* remove */
93 {&vnop_link_desc, (VOPFUNC)err_link}, /* link - not supported */
94 {&vnop_rename_desc, (VOPFUNC)synthfs_rename}, /* rename */
95 {&vnop_mkdir_desc, (VOPFUNC)synthfs_mkdir}, /* mkdir */
96 {&vnop_rmdir_desc, (VOPFUNC)synthfs_rmdir}, /* rmdir */
97 {&vnop_symlink_desc, (VOPFUNC)synthfs_symlink}, /* symlink */
98 {&vnop_readdir_desc, (VOPFUNC)synthfs_readdir}, /* readdir */
99 {&vnop_readdirattr_desc, (VOPFUNC)err_readdirattr}, /* readdirattr - not supported */
100 {&vnop_readlink_desc, (VOPFUNC)synthfs_readlink}, /* readlink */
101 {&vnop_inactive_desc, (VOPFUNC)synthfs_inactive}, /* inactive */
102 {&vnop_reclaim_desc, (VOPFUNC)synthfs_reclaim}, /* reclaim */
103 {&vnop_pathconf_desc, (VOPFUNC)synthfs_pathconf}, /* pathconf */
104 {&vnop_advlock_desc, (VOPFUNC)err_advlock}, /* advlock - not supported */
105 {&vnop_allocate_desc, (VOPFUNC)err_allocate}, /* allocate - not supported */
106 {&vnop_pagein_desc, (VOPFUNC)err_pagein}, /* pagein - not supported */
107 {&vnop_pageout_desc, (VOPFUNC)err_pageout}, /* pageout - not supported */
91447636
A
108 {&vnop_searchfs_desc, (VOPFUNC)err_searchfs}, /* searchfs - not supported */
109 {&vnop_copyfile_desc, (VOPFUNC)err_copyfile}, /* copyfile - not supported */
110 { &vnop_blktooff_desc, (VOPFUNC)err_blktooff }, /* blktooff not supported */
111 { &vnop_offtoblk_desc, (VOPFUNC)err_offtoblk }, /* offtoblk not supported */
112 { &vnop_blockmap_desc, (VOPFUNC)err_blockmap }, /* blockmap not supported */
1c79356b
A
113 {(struct vnodeop_desc *) NULL, (int (*) ()) NULL}
114};
115
116/*
117 * Oh what a tangled web we weave. This structure will be used by
118 * bsd/vfs/vfs_conf.c to actually do the initialization of synthfs_vnodeop_p
119 */
120struct vnodeopv_desc synthfs_vnodeop_opv_desc =
121{&synthfs_vnodeop_p, synthfs_vnodeop_entries};
122
123
124
125/*
126 * Create a regular file
127#% create dvp L U U
128#% create vpp - L -
129#
91447636 130 vnop_create {
1c79356b
A
131 IN WILLRELE struct vnode *dvp;
132 OUT struct vnode **vpp;
133 IN struct componentname *cnp;
91447636 134 IN struct vnode_attr *vap;
1c79356b
A
135
136 We are responsible for freeing the namei buffer, it is done in hfs_makenode(), unless there is
137 a previous error.
138
139*/
140
141int
142synthfs_create(ap)
91447636 143struct vnop_create_args /* {
1c79356b
A
144 struct vnode *a_dvp;
145 struct vnode **a_vpp;
146 struct componentname *a_cnp;
91447636
A
147 struct vnode_attr *a_vap;
148 vfs_context_t a_context;
1c79356b
A
149} */ *ap;
150{
151#if DEBUG
152 struct vnode *dvp = ap->a_dvp;
153 char debugmsg[255];
154
155 sprintf(debugmsg, "synthfs_create: attempt to create '%s' in '%s' ?!", ap->a_cnp->cn_nameptr, VTOS(dvp)->s_name);
156 Debugger(debugmsg);
157#endif
158
55e303ae 159 return err_create(ap);
1c79356b
A
160}
161
162
163
164/*
165 * Open called.
166#% open vp L L L
167#
91447636 168 vnop_open {
1c79356b
A
169 IN struct vnode *vp;
170 IN int mode;
91447636 171 IN vfs_context_t a_context;
1c79356b
A
172 */
173
174int
175synthfs_open(ap)
91447636 176struct vnop_open_args /* {
1c79356b
A
177 struct vnode *a_vp;
178 int a_mode;
91447636 179 vfs_context_t a_context;
1c79356b
A
180} */ *ap;
181{
182 struct vnode *vp = ap->a_vp;
183
184 if (vp->v_type == VDIR) {
185 return 0;
186 } else {
187#if DEBUG
188 struct synthfsnode *sp = VTOS(vp);
189 char debugmsg[255];
190
191 sprintf(debugmsg, "synthfs_open: attempt to open '/%s' ?!", sp->s_name);
192 Debugger(debugmsg);
193#endif
194 };
195
196 return 0;
197}
198
199
200
201/*
202 * Mmap a file
203 *
204 * NB Currently unsupported.
205# XXX - not used
206#
91447636 207 vnop_mmap {
1c79356b
A
208 IN struct vnode *vp;
209 IN int fflags;
91447636 210 IN kauth_cred_t cred;
1c79356b
A
211 IN struct proc *p;
212
213 */
214
215/* ARGSUSED */
216
217int
91447636 218synthfs_mmap(__unused struct vnop_mmap_args *ap)
1c79356b 219{
1c79356b
A
220 return EINVAL;
221}
222
223
224
1c79356b
A
225/*
226#% getattr vp = = =
227#
91447636 228 vnop_getattr {
1c79356b 229 IN struct vnode *vp;
91447636
A
230 IN struct vnode_attr *vap;
231 IN vfs_context_t context;
1c79356b
A
232
233*/
234int
235synthfs_getattr(ap)
91447636 236struct vnop_getattr_args /* {
1c79356b 237 struct vnode *a_vp;
91447636
A
238 struct vnode_attr *a_vap;
239 vfs_context_t a_context;
1c79356b
A
240} */ *ap;
241{
91447636
A
242 struct vnode *vp = ap->a_vp;
243 struct vnode_attr *vap = ap->a_vap;
244 struct synthfsnode *sp = VTOS(vp);
245
246 VATTR_RETURN(vap, va_type, vp->v_type);
247 VATTR_RETURN(vap, va_mode, sp->s_mode);
248 VATTR_RETURN(vap, va_nlink, sp->s_linkcount);
249 VATTR_RETURN(vap, va_uid, sp->s_uid);
250 VATTR_RETURN(vap, va_gid, sp->s_gid);
251 VATTR_RETURN(vap, va_fsid, VTOVFS(vp)->mnt_vfsstat.f_fsid.val[0]);
252 VATTR_RETURN(vap, va_fileid, sp->s_nodeid);
1c79356b 253 switch (vp->v_type) {
91447636
A
254 case VDIR:
255 VATTR_RETURN(vap, va_data_size, (sp->s_u.d.d_entrycount + 2) * sizeof(struct dirent));
1c79356b
A
256 break;
257
91447636
A
258 case VREG:
259 VATTR_RETURN(vap, va_data_size, sp->s_u.f.f_size);
1c79356b
A
260 break;
261
91447636
A
262 case VLNK:
263 VATTR_RETURN(vap, va_data_size, sp->s_u.s.s_length);
1c79356b
A
264 break;
265
91447636
A
266 default:
267 VATTR_RETURN(vap, va_data_size, 0);
1c79356b 268 };
91447636
A
269 VATTR_RETURN(vap, va_iosize, 512);
270 vap->va_access_time.tv_sec = sp->s_accesstime.tv_sec;
271 vap->va_access_time.tv_nsec = sp->s_accesstime.tv_usec * 1000;
272 VATTR_SET_SUPPORTED(vap, va_access_time);
273 vap->va_modify_time.tv_sec = sp->s_modificationtime.tv_sec;
274 vap->va_modify_time.tv_nsec = sp->s_modificationtime.tv_usec * 1000;
275 VATTR_SET_SUPPORTED(vap, va_modify_time);
276 vap->va_change_time.tv_sec = sp->s_changetime.tv_sec;
277 vap->va_change_time.tv_nsec = sp->s_changetime.tv_usec * 1000;
278 VATTR_SET_SUPPORTED(vap, va_change_time);
279 VATTR_RETURN(vap, va_gen, sp->s_generation);
280 VATTR_RETURN(vap, va_flags, sp->s_flags);
281 VATTR_RETURN(vap, va_rdev, sp->s_rdev);
282 VATTR_RETURN(vap, va_filerev, 0);
283 VATTR_RETURN(vap, va_acl, NULL);
284
285 return (0);
1c79356b
A
286}
287
288
289
290/*
291 * Change the mode on a file or directory.
292 * vnode vp must be locked on entry.
293 */
91447636 294int synthfs_chmod(struct vnode *vp, int mode, kauth_cred_t cred, struct proc *p)
1c79356b
A
295{
296 struct synthfsnode *sp = VTOS(vp);
297 int result;
298
1c79356b
A
299 sp->s_mode &= ~ALLPERMS;
300 sp->s_mode |= (mode & ALLPERMS);
301 sp->s_nodeflags |= IN_CHANGE;
302#if RWSUPPORT
303 if ((vp->v_flag & VTEXT) && (sp->s_mode & S_ISTXT) == 0) (void) vnode_uncache(vp);
304#endif
305
306 return 0;
307}
308
309
310
311/*
312 * Change the flags on a file or directory.
313 * vnode vp must be locked on entry.
314 */
91447636 315int synthfs_chflags(struct vnode *vp, u_long flags, kauth_cred_t cred, struct proc *p)
1c79356b
A
316{
317 struct synthfsnode *sp = VTOS(vp);
1c79356b 318
91447636 319 sp->s_flags = flags;
1c79356b
A
320 sp->s_nodeflags |= IN_CHANGE;
321
322 return 0;
323}
324
325
326
327/*
328 * Perform chown operation on vnode vp;
329 * vnode vp must be locked on entry.
330 */
91447636 331int synthfs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred, struct proc *p)
1c79356b
A
332{
333 struct synthfsnode *sp = VTOS(vp);
334 uid_t ouid;
335 gid_t ogid;
336 int result = 0;
91447636 337 int is_member;
1c79356b
A
338
339 if (uid == (uid_t)VNOVAL) uid = sp->s_uid;
340 if (gid == (gid_t)VNOVAL) gid = sp->s_gid;
341
1c79356b
A
342 ogid = sp->s_gid;
343 ouid = sp->s_uid;
344
345 sp->s_gid = gid;
346 sp->s_uid = uid;
347
348 if (ouid != uid || ogid != gid) sp->s_nodeflags |= IN_CHANGE;
91447636
A
349 if (ouid != uid && suser(cred, NULL)) sp->s_mode &= ~S_ISUID;
350 if (ogid != gid && suser(cred, NULL)) sp->s_mode &= ~S_ISGID;
1c79356b
A
351
352 return 0;
353}
354
355
356
357/*
358 * Set attribute vnode op. called from several syscalls
359#% setattr vp L L L
360#
91447636 361 vnop_setattr {
1c79356b 362 IN struct vnode *vp;
91447636
A
363 IN struct vnode_attr *vap;
364 IN vfs_context_t context;
1c79356b
A
365 */
366
367int
368synthfs_setattr(ap)
91447636 369struct vnop_setattr_args /* {
1c79356b 370struct vnode *a_vp;
91447636
A
371struct vnode_attr *a_vap;
372vfs_context_t a_context;
1c79356b
A
373} */ *ap;
374{
91447636
A
375 struct vnode *vp = ap->a_vp;
376 struct synthfsnode *sp = VTOS(vp);
377 struct vnode_attr *vap = ap->a_vap;
378 kauth_cred_t cred = vfs_context_ucred(ap->a_context);
379 struct proc *p = vfs_context_proc(ap->a_context);
380 struct timeval atimeval, mtimeval;
381 uid_t nuid;
382 gid_t ngid;
383 int result;
384
385 result = 0;
386
387 if (VATTR_IS_ACTIVE(vap, va_flags)) {
388 if ((result = synthfs_chflags(vp, vap->va_flags, cred, p))) {
389 goto Err_Exit;
390 }
391 }
392 VATTR_SET_SUPPORTED(vap, va_flags);
393
394 nuid = (uid_t)ngid = (gid_t)VNOVAL;
395 if (VATTR_IS_ACTIVE(vap, va_uid))
396 nuid = vap->va_uid;
397 if (VATTR_IS_ACTIVE(vap, va_gid))
398 ngid = vap->va_gid;
399 if (nuid != (uid_t)VNOVAL || ngid != (gid_t)VNOVAL) {
400 if ((result = synthfs_chown(vp, nuid, ngid, cred, p))) {
401 goto Err_Exit;
402 }
403 }
404 VATTR_SET_SUPPORTED(vap, va_uid);
405 VATTR_SET_SUPPORTED(vap, va_gid);
1c79356b 406
91447636 407 if (VATTR_IS_ACTIVE(vap, va_data_size)) {
1c79356b 408#if RWSUPPORT
91447636
A
409 if ((result = vnode_setsize(vp, vap->va_data_size, 0, ap->a_context))) {
410 goto Err_Exit;
411 };
412 VATTR_SET_SUPPORTED(vap, va_data_size);
1c79356b 413#else
91447636
A
414 result = EINVAL;
415 goto Err_Exit;
1c79356b 416#endif
91447636 417 }
1c79356b 418
91447636
A
419 sp = VTOS(vp);
420 if (VATTR_IS_ACTIVE(vap, va_access_time) || VATTR_IS_ACTIVE(vap, va_modify_time)) {
421 if (VATTR_IS_ACTIVE(vap, va_access_time)) {
422 sp->s_nodeflags |= IN_ACCESS;
423 atimeval.tv_sec = vap->va_access_time.tv_sec;
424 atimeval.tv_usec = vap->va_access_time.tv_nsec / 1000;
425 }
426 if (VATTR_IS_ACTIVE(vap, va_modify_time)) {
427 sp->s_nodeflags |= IN_CHANGE | IN_UPDATE;
428 mtimeval.tv_sec = vap->va_modify_time.tv_sec;
429 mtimeval.tv_usec = vap->va_modify_time.tv_nsec / 1000;
430 }
431 if ((result = synthfs_update(vp, &atimeval, &mtimeval, 1))) {
432 goto Err_Exit;
433 }
434 }
435 VATTR_SET_SUPPORTED(vap, va_access_time);
436 VATTR_SET_SUPPORTED(vap, va_modify_time);
1c79356b 437
91447636
A
438 if (VATTR_IS_ACTIVE(vap, va_mode))
439 result = synthfs_chmod(vp, (int)vap->va_mode, cred, p);
440 VATTR_SET_SUPPORTED(vap, va_mode);
1c79356b 441
91447636 442 Err_Exit:
1c79356b 443
91447636 444 DBG_VOP(("synthfs_setattr: returning %d...\n", result));
1c79356b 445
91447636 446 return (result);
1c79356b
A
447}
448
449
450
451/*
452
453#% rename sourcePar_vp U U U
454#% rename source_vp U U U
455#% rename targetPar_vp L U U
456#% rename target_vp X U U
457#
91447636 458 vnop_rename {
1c79356b
A
459 IN WILLRELE struct vnode *sourcePar_vp;
460 IN WILLRELE struct vnode *source_vp;
461 IN struct componentname *source_cnp;
462 IN WILLRELE struct vnode *targetPar_vp;
463 IN WILLRELE struct vnode *target_vp;
464 IN struct componentname *target_cnp;
465
466
467 */
468
469/*
470 * On entry:
471 * source's parent directory is unlocked
472 * source file or directory is unlocked
473 * destination's parent directory is locked
474 * destination file or directory is locked if it exists
475 *
476 * On exit:
477 * all denodes should be released
478 *
479 */
480
481int
482synthfs_rename(ap)
91447636 483struct vnop_rename_args /* {
1c79356b
A
484 struct vnode *a_fdvp;
485 struct vnode *a_fvp;
486 struct componentname *a_fcnp;
487 struct vnode *a_tdvp;
488 struct vnode *a_tvp;
489 struct componentname *a_tcnp;
91447636 490 vfs_context_t a_context;
1c79356b
A
491} */ *ap;
492{
493 struct vnode *target_vp = ap->a_tvp;
494 struct vnode *targetPar_vp = ap->a_tdvp;
495 struct vnode *source_vp = ap->a_fvp;
496 struct vnode *sourcePar_vp = ap->a_fdvp;
497 struct componentname *target_cnp = ap->a_tcnp;
498 struct componentname *source_cnp = ap->a_fcnp;
1c79356b
A
499 struct synthfsnode *target_sp, *targetPar_sp, *source_sp, *sourcePar_sp;
500 u_short doingdirectory = 0, oldparent = 0, newparent = 0;
501 int retval = 0;
502 struct timeval tv;
503
504#if SYNTHFS_DIAGNOSTIC
505 if ((target_cnp->cn_flags & HASBUF) == 0 ||
506 (source_cnp->cn_flags & HASBUF) == 0)
507 panic("synthfs_rename: no name");
508#endif
509
510 DBG_ASSERT((ap->a_fdvp->v_type == VDIR) && (ap->a_tdvp->v_type == VDIR));
511 target_sp = targetPar_sp = source_sp = sourcePar_sp = NULL;
512
1c79356b
A
513
514 sourcePar_sp = VTOS(sourcePar_vp);
515 source_sp = VTOS(source_vp);
516 oldparent = sourcePar_sp->s_nodeid;
1c79356b
A
517
518 /*
519 * Be sure we are not renaming ".", "..", or an alias of ".". This
520 * leads to a crippled directory tree. It's pretty tough to do a
521 * "ls" or "pwd" with the "." directory entry missing, and "cd .."
522 * doesn't work if the ".." entry is missing.
523 */
524 if (source_sp->s_type == SYNTHFS_DIRECTORY) {
525 if ((source_cnp->cn_namelen == 1 && source_cnp->cn_nameptr[0] == '.')
526 || sourcePar_sp == source_sp
527 || (source_cnp->cn_flags & ISDOTDOT)
528 || (source_sp->s_nodeflags & IN_RENAME)) {
1c79356b
A
529 retval = EINVAL;
530 goto abortit;
531 }
532 source_sp->s_nodeflags |= IN_RENAME;
533 doingdirectory = TRUE;
534 }
535
536 /* Transit between abort and bad */
537
538 targetPar_sp = VTOS(targetPar_vp);
539 target_sp = target_vp ? VTOS(target_vp) : NULL;
540 newparent = targetPar_sp->s_nodeid;
541
1c79356b
A
542
543 /*
544 * If the destination exists, then be sure its type (file or dir)
545 * matches that of the source. And, if it is a directory make sure
546 * it is empty. Then delete the destination.
547 */
548 if (target_vp) {
1c79356b 549
1c79356b 550#if RWSUPPORT
91447636
A
551 if (target_vp->v_type == VREG) {
552 (void) vnode_uncache(target_vp);
553 };
1c79356b 554#endif
91447636 555 cache_purge(target_vp);
1c79356b 556
91447636 557 retval = synthfs_remove_internal(targetPar_vp, target_vp, target_cnp, ap->a_context);
1c79356b
A
558
559 target_vp = NULL;
560 target_sp = NULL;
561
562 if (retval) goto bad;
563 };
564
565
1c79356b
A
566 /* remove the existing entry from the namei cache: */
567 if (source_vp->v_type == VREG) cache_purge(source_vp);
568
569 retval = synthfs_move_rename_entry( source_vp, targetPar_vp, target_cnp->cn_nameptr);
570
1c79356b
A
571 if (retval) goto bad;
572
573 source_sp->s_nodeflags &= ~IN_RENAME;
574
575 /*
576 * Timestamp both parent directories.
577 * Note that if this is a rename within the same directory,
578 * (where targetPar_hp == sourcePar_hp)
579 * the code below is still safe and correct.
580 */
581 targetPar_sp->s_nodeflags |= IN_UPDATE;
582 sourcePar_sp->s_nodeflags |= IN_UPDATE;
91447636
A
583
584 microtime(&tv);
1c79356b
A
585 SYNTHFSTIMES(targetPar_sp, &tv, &tv);
586 SYNTHFSTIMES(sourcePar_sp, &tv, &tv);
587
1c79356b
A
588 return (retval);
589
590bad:;
591 if (retval && doingdirectory)
592 source_sp->s_nodeflags &= ~IN_RENAME;
593
91447636 594 return (retval);
1c79356b
A
595
596abortit:;
91447636 597 return (retval);
1c79356b
A
598}
599
600
601
602/*
603 * Mkdir system call
604
605#% mkdir dvp L U U
606#% mkdir vpp - L -
607#
91447636 608 vnop_mkdir {
1c79356b
A
609 IN WILLRELE struct vnode *dvp;
610 OUT struct vnode **vpp;
611 IN struct componentname *cnp;
91447636
A
612 IN struct vnode_attr *vap;
613 IN vfs_context_t context;
1c79356b
A
614
615 We are responsible for freeing the namei buffer, it is done in synthfs_makenode(), unless there is
616 a previous error.
617
618*/
619
620int
621synthfs_mkdir(ap)
91447636 622struct vnop_mkdir_args /* {
1c79356b
A
623 struct vnode *a_dvp;
624 struct vnode **a_vpp;
625 struct componentname *a_cnp;
91447636
A
626 struct vnode_attr *a_vap;
627 vfs_context_t a_context;
1c79356b
A
628} */ *ap;
629{
630 int retval;
631 struct vnode *dvp = ap->a_dvp;
632 struct componentname *cnp = ap->a_cnp;
633 int mode = MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode);
634 struct vnode *vp = NULL;
635
91447636 636 *ap->a_vpp = NULL;
1c79356b 637
91447636
A
638 retval = synthfs_new_directory(VTOVFS(dvp), dvp, cnp->cn_nameptr, VTOSFS(dvp)->synthfs_nextid++, mode, vfs_context_proc(cnp->cn_context), &vp);
639 if (retval) goto Error_Exit;
1c79356b 640
91447636 641 *ap->a_vpp = vp;
1c79356b 642
91447636
A
643 retval = vnode_setattr(vp, ap->a_vap, ap->a_context);
644 if (retval != 0) goto Error_Exit;
1c79356b 645
91447636
A
646 Error_Exit:;
647 if (retval != 0) {
648 if (vp) synthfs_remove_directory(vp);
649 }
1c79356b
A
650
651 return retval;
652}
653
654
655
656/*
657
658#% remove dvp L U U
659#% remove vp L U U
660#
91447636 661 vnop_remove {
1c79356b
A
662 IN WILLRELE struct vnode *dvp;
663 IN WILLRELE struct vnode *vp;
664 IN struct componentname *cnp;
91447636
A
665 IN vfs_context_t context;
666
1c79356b
A
667 */
668
669int
670synthfs_remove(ap)
91447636 671struct vnop_remove_args /* {
1c79356b
A
672 struct vnode *a_dvp;
673 struct vnode *a_vp;
674 struct componentname *a_cnp;
91447636 675 vfs_context_t a_context;
1c79356b
A
676} */ *ap;
677{
91447636
A
678 return synthfs_remove_internal(ap->a_dvp, ap->a_vp, ap->a_cnp, ap->a_context);
679}
680
681static int
682synthfs_remove_internal(struct vnode *dvp, struct vnode *vp,
683 __unused struct componentname *cnp,
684 __unused vfs_context_t context)
685{
1c79356b 686 struct synthfsnode *sp = VTOS(vp);
91447636 687 struct timeval tv;
1c79356b
A
688 int retval = 0;
689
1c79356b
A
690 /* This is sort of silly right now but someday it may make sense... */
691 if (sp->s_nodeflags & IN_MODIFIED) {
91447636
A
692 microtime(&tv);
693 synthfs_update(vp, &tv, &tv, 0);
1c79356b
A
694 };
695
696 /* remove the entry from the namei cache: */
697 cache_purge(vp);
698
699 /* remove entry from tree and reclaim any resources consumed: */
700 switch (sp->s_type) {
701 case SYNTHFS_DIRECTORY:
702 synthfs_remove_directory(vp);
703 break;
704
705
706 case SYNTHFS_SYMLINK:
707 synthfs_remove_symlink(vp);
708 break;
709
710 case SYNTHFS_FILE:
711 /* Fall through to default case */
712
713 default:
714 synthfs_remove_entry(vp);
715 };
716
717out:
718
719 if (! retval)
720 VTOS(dvp)->s_nodeflags |= IN_CHANGE | IN_UPDATE;
721
1c79356b
A
722 return (retval);
723}
724
725
726
727/*
728#% rmdir dvp L U U
729#% rmdir vp L U U
730#
91447636 731 vnop_rmdir {
1c79356b
A
732 IN WILLRELE struct vnode *dvp;
733 IN WILLRELE struct vnode *vp;
734 IN struct componentname *cnp;
91447636 735 IN vfs_context_t context;
1c79356b
A
736
737 */
738
739int
740synthfs_rmdir(ap)
91447636 741 struct vnop_rmdir_args /* {
1c79356b
A
742 struct vnode *a_dvp;
743 struct vnode *a_vp;
744 struct componentname *a_cnp;
91447636 745 vfs_context_t a_context;
1c79356b
A
746} */ *ap;
747{
91447636 748 return synthfs_remove((struct vnop_remove_args *)ap);
1c79356b
A
749}
750
751
752
753/*
754 * synthfs_select - just say OK. Only possible op is readdir
755 *
756 * Locking policy: ignore
757 */
758int
91447636
A
759synthfs_select(__unused
760struct vnop_select_args /* {
1c79356b
A
761 struct vnode *a_vp;
762 int a_which;
763 int a_fflags;
91447636 764 kauth_cred_t a_cred;
0b4e3aa0 765 void *a_wql;
1c79356b 766 struct proc *a_p;
91447636 767} */ *ap)
1c79356b
A
768{
769 DBG_VOP(("synthfs_select called\n"));
770
771 return (1);
772}
773
774/*
775#
776#% symlink dvp L U U
777#% symlink vpp - U -
778#
91447636
A
779# XXX - note that the return vnode has already been vnode_put'ed
780# by the filesystem layer. To use it you must use vnode_get,
1c79356b
A
781# possibly with a further namei.
782#
91447636 783 vnop_symlink {
1c79356b
A
784 IN WILLRELE struct vnode *dvp;
785 OUT WILLRELE struct vnode **vpp;
786 IN struct componentname *cnp;
91447636 787 IN struct vnode_attr *vap;
1c79356b
A
788 IN char *target;
789
790 We are responsible for freeing the namei buffer, it is done in synthfs_makenode(), unless there is
791 a previous error.
792
793
794*/
795
796int
797synthfs_symlink(ap)
91447636 798 struct vnop_symlink_args /* {
1c79356b
A
799 struct vnode *a_dvp;
800 struct vnode **a_vpp;
801 struct componentname *a_cnp;
91447636 802 struct vnode_attr *a_vap;
1c79356b 803 char *a_target;
91447636 804 vfs_context_t a_context;
1c79356b
A
805 } */ *ap;
806{
807 struct vnode *dvp = ap->a_dvp;
808 struct vnode **vpp = ap->a_vpp;
809 struct componentname *cnp = ap->a_cnp;
810 int retval;
811
812 *vpp = NULL;
813
91447636 814 retval = synthfs_new_symlink(VTOVFS(dvp), dvp, cnp->cn_nameptr, VTOSFS(dvp)->synthfs_nextid++, ap->a_target, vfs_context_proc(cnp->cn_context), vpp);
1c79356b
A
815
816 return (retval);
817}
818
819
820
821/*
822#
823#% readlink vp L L L
824#
91447636 825 vnop_readlink {
1c79356b
A
826 IN struct vnode *vp;
827 INOUT struct uio *uio;
91447636 828 IN kauth_cred_t cred;
1c79356b
A
829 */
830
831int
832synthfs_readlink(ap)
91447636 833struct vnop_readlink_args /* {
1c79356b
A
834 struct vnode *a_vp;
835 struct uio *a_uio;
91447636 836 vfs_context_t a_context;
1c79356b
A
837} */ *ap;
838{
839 struct vnode *vp = ap->a_vp;
840 struct synthfsnode *sp = VTOS(vp);
841 struct uio *uio = ap->a_uio;
842 int retval;
843 unsigned long count;
844
845 if (ap->a_uio->uio_offset > sp->s_u.s.s_length) {
846 return 0;
847 };
848
91447636
A
849 // LP64todo - fix this!
850 if (uio->uio_offset + uio_resid(uio) <= sp->s_u.s.s_length) {
851 count = uio_resid(uio);
1c79356b
A
852 } else {
853 count = sp->s_u.s.s_length - uio->uio_offset;
854 };
855 retval = uiomove((void *)((unsigned char *)sp->s_u.s.s_symlinktarget + uio->uio_offset), count, uio);
856 return (retval);
857
858}
859
860
861
862
863
864
865/*
91447636
A
866 * Read directory entries.
867 */
1c79356b
A
868int
869synthfs_readdir(ap)
91447636
A
870struct vnop_readdir_args /* {
871 struct vnode *a_vp;
872 struct uio *a_uio;
873 int a_flags;
874 int *a_eofflag;
875 int *a_numdirent;
876 vfs_context_t a_context;
1c79356b
A
877} */ *ap;
878{
879 struct synthfsnode *sp = VTOS(ap->a_vp);
880 register struct uio *uio = ap->a_uio;
881 off_t diroffset; /* Offset into simulated directory file */
882 struct synthfsnode *entry;
883
91447636
A
884 DBG_VOP(("\tuio_offset = %d, uio_resid = %lld\n", (int) uio->uio_offset, uio_resid(uio)));
885
886 if (ap->a_flags & (VNODE_READDIR_EXTENDED | VNODE_READDIR_REQSEEKOFF))
887 return (EINVAL);
1c79356b
A
888
889 /* We assume it's all one big buffer... */
890 if (uio->uio_iovcnt > 1) {
891 DBG_VOP(("\tuio->uio_iovcnt = %d?\n", uio->uio_iovcnt));
892 return EINVAL;
893 };
1c79356b
A
894
895 diroffset = 0;
896
897 /*
898 * We must synthesize . and ..
899 */
91447636 900 DBG_VOP(("\tstarting ... uio_offset = %d, uio_resid = %lld\n", (int) uio->uio_offset, uio_resid(uio)));
1c79356b
A
901 if (uio->uio_offset == diroffset)
902 {
903 DBG_VOP(("\tAdding .\n"));
904 diroffset += synthfs_adddirentry(sp->s_nodeid, DT_DIR, ".", uio);
91447636 905 DBG_VOP(("\t after adding ., uio_offset = %d, uio_resid = %lld\n", (int) uio->uio_offset, uio_resid(uio)));
1c79356b 906 }
91447636 907 if ((uio_resid(uio) > 0) && (diroffset > uio->uio_offset)) {
1c79356b
A
908 /* Oops - we skipped over a partial entry: at best, diroffset should've just matched uio->uio_offset */
909 return EINVAL;
910 };
911
912 if (uio->uio_offset == diroffset)
913 {
914 DBG_VOP(("\tAdding ..\n"));
915 if (sp->s_parent != NULL) {
916 diroffset += synthfs_adddirentry(sp->s_parent->s_nodeid, DT_DIR, "..", uio);
917 } else {
918 diroffset += synthfs_adddirentry(sp->s_nodeid, DT_DIR, "..", uio);
919 }
91447636 920 DBG_VOP(("\t after adding .., uio_offset = %d, uio_resid = %lld\n", (int) uio->uio_offset, uio_resid(uio)));
1c79356b 921 }
91447636 922 if ((uio_resid(uio) > 0) && (diroffset > uio->uio_offset)) {
1c79356b
A
923 /* Oops - we skipped over a partial entry: at best, diroffset should've just matched uio->uio_offset */
924 return EINVAL;
925 };
926
927 /* OK, so much for the fakes. Now for the "real thing": */
928 TAILQ_FOREACH(entry, &sp->s_u.d.d_subnodes, s_sibling) {
929 if (diroffset == uio->uio_offset) {
930 /* Return this entry */
931 diroffset += synthfs_adddirentry(entry->s_nodeid, VTTOIF(STOV(entry)->v_type), entry->s_name, uio);
932 };
91447636 933 if ((uio_resid(uio) > 0) && (diroffset > uio->uio_offset)) {
1c79356b
A
934 /* Oops - we skipped over a partial entry: at best, diroffset should've just matched uio->uio_offset */
935 return EINVAL;
936 };
937 };
938
939 if (ap->a_eofflag)
940 *ap->a_eofflag = (entry == NULL); /* If we ran all the way through the list, there is no more */
941
942 return 0;
943}
944
945
946
947/*
948
949#% lookup dvp L ? ?
950#% lookup vpp - L -
951
952 */
953
954int
955synthfs_cached_lookup(ap)
91447636 956 struct vnop_lookup_args /* {
1c79356b
A
957 struct vnode *a_dvp;
958 struct vnode **a_vpp;
959 struct componentname *a_cnp;
960 } */ *ap;
961{
962 struct vnode *dp = ap->a_dvp;
963 struct componentname *cnp = ap->a_cnp;
964 u_long nameiop = cnp->cn_nameiop;
965 u_long flags = cnp->cn_flags;
1c79356b
A
966 struct vnode **vpp = ap->a_vpp;
967 int result = 0;
968
969 DBG_VOP(("synthfs_cached_lookup called, name = %s, namelen = %ld\n", ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen));
91447636 970#if DEBUG
1c79356b 971 if (flags & ISLASTCN) DBG_VOP(("\tISLASTCN is set\n"));
91447636 972#endif
1c79356b
A
973
974 *vpp = NULL;
975
1c79356b
A
976 /*
977 * Look up an entry in the namei cache
978 */
979
980 result = cache_lookup(dp, vpp, cnp);
981 if (result == 0) {
982 /* There was no entry in the cache for this parent vnode/name pair:
983 do the full-blown pathname lookup
984 */
985 return synthfs_lookup(ap);
986 };
987 if (result == ENOENT) return result;
988
989 /* An entry matching the parent vnode/name was found in the cache: */
990
91447636 991 return (0);
1c79356b
A
992
993Err_Exit:;
91447636 994 return result;
1c79356b
A
995}
996
997
998
999int
1000synthfs_lookup(ap)
91447636 1001 struct vnop_lookup_args /* {
1c79356b
A
1002 struct vnode *a_dvp;
1003 struct vnode **a_vpp;
1004 struct componentname *a_cnp;
91447636 1005 vfs_context_t a_context;
1c79356b
A
1006 } */ *ap;
1007{
1008 struct vnode *dp = ap->a_dvp;
1009 struct synthfsnode *dsp = VTOS(dp);
1010 struct componentname *cnp = ap->a_cnp;
1011 u_long nameiop = cnp->cn_nameiop;
1012// char *nameptr = cnp->cn_nameptr;
1013 u_long flags = cnp->cn_flags;
1014 long namelen = cnp->cn_namelen;
91447636
A
1015// struct proc *p = cnp->cn_proc;
1016 vfs_context_t ctx = cnp->cn_context;
1017 kauth_cred_t cred = vfs_context_ucred(ctx);
1c79356b
A
1018 struct synthfsnode *entry;
1019 struct vnode *target_vp = NULL;
1020 int result = 0;
1021 boolean_t found = FALSE;
1022 boolean_t isDot = FALSE;
1023 boolean_t isDotDot = FALSE;
1024 struct vnode *starting_parent = dp;
1025
1026 DBG_VOP(("synthfs_lookup called, name = %s, namelen = %ld\n", ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen));
91447636 1027#if DEBUG
1c79356b
A
1028 if (flags & LOCKPARENT) DBG_VOP(("\tLOCKPARENT is set\n"));
1029 if (flags & ISLASTCN) DBG_VOP(("\tISLASTCN is set\n"));
91447636 1030#endif
1c79356b
A
1031
1032 *ap->a_vpp = NULL;
1033
1c79356b
A
1034 /* first check for "." and ".." */
1035 if (cnp->cn_nameptr[0] == '.') {
1036 if (namelen == 1) {
1037 /*
1038 "." requested
1039 */
1040 isDot = TRUE;
1041 found = TRUE;
1042
1043 target_vp = dp;
91447636 1044 vnode_get(target_vp);
1c79356b
A
1045
1046 result = 0;
1047
1048 goto Std_Exit;
1049 } else if ((namelen == 2) && (cnp->cn_nameptr[1] == '.')) {
1050 /*
1051 ".." requested
1052 */
1053 isDotDot = TRUE;
1054 found = TRUE;
1055
1056 if ((dsp->s_parent != NULL) && (dsp->s_parent != VTOS(dp))) {
1057 target_vp = STOV(dsp->s_parent);
1058 /*
1059 * Special case for ".." to prevent deadlock:
1060 * always release the parent vnode BEFORE trying to acquire
1061 * ITS parent. This avoids deadlocking with another lookup
91447636 1062 * starting from the target_vp trying to vnode_get() this directory.
1c79356b 1063 */
91447636
A
1064 result = vnode_get(target_vp);
1065
1c79356b
A
1066 } else {
1067 target_vp = dp;
1068 /* dp is alread locked and ref'ed */
1069 result = 0;
1070 }
1071
1072 goto Std_Exit;
1073 }
1074 }
1075
1076 /* finally, just look for entries by name (making sure the entry's length
1077 matches the cnp's namelen... */
1078 TAILQ_FOREACH(entry, &dsp->s_u.d.d_subnodes, s_sibling) {
1079 if ((bcmp(cnp->cn_nameptr, entry->s_name, (unsigned)namelen) == 0) &&
1080 (*(entry->s_name + namelen) == (char)0)) {
1081 found = TRUE;
1082 target_vp = STOV(entry);
91447636 1083 result = vnode_getwithref(target_vp); /* refcount is always > 0 for any vnode in this list... */
1c79356b 1084 if (result != 0) {
1c79356b
A
1085 goto Err_Exit;
1086 };
1087
1088 /* The specified entry was found and successfully acquired: */
1089 goto Std_Exit;
1090 };
1091 };
1092
1093 found = FALSE;
1094
1095Std_Exit:;
1096 if (found) {
1097 if ((nameiop == DELETE) && (flags & ISLASTCN)) {
1c79356b
A
1098
1099 /*
1100 * If the parent directory is "sticky" then the user must own
1101 * the directory, or the file in it, in order to be allowed to
1102 * delete it (unless the user is root). This implements
1103 * append-only directories
1104 */
1105 if ((dsp->s_mode & S_ISVTX) &&
91447636
A
1106 suser(cred, NULL) &&
1107 (kauth_cred_getuid(cred) != dsp->s_uid) &&
1c79356b
A
1108 (target_vp != NULL) &&
1109 (target_vp->v_type != VLNK) &&
91447636
A
1110 (VTOS(target_vp)->s_uid != kauth_cred_getuid(cred))) {
1111 vnode_put(target_vp);
1c79356b
A
1112 result = EPERM;
1113 goto Err_Exit;
1114 };
1115 };
1116
1117 if ((nameiop == RENAME) && (flags & WANTPARENT) && (flags * ISLASTCN)) {
1c79356b
A
1118
1119 if (isDot) {
91447636 1120 vnode_put(target_vp);
1c79356b
A
1121 result = EISDIR;
1122 goto Err_Exit;
1123 };
1124 };
1125 } else {
1126 /* The specified entry wasn't found: */
1127 result = ENOENT;
1128
1129 if ((flags & ISLASTCN) &&
1130 ((nameiop == CREATE) ||
1131 (nameiop == RENAME) ||
1132 ((nameiop == DELETE) && (flags & DOWHITEOUT) && (flags & ISWHITEOUT)))) {
91447636 1133 /* create a new entry */
1c79356b
A
1134 result = EJUSTRETURN;
1135 }
1136 };
1137
1c79356b
A
1138 *ap->a_vpp = target_vp;
1139
1140Err_Exit:;
1141 DBG_VOP(("synthfs_lookup: result = %d.\n", result));
1142 if (found) {
1143 if (target_vp) {
91447636 1144 DBG_VOP(("synthfs_lookup: target_vp = 0x%08X \n", (u_long)target_vp));
1c79356b
A
1145 } else {
1146 DBG_VOP(("synthfs_lookup: found = true but target_vp = NULL?\n"));
1147 };
1148 } else {
1149 DBG_VOP(("synthf_lookup: target not found.\n"));
1150 };
91447636 1151 DBG_VOP(("synthfs_lookup: dp = %08X; starting_parent = 0x%08X .\n", (u_long)dp, (u_long)starting_parent));
1c79356b
A
1152
1153 return result;
1154}
1155
1156
1157
1158/*
1159
1160#% pathconf vp L L L
1161#
91447636 1162 vnop_pathconf {
1c79356b
A
1163 IN struct vnode *vp;
1164 IN int name;
1165 OUT register_t *retval;
1166*/
1167int
1168synthfs_pathconf(ap)
91447636 1169struct vnop_pathconf_args /* {
1c79356b
A
1170 struct vnode *a_vp;
1171 int a_name;
1172 int *a_retval;
91447636 1173 vfs_context_t a_context;
1c79356b
A
1174} */ *ap;
1175{
1176 DBG_VOP(("synthfs_pathconf called\n"));
1177
1178 switch (ap->a_name)
1179 {
1180 case _PC_LINK_MAX:
1181 *ap->a_retval = LINK_MAX;
1182 return (0);
1183 case _PC_NAME_MAX:
1184 *ap->a_retval = NAME_MAX;
1185 return (0);
1186 case _PC_PATH_MAX:
1187 *ap->a_retval = PATH_MAX;
1188 return (0);
1189 case _PC_PIPE_BUF:
1190 *ap->a_retval = PIPE_BUF;
1191 return (0);
1192 case _PC_CHOWN_RESTRICTED:
1193 *ap->a_retval = 1;
1194 return (0);
1195 case _PC_NO_TRUNC:
1196 *ap->a_retval = 1;
1197 return (0);
1198 default:
1199 return (EINVAL);
1200 }
1201 /* NOTREACHED */
1202}
1203
1204
1205/*
1206 * Update the access, modified, and node change times as specified by the
1207 * IACCESS, IUPDATE, and ICHANGE flags respectively. The IMODIFIED flag is
1208 * used to specify that the node needs to be updated but that the times have
1209 * already been set. The access and modified times are taken from the second
1210 * and third parameters; the node change time is always taken from the current
1211 * time. If waitfor is set, then wait for the disk write of the node to
1212 * complete.
1213 */
1c79356b
A
1214
1215int
91447636 1216synthfs_update(struct vnode *vp, struct timeval *access, struct timeval *modify, __unused int waitfor)
1c79356b 1217{
1c79356b 1218 struct synthfsnode *sp = VTOS(vp);
91447636 1219 struct timeval tv;
1c79356b
A
1220
1221 DBG_ASSERT(sp != NULL);
1c79356b
A
1222
1223 if (((sp->s_nodeflags & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) != 0) &&
91447636
A
1224 !(VTOVFS(vp)->mnt_flag & MNT_RDONLY)) {
1225 if (sp->s_nodeflags & IN_ACCESS) sp->s_accesstime = *access;
1226 if (sp->s_nodeflags & IN_UPDATE) sp->s_modificationtime = *modify;
1227 if (sp->s_nodeflags & IN_CHANGE) {
1228
1229 microtime(&tv);
1230 sp->s_changetime = tv;
1231 }
1c79356b
A
1232 };
1233
1234 /* After the updates are finished, clear the flags */
1235 sp->s_nodeflags &= ~(IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE);
1236
1c79356b
A
1237 return 0;
1238}
1239
1240
1241
1242/*******************************************************************************************
1243
1244 Utility/housekeeping vnode operations:
1245
1246 ******************************************************************************************/
1247
1248
1c79356b
A
1249/*
1250#
1251#% inactive vp L U U
1252#
91447636 1253 vnop_inactive {
1c79356b
A
1254 IN struct vnode *vp;
1255 IN struct proc *p;
1256
1257*/
1258
1259int
1260synthfs_inactive(ap)
91447636 1261struct vnop_inactive_args /* {
1c79356b 1262 struct vnode *a_vp;
91447636 1263 vfs_context_t a_context;
1c79356b
A
1264} */ *ap;
1265{
1266 struct vnode *vp = ap->a_vp;
1c79356b
A
1267 struct synthfsnode *sp = VTOS(vp);
1268 struct timeval tv;
1269
91447636 1270#if DEBUG
1c79356b
A
1271 if (vp->v_usecount != 0)
1272 DBG_VOP(("synthfs_inactive: bad usecount = %d\n", vp->v_usecount ));
91447636 1273#endif
1c79356b
A
1274
1275 /*
1276 * Ignore nodes related to stale file handles.
1277 */
1278 if (vp->v_type == VNON)
1279 goto out;
1280
1281 /* This is sort of silly but might make sense in the future: */
1282 if (sp->s_nodeflags & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) {
91447636
A
1283 microtime(&tv);
1284 synthfs_update(vp, &tv, &tv, 0);
1c79356b
A
1285 }
1286
1287out:
1c79356b
A
1288 /*
1289 * If we are done with the inode, reclaim it
1290 * so that it can be reused immediately.
1291 */
1292 if (vp->v_type == VNON) {
91447636 1293 vnode_recycle(vp);
1c79356b
A
1294 };
1295
1296 return 0;
1297}
1298
1299
1300
1301/*
1302 * synthfs_reclaim - Reclaim a vnode so that it can be used for other purposes.
1303 *
1304 * Locking policy: ignored
1305 */
1306int
1307synthfs_reclaim(ap)
91447636 1308 struct vnop_reclaim_args /* { struct vnode *a_vp; struct proc *a_p; } */ *ap;
1c79356b
A
1309{
1310 struct vnode *vp = ap->a_vp;
1311 struct synthfsnode *sp = VTOS(vp);
1312 void *name = sp->s_name;
1313
1314 sp->s_name = NULL;
1315 FREE(name, M_TEMP);
1316
1317 vp->v_data = NULL;
1318 FREE((void *)sp, M_SYNTHFS);
1319
1320 return (0);
1321}