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