ufs_vnops.c revision 92462
1/*
2 * Copyright (c) 1982, 1986, 1989, 1993, 1995
3 *	The Regents of the University of California.  All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by the University of
21 *	California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 *	@(#)ufs_vnops.c	8.27 (Berkeley) 5/27/95
39 * $FreeBSD: head/sys/ufs/ufs/ufs_vnops.c 92462 2002-03-17 01:25:47Z mckusick $
40 */
41
42#include "opt_quota.h"
43#include "opt_suiddir.h"
44#include "opt_ufs.h"
45
46#include <sys/param.h>
47#include <sys/systm.h>
48#include <sys/namei.h>
49#include <sys/kernel.h>
50#include <sys/fcntl.h>
51#include <sys/stat.h>
52#include <sys/bio.h>
53#include <sys/buf.h>
54#include <sys/mount.h>
55#include <sys/unistd.h>
56#include <sys/malloc.h>
57#include <sys/vnode.h>
58#include <sys/dirent.h>
59#include <sys/lockf.h>
60#include <sys/event.h>
61#include <sys/conf.h>
62#include <sys/acl.h>
63
64#include <machine/mutex.h>
65
66#include <sys/file.h>		/* XXX */
67
68#include <vm/vm.h>
69#include <vm/vm_extern.h>
70
71#include <fs/fifofs/fifo.h>
72
73#include <ufs/ufs/acl.h>
74#include <ufs/ufs/extattr.h>
75#include <ufs/ufs/quota.h>
76#include <ufs/ufs/inode.h>
77#include <ufs/ufs/dir.h>
78#include <ufs/ufs/ufsmount.h>
79#include <ufs/ufs/ufs_extern.h>
80#ifdef UFS_DIRHASH
81#include <ufs/ufs/dirhash.h>
82#endif
83
84static int ufs_access __P((struct vop_access_args *));
85static int ufs_advlock __P((struct vop_advlock_args *));
86static int ufs_chmod __P((struct vnode *, int, struct ucred *, struct thread *));
87static int ufs_chown __P((struct vnode *, uid_t, gid_t, struct ucred *, struct thread *));
88static int ufs_close __P((struct vop_close_args *));
89static int ufs_create __P((struct vop_create_args *));
90static int ufs_getattr __P((struct vop_getattr_args *));
91static int ufs_link __P((struct vop_link_args *));
92static int ufs_makeinode __P((int mode, struct vnode *, struct vnode **, struct componentname *));
93static int ufs_missingop __P((struct vop_generic_args *ap));
94static int ufs_mkdir __P((struct vop_mkdir_args *));
95static int ufs_mknod __P((struct vop_mknod_args *));
96static int ufs_open __P((struct vop_open_args *));
97static int ufs_pathconf __P((struct vop_pathconf_args *));
98static int ufs_print __P((struct vop_print_args *));
99static int ufs_readlink __P((struct vop_readlink_args *));
100static int ufs_remove __P((struct vop_remove_args *));
101static int ufs_rename __P((struct vop_rename_args *));
102static int ufs_rmdir __P((struct vop_rmdir_args *));
103static int ufs_setattr __P((struct vop_setattr_args *));
104static int ufs_strategy __P((struct vop_strategy_args *));
105static int ufs_symlink __P((struct vop_symlink_args *));
106static int ufs_whiteout __P((struct vop_whiteout_args *));
107static int ufsfifo_close __P((struct vop_close_args *));
108static int ufsfifo_kqfilter __P((struct vop_kqfilter_args *));
109static int ufsfifo_read __P((struct vop_read_args *));
110static int ufsfifo_write __P((struct vop_write_args *));
111static int ufsspec_close __P((struct vop_close_args *));
112static int ufsspec_read __P((struct vop_read_args *));
113static int ufsspec_write __P((struct vop_write_args *));
114static int filt_ufsread __P((struct knote *kn, long hint));
115static int filt_ufswrite __P((struct knote *kn, long hint));
116static int filt_ufsvnode __P((struct knote *kn, long hint));
117static void filt_ufsdetach __P((struct knote *kn));
118static int ufs_kqfilter __P((struct vop_kqfilter_args *ap));
119
120union _qcvt {
121	int64_t qcvt;
122	int32_t val[2];
123};
124#define SETHIGH(q, h) { \
125	union _qcvt tmp; \
126	tmp.qcvt = (q); \
127	tmp.val[_QUAD_HIGHWORD] = (h); \
128	(q) = tmp.qcvt; \
129}
130#define SETLOW(q, l) { \
131	union _qcvt tmp; \
132	tmp.qcvt = (q); \
133	tmp.val[_QUAD_LOWWORD] = (l); \
134	(q) = tmp.qcvt; \
135}
136
137/*
138 * A virgin directory (no blushing please).
139 */
140static struct dirtemplate mastertemplate = {
141	0, 12, DT_DIR, 1, ".",
142	0, DIRBLKSIZ - 12, DT_DIR, 2, ".."
143};
144static struct odirtemplate omastertemplate = {
145	0, 12, 1, ".",
146	0, DIRBLKSIZ - 12, 2, ".."
147};
148
149void
150ufs_itimes(vp)
151	struct vnode *vp;
152{
153	struct inode *ip;
154	struct timespec ts;
155
156	ip = VTOI(vp);
157	if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0)
158		return;
159	if ((vp->v_type == VBLK || vp->v_type == VCHR) && !DOINGSOFTDEP(vp))
160		ip->i_flag |= IN_LAZYMOD;
161	else
162		ip->i_flag |= IN_MODIFIED;
163	if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
164		vfs_timestamp(&ts);
165		if (ip->i_flag & IN_ACCESS) {
166			ip->i_atime = ts.tv_sec;
167			ip->i_atimensec = ts.tv_nsec;
168		}
169		if (ip->i_flag & IN_UPDATE) {
170			ip->i_mtime = ts.tv_sec;
171			ip->i_mtimensec = ts.tv_nsec;
172			ip->i_modrev++;
173		}
174		if (ip->i_flag & IN_CHANGE) {
175			ip->i_ctime = ts.tv_sec;
176			ip->i_ctimensec = ts.tv_nsec;
177		}
178	}
179	ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE);
180}
181
182/*
183 * Create a regular file
184 */
185int
186ufs_create(ap)
187	struct vop_create_args /* {
188		struct vnode *a_dvp;
189		struct vnode **a_vpp;
190		struct componentname *a_cnp;
191		struct vattr *a_vap;
192	} */ *ap;
193{
194	int error;
195
196	error =
197	    ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
198	    ap->a_dvp, ap->a_vpp, ap->a_cnp);
199	if (error)
200		return (error);
201	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
202	return (0);
203}
204
205/*
206 * Mknod vnode call
207 */
208/* ARGSUSED */
209int
210ufs_mknod(ap)
211	struct vop_mknod_args /* {
212		struct vnode *a_dvp;
213		struct vnode **a_vpp;
214		struct componentname *a_cnp;
215		struct vattr *a_vap;
216	} */ *ap;
217{
218	struct vattr *vap = ap->a_vap;
219	struct vnode **vpp = ap->a_vpp;
220	struct inode *ip;
221	ino_t ino;
222	int error;
223
224	error = ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
225	    ap->a_dvp, vpp, ap->a_cnp);
226	if (error)
227		return (error);
228	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
229	ip = VTOI(*vpp);
230	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
231	if (vap->va_rdev != VNOVAL) {
232		/*
233		 * Want to be able to use this to make badblock
234		 * inodes, so don't truncate the dev number.
235		 */
236		ip->i_rdev = vap->va_rdev;
237	}
238	/*
239	 * Remove inode, then reload it through VFS_VGET so it is
240	 * checked to see if it is an alias of an existing entry in
241	 * the inode cache.
242	 */
243	vput(*vpp);
244	(*vpp)->v_type = VNON;
245	ino = ip->i_number;	/* Save this before vgone() invalidates ip. */
246	vgone(*vpp);
247	error = VFS_VGET(ap->a_dvp->v_mount, ino, LK_EXCLUSIVE, vpp);
248	if (error) {
249		*vpp = NULL;
250		return (error);
251	}
252	return (0);
253}
254
255/*
256 * Open called.
257 *
258 * Nothing to do.
259 */
260/* ARGSUSED */
261int
262ufs_open(ap)
263	struct vop_open_args /* {
264		struct vnode *a_vp;
265		int  a_mode;
266		struct ucred *a_cred;
267		struct thread *a_td;
268	} */ *ap;
269{
270
271	/*
272	 * Files marked append-only must be opened for appending.
273	 */
274	if ((VTOI(ap->a_vp)->i_flags & APPEND) &&
275	    (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
276		return (EPERM);
277	return (0);
278}
279
280/*
281 * Close called.
282 *
283 * Update the times on the inode.
284 */
285/* ARGSUSED */
286int
287ufs_close(ap)
288	struct vop_close_args /* {
289		struct vnode *a_vp;
290		int  a_fflag;
291		struct ucred *a_cred;
292		struct thread *a_td;
293	} */ *ap;
294{
295	struct vnode *vp = ap->a_vp;
296	struct mount *mp;
297
298	mtx_lock(&vp->v_interlock);
299	if (vp->v_usecount > 1) {
300		ufs_itimes(vp);
301		mtx_unlock(&vp->v_interlock);
302	} else {
303		mtx_unlock(&vp->v_interlock);
304		/*
305		 * If we are closing the last reference to an unlinked
306		 * file, then it will be freed by the inactive routine.
307		 * Because the freeing causes a the filesystem to be
308		 * modified, it must be held up during periods when the
309		 * filesystem is suspended.
310		 *
311		 * XXX - EAGAIN is returned to prevent vn_close from
312		 * repeating the vrele operation.
313		 */
314		if (vp->v_type == VREG &&
315		    (VFSTOUFS(vp->v_mount)->um_i_effnlink_valid ?
316		    VTOI(vp)->i_effnlink : VTOI(vp)->i_nlink) == 0) {
317			(void) vn_start_write(vp, &mp, V_WAIT);
318			vrele(vp);
319			vn_finished_write(mp);
320			return (EAGAIN);
321		}
322	}
323	return (0);
324}
325
326int
327ufs_access(ap)
328	struct vop_access_args /* {
329		struct vnode *a_vp;
330		int  a_mode;
331		struct ucred *a_cred;
332		struct thread *a_td;
333	} */ *ap;
334{
335	struct vnode *vp = ap->a_vp;
336	struct inode *ip = VTOI(vp);
337	mode_t mode = ap->a_mode;
338	int error;
339#ifdef UFS_ACL
340	struct acl *acl;
341	int len;
342#endif
343
344	/*
345	 * Disallow write attempts on read-only file systems;
346	 * unless the file is a socket, fifo, or a block or
347	 * character device resident on the file system.
348	 */
349	if (mode & VWRITE) {
350		switch (vp->v_type) {
351		case VDIR:
352		case VLNK:
353		case VREG:
354			if (vp->v_mount->mnt_flag & MNT_RDONLY)
355				return (EROFS);
356#ifdef QUOTA
357			if ((error = getinoquota(ip)) != 0)
358				return (error);
359#endif
360			break;
361		default:
362			break;
363		}
364	}
365
366	/* If immutable bit set, nobody gets to write it. */
367	if ((mode & VWRITE) && (ip->i_flags & (IMMUTABLE | SF_SNAPSHOT)))
368		return (EPERM);
369
370#ifdef UFS_ACL
371	MALLOC(acl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK);
372	len = sizeof(*acl);
373	error = VOP_GETACL(vp, ACL_TYPE_ACCESS, acl, ap->a_cred, ap->a_td);
374	switch (error) {
375	case EOPNOTSUPP:
376		error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid,
377		    ap->a_mode, ap->a_cred, NULL);
378		break;
379	case 0:
380		error = vaccess_acl_posix1e(vp->v_type, ip->i_uid, ip->i_gid,
381		    acl, ap->a_mode, ap->a_cred, NULL);
382		break;
383	default:
384		printf("ufs_access(): Error retrieving ACL on object (%d).\n",
385		    error);
386		/*
387		 * XXX: Fall back until debugged.  Should eventually
388		 * possibly log an error, and return EPERM for safety.
389		 */
390		error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid,
391		    ap->a_mode, ap->a_cred, NULL);
392	}
393	FREE(acl, M_ACL);
394#else
395	error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid,
396	    ap->a_mode, ap->a_cred, NULL);
397#endif
398	return (error);
399}
400
401/* ARGSUSED */
402int
403ufs_getattr(ap)
404	struct vop_getattr_args /* {
405		struct vnode *a_vp;
406		struct vattr *a_vap;
407		struct ucred *a_cred;
408		struct thread *a_td;
409	} */ *ap;
410{
411	register struct vnode *vp = ap->a_vp;
412	register struct inode *ip = VTOI(vp);
413	register struct vattr *vap = ap->a_vap;
414
415	ufs_itimes(vp);
416	/*
417	 * Copy from inode table
418	 */
419	vap->va_fsid = dev2udev(ip->i_dev);
420	vap->va_fileid = ip->i_number;
421	vap->va_mode = ip->i_mode & ~IFMT;
422	vap->va_nlink = VFSTOUFS(vp->v_mount)->um_i_effnlink_valid ?
423	    ip->i_effnlink : ip->i_nlink;
424	vap->va_uid = ip->i_uid;
425	vap->va_gid = ip->i_gid;
426	vap->va_rdev = ip->i_rdev;
427	vap->va_size = ip->i_din.di_size;
428	vap->va_atime.tv_sec = ip->i_atime;
429	vap->va_atime.tv_nsec = ip->i_atimensec;
430	vap->va_mtime.tv_sec = ip->i_mtime;
431	vap->va_mtime.tv_nsec = ip->i_mtimensec;
432	vap->va_ctime.tv_sec = ip->i_ctime;
433	vap->va_ctime.tv_nsec = ip->i_ctimensec;
434	vap->va_flags = ip->i_flags;
435	vap->va_gen = ip->i_gen;
436	vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
437	vap->va_bytes = dbtob((u_quad_t)ip->i_blocks);
438	vap->va_type = IFTOVT(ip->i_mode);
439	vap->va_filerev = ip->i_modrev;
440	return (0);
441}
442
443/*
444 * Set attribute vnode op. called from several syscalls
445 */
446int
447ufs_setattr(ap)
448	struct vop_setattr_args /* {
449		struct vnode *a_vp;
450		struct vattr *a_vap;
451		struct ucred *a_cred;
452		struct thread *a_td;
453	} */ *ap;
454{
455	struct vattr *vap = ap->a_vap;
456	struct vnode *vp = ap->a_vp;
457	struct inode *ip = VTOI(vp);
458	struct ucred *cred = ap->a_cred;
459	struct thread *td = ap->a_td;
460	int error;
461
462	/*
463	 * Check for unsettable attributes.
464	 */
465	if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
466	    (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
467	    (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
468	    ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
469		return (EINVAL);
470	}
471	if (vap->va_flags != VNOVAL) {
472		if (vp->v_mount->mnt_flag & MNT_RDONLY)
473			return (EROFS);
474		/*
475		 * Callers may only modify the file flags on objects they
476		 * have VADMIN rights for.
477		 */
478		if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
479			return (error);
480		/*
481		 * Unprivileged processes and privileged processes in
482		 * jail() are not permitted to unset system flags, or
483		 * modify flags if any system flags are set.
484		 * Privileged non-jail processes may not modify system flags
485		 * if securelevel > 0 and any existing system flags are set.
486		 */
487		if (!suser_xxx(cred, NULL, PRISON_ROOT)) {
488			if (ip->i_flags
489			    & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {
490				error = securelevel_gt(cred, 0);
491				if (error)
492					return (error);
493			}
494			/* Snapshot flag cannot be set or cleared */
495			if (((vap->va_flags & SF_SNAPSHOT) != 0 &&
496			     (ip->i_flags & SF_SNAPSHOT) == 0) ||
497			    ((vap->va_flags & SF_SNAPSHOT) == 0 &&
498			     (ip->i_flags & SF_SNAPSHOT) != 0))
499				return (EPERM);
500			ip->i_flags = vap->va_flags;
501		} else {
502			if (ip->i_flags
503			    & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) ||
504			    (vap->va_flags & UF_SETTABLE) != vap->va_flags)
505				return (EPERM);
506			ip->i_flags &= SF_SETTABLE;
507			ip->i_flags |= (vap->va_flags & UF_SETTABLE);
508		}
509		ip->i_flag |= IN_CHANGE;
510		if (vap->va_flags & (IMMUTABLE | APPEND))
511			return (0);
512	}
513	if (ip->i_flags & (IMMUTABLE | APPEND))
514		return (EPERM);
515	/*
516	 * Go through the fields and update iff not VNOVAL.
517	 */
518	if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
519		if (vp->v_mount->mnt_flag & MNT_RDONLY)
520			return (EROFS);
521		if ((error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred,
522		    td)) != 0)
523			return (error);
524	}
525	if (vap->va_size != VNOVAL) {
526		/*
527		 * Disallow write attempts on read-only file systems;
528		 * unless the file is a socket, fifo, or a block or
529		 * character device resident on the file system.
530		 */
531		switch (vp->v_type) {
532		case VDIR:
533			return (EISDIR);
534		case VLNK:
535		case VREG:
536			if (vp->v_mount->mnt_flag & MNT_RDONLY)
537				return (EROFS);
538			if ((ip->i_flags & SF_SNAPSHOT) != 0)
539				return (EPERM);
540			break;
541		default:
542			break;
543		}
544		if ((error = UFS_TRUNCATE(vp, vap->va_size, 0, cred, td)) != 0)
545			return (error);
546	}
547	if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
548		if (vp->v_mount->mnt_flag & MNT_RDONLY)
549			return (EROFS);
550		if ((ip->i_flags & SF_SNAPSHOT) != 0)
551			return (EPERM);
552		/*
553		 * From utimes(2):
554		 * If times is NULL, ... The caller must be the owner of
555		 * the file, have permission to write the file, or be the
556		 * super-user.
557		 * If times is non-NULL, ... The caller must be the owner of
558		 * the file or be the super-user.
559		 */
560		if ((error = VOP_ACCESS(vp, VADMIN, cred, td)) &&
561		    ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
562		    (error = VOP_ACCESS(vp, VWRITE, cred, td))))
563			return (error);
564		if (vap->va_atime.tv_sec != VNOVAL)
565			ip->i_flag |= IN_ACCESS;
566		if (vap->va_mtime.tv_sec != VNOVAL)
567			ip->i_flag |= IN_CHANGE | IN_UPDATE;
568		ufs_itimes(vp);
569		if (vap->va_atime.tv_sec != VNOVAL) {
570			ip->i_atime = vap->va_atime.tv_sec;
571			ip->i_atimensec = vap->va_atime.tv_nsec;
572		}
573		if (vap->va_mtime.tv_sec != VNOVAL) {
574			ip->i_mtime = vap->va_mtime.tv_sec;
575			ip->i_mtimensec = vap->va_mtime.tv_nsec;
576		}
577		error = UFS_UPDATE(vp, 0);
578		if (error)
579			return (error);
580	}
581	error = 0;
582	if (vap->va_mode != (mode_t)VNOVAL) {
583		if (vp->v_mount->mnt_flag & MNT_RDONLY)
584			return (EROFS);
585		if ((ip->i_flags & SF_SNAPSHOT) != 0 && (vap->va_mode &
586		   (S_IXUSR | S_IWUSR | S_IXGRP | S_IWGRP | S_IXOTH | S_IWOTH)))
587			return (EPERM);
588		error = ufs_chmod(vp, (int)vap->va_mode, cred, td);
589	}
590	VN_KNOTE(vp, NOTE_ATTRIB);
591	return (error);
592}
593
594/*
595 * Change the mode on a file.
596 * Inode must be locked before calling.
597 */
598static int
599ufs_chmod(vp, mode, cred, td)
600	register struct vnode *vp;
601	register int mode;
602	register struct ucred *cred;
603	struct thread *td;
604{
605	register struct inode *ip = VTOI(vp);
606	int error;
607
608	/*
609	 * To modify the permissions on a file, must possess VADMIN
610	 * for that file.
611	 */
612	if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
613		return (error);
614	/*
615	 * Privileged processes may set the sticky bit on non-directories,
616	 * as well as set the setgid bit on a file with a group that the
617	 * process is not a member of.
618	 */
619	if (suser_xxx(cred, NULL, PRISON_ROOT)) {
620		if (vp->v_type != VDIR && (mode & S_ISTXT))
621			return (EFTYPE);
622		if (!groupmember(ip->i_gid, cred) && (mode & ISGID))
623			return (EPERM);
624	}
625	ip->i_mode &= ~ALLPERMS;
626	ip->i_mode |= (mode & ALLPERMS);
627	ip->i_flag |= IN_CHANGE;
628	return (0);
629}
630
631/*
632 * Perform chown operation on inode ip;
633 * inode must be locked prior to call.
634 */
635static int
636ufs_chown(vp, uid, gid, cred, td)
637	register struct vnode *vp;
638	uid_t uid;
639	gid_t gid;
640	struct ucred *cred;
641	struct thread *td;
642{
643	register struct inode *ip = VTOI(vp);
644	uid_t ouid;
645	gid_t ogid;
646	int error = 0;
647#ifdef QUOTA
648	register int i;
649	long change;
650#endif
651
652	if (uid == (uid_t)VNOVAL)
653		uid = ip->i_uid;
654	if (gid == (gid_t)VNOVAL)
655		gid = ip->i_gid;
656	/*
657	 * To modify the ownership of a file, must possess VADMIN
658	 * for that file.
659	 */
660	if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
661		return (error);
662	/*
663	 * To change the owner of a file, or change the group of a file
664	 * to a group of which we are not a member, the caller must
665	 * have privilege.
666	 */
667	if ((uid != ip->i_uid ||
668	    (gid != ip->i_gid && !groupmember(gid, cred))) &&
669	    (error = suser_xxx(cred, td->td_proc, PRISON_ROOT)))
670		return (error);
671	ogid = ip->i_gid;
672	ouid = ip->i_uid;
673#ifdef QUOTA
674	if ((error = getinoquota(ip)) != 0)
675		return (error);
676	if (ouid == uid) {
677		dqrele(vp, ip->i_dquot[USRQUOTA]);
678		ip->i_dquot[USRQUOTA] = NODQUOT;
679	}
680	if (ogid == gid) {
681		dqrele(vp, ip->i_dquot[GRPQUOTA]);
682		ip->i_dquot[GRPQUOTA] = NODQUOT;
683	}
684	change = ip->i_blocks;
685	(void) chkdq(ip, -change, cred, CHOWN);
686	(void) chkiq(ip, -1, cred, CHOWN);
687	for (i = 0; i < MAXQUOTAS; i++) {
688		dqrele(vp, ip->i_dquot[i]);
689		ip->i_dquot[i] = NODQUOT;
690	}
691#endif
692	ip->i_gid = gid;
693	ip->i_uid = uid;
694#ifdef QUOTA
695	if ((error = getinoquota(ip)) == 0) {
696		if (ouid == uid) {
697			dqrele(vp, ip->i_dquot[USRQUOTA]);
698			ip->i_dquot[USRQUOTA] = NODQUOT;
699		}
700		if (ogid == gid) {
701			dqrele(vp, ip->i_dquot[GRPQUOTA]);
702			ip->i_dquot[GRPQUOTA] = NODQUOT;
703		}
704		if ((error = chkdq(ip, change, cred, CHOWN)) == 0) {
705			if ((error = chkiq(ip, 1, cred, CHOWN)) == 0)
706				goto good;
707			else
708				(void) chkdq(ip, -change, cred, CHOWN|FORCE);
709		}
710		for (i = 0; i < MAXQUOTAS; i++) {
711			dqrele(vp, ip->i_dquot[i]);
712			ip->i_dquot[i] = NODQUOT;
713		}
714	}
715	ip->i_gid = ogid;
716	ip->i_uid = ouid;
717	if (getinoquota(ip) == 0) {
718		if (ouid == uid) {
719			dqrele(vp, ip->i_dquot[USRQUOTA]);
720			ip->i_dquot[USRQUOTA] = NODQUOT;
721		}
722		if (ogid == gid) {
723			dqrele(vp, ip->i_dquot[GRPQUOTA]);
724			ip->i_dquot[GRPQUOTA] = NODQUOT;
725		}
726		(void) chkdq(ip, change, cred, FORCE|CHOWN);
727		(void) chkiq(ip, 1, cred, FORCE|CHOWN);
728		(void) getinoquota(ip);
729	}
730	return (error);
731good:
732	if (getinoquota(ip))
733		panic("ufs_chown: lost quota");
734#endif /* QUOTA */
735	ip->i_flag |= IN_CHANGE;
736	if (suser_xxx(cred, NULL, PRISON_ROOT) && (ouid != uid || ogid != gid))
737		ip->i_mode &= ~(ISUID | ISGID);
738	return (0);
739}
740
741int
742ufs_remove(ap)
743	struct vop_remove_args /* {
744		struct vnode *a_dvp;
745		struct vnode *a_vp;
746		struct componentname *a_cnp;
747	} */ *ap;
748{
749	struct inode *ip;
750	struct vnode *vp = ap->a_vp;
751	struct vnode *dvp = ap->a_dvp;
752	int error;
753
754	ip = VTOI(vp);
755	if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
756	    (VTOI(dvp)->i_flags & APPEND)) {
757		error = EPERM;
758		goto out;
759	}
760	error = ufs_dirremove(dvp, ip, ap->a_cnp->cn_flags, 0);
761	if (ip->i_nlink <= 0)
762		vp->v_flag |= VNOSYNC;
763	VN_KNOTE(vp, NOTE_DELETE);
764	VN_KNOTE(dvp, NOTE_WRITE);
765out:
766	return (error);
767}
768
769/*
770 * link vnode call
771 */
772int
773ufs_link(ap)
774	struct vop_link_args /* {
775		struct vnode *a_tdvp;
776		struct vnode *a_vp;
777		struct componentname *a_cnp;
778	} */ *ap;
779{
780	struct vnode *vp = ap->a_vp;
781	struct vnode *tdvp = ap->a_tdvp;
782	struct componentname *cnp = ap->a_cnp;
783	struct thread *td = cnp->cn_thread;
784	struct inode *ip;
785	struct direct newdir;
786	int error;
787
788#ifdef DIAGNOSTIC
789	if ((cnp->cn_flags & HASBUF) == 0)
790		panic("ufs_link: no name");
791#endif
792	if (tdvp->v_mount != vp->v_mount) {
793		error = EXDEV;
794		goto out2;
795	}
796	if (tdvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, td))) {
797		goto out2;
798	}
799	ip = VTOI(vp);
800	if ((nlink_t)ip->i_nlink >= LINK_MAX) {
801		error = EMLINK;
802		goto out1;
803	}
804	if (ip->i_flags & (IMMUTABLE | APPEND)) {
805		error = EPERM;
806		goto out1;
807	}
808	ip->i_effnlink++;
809	ip->i_nlink++;
810	ip->i_flag |= IN_CHANGE;
811	if (DOINGSOFTDEP(vp))
812		softdep_change_linkcnt(ip);
813	error = UFS_UPDATE(vp, !(DOINGSOFTDEP(vp) | DOINGASYNC(vp)));
814	if (!error) {
815		ufs_makedirentry(ip, cnp, &newdir);
816		error = ufs_direnter(tdvp, vp, &newdir, cnp, NULL);
817	}
818
819	if (error) {
820		ip->i_effnlink--;
821		ip->i_nlink--;
822		ip->i_flag |= IN_CHANGE;
823		if (DOINGSOFTDEP(vp))
824			softdep_change_linkcnt(ip);
825	}
826out1:
827	if (tdvp != vp)
828		VOP_UNLOCK(vp, 0, td);
829out2:
830	VN_KNOTE(vp, NOTE_LINK);
831	VN_KNOTE(tdvp, NOTE_WRITE);
832	return (error);
833}
834
835/*
836 * whiteout vnode call
837 */
838int
839ufs_whiteout(ap)
840	struct vop_whiteout_args /* {
841		struct vnode *a_dvp;
842		struct componentname *a_cnp;
843		int a_flags;
844	} */ *ap;
845{
846	struct vnode *dvp = ap->a_dvp;
847	struct componentname *cnp = ap->a_cnp;
848	struct direct newdir;
849	int error = 0;
850
851	switch (ap->a_flags) {
852	case LOOKUP:
853		/* 4.4 format directories support whiteout operations */
854		if (dvp->v_mount->mnt_maxsymlinklen > 0)
855			return (0);
856		return (EOPNOTSUPP);
857
858	case CREATE:
859		/* create a new directory whiteout */
860#ifdef DIAGNOSTIC
861		if ((cnp->cn_flags & SAVENAME) == 0)
862			panic("ufs_whiteout: missing name");
863		if (dvp->v_mount->mnt_maxsymlinklen <= 0)
864			panic("ufs_whiteout: old format filesystem");
865#endif
866
867		newdir.d_ino = WINO;
868		newdir.d_namlen = cnp->cn_namelen;
869		bcopy(cnp->cn_nameptr, newdir.d_name, (unsigned)cnp->cn_namelen + 1);
870		newdir.d_type = DT_WHT;
871		error = ufs_direnter(dvp, NULL, &newdir, cnp, NULL);
872		break;
873
874	case DELETE:
875		/* remove an existing directory whiteout */
876#ifdef DIAGNOSTIC
877		if (dvp->v_mount->mnt_maxsymlinklen <= 0)
878			panic("ufs_whiteout: old format filesystem");
879#endif
880
881		cnp->cn_flags &= ~DOWHITEOUT;
882		error = ufs_dirremove(dvp, NULL, cnp->cn_flags, 0);
883		break;
884	default:
885		panic("ufs_whiteout: unknown op");
886	}
887	return (error);
888}
889
890/*
891 * Rename system call.
892 * 	rename("foo", "bar");
893 * is essentially
894 *	unlink("bar");
895 *	link("foo", "bar");
896 *	unlink("foo");
897 * but ``atomically''.  Can't do full commit without saving state in the
898 * inode on disk which isn't feasible at this time.  Best we can do is
899 * always guarantee the target exists.
900 *
901 * Basic algorithm is:
902 *
903 * 1) Bump link count on source while we're linking it to the
904 *    target.  This also ensure the inode won't be deleted out
905 *    from underneath us while we work (it may be truncated by
906 *    a concurrent `trunc' or `open' for creation).
907 * 2) Link source to destination.  If destination already exists,
908 *    delete it first.
909 * 3) Unlink source reference to inode if still around. If a
910 *    directory was moved and the parent of the destination
911 *    is different from the source, patch the ".." entry in the
912 *    directory.
913 */
914int
915ufs_rename(ap)
916	struct vop_rename_args  /* {
917		struct vnode *a_fdvp;
918		struct vnode *a_fvp;
919		struct componentname *a_fcnp;
920		struct vnode *a_tdvp;
921		struct vnode *a_tvp;
922		struct componentname *a_tcnp;
923	} */ *ap;
924{
925	struct vnode *tvp = ap->a_tvp;
926	register struct vnode *tdvp = ap->a_tdvp;
927	struct vnode *fvp = ap->a_fvp;
928	struct vnode *fdvp = ap->a_fdvp;
929	struct componentname *tcnp = ap->a_tcnp;
930	struct componentname *fcnp = ap->a_fcnp;
931	struct thread *td = fcnp->cn_thread;
932	struct inode *ip, *xp, *dp;
933	struct direct newdir;
934	int doingdirectory = 0, oldparent = 0, newparent = 0;
935	int error = 0, ioflag;
936
937#ifdef DIAGNOSTIC
938	if ((tcnp->cn_flags & HASBUF) == 0 ||
939	    (fcnp->cn_flags & HASBUF) == 0)
940		panic("ufs_rename: no name");
941#endif
942	/*
943	 * Check for cross-device rename.
944	 */
945	if ((fvp->v_mount != tdvp->v_mount) ||
946	    (tvp && (fvp->v_mount != tvp->v_mount))) {
947		error = EXDEV;
948abortit:
949		if (tdvp == tvp)
950			vrele(tdvp);
951		else
952			vput(tdvp);
953		if (tvp)
954			vput(tvp);
955		vrele(fdvp);
956		vrele(fvp);
957		return (error);
958	}
959
960	if (tvp && ((VTOI(tvp)->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) ||
961	    (VTOI(tdvp)->i_flags & APPEND))) {
962		error = EPERM;
963		goto abortit;
964	}
965
966	/*
967	 * Check if just deleting a link name or if we've lost a race.
968	 * If another process completes the same rename after we've looked
969	 * up the source and have blocked looking up the target, then the
970	 * source and target inodes may be identical now although the
971	 * names were never linked.
972	 */
973	if (fvp == tvp) {
974		if (fvp->v_type == VDIR) {
975			/*
976			 * Linked directories are impossible, so we must
977			 * have lost the race.  Pretend that the rename
978			 * completed before the lookup.
979			 */
980#ifdef UFS_RENAME_DEBUG
981			printf("ufs_rename: fvp == tvp for directories\n");
982#endif
983			error = ENOENT;
984			goto abortit;
985		}
986
987		/* Release destination completely. */
988		vput(tdvp);
989		vput(tvp);
990
991		/*
992		 * Delete source.  There is another race now that everything
993		 * is unlocked, but this doesn't cause any new complications.
994		 * Relookup() may find a file that is unrelated to the
995		 * original one, or it may fail.  Too bad.
996		 */
997		vrele(fdvp);
998		vrele(fvp);
999		fcnp->cn_flags &= ~MODMASK;
1000		fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
1001		if ((fcnp->cn_flags & SAVESTART) == 0)
1002			panic("ufs_rename: lost from startdir");
1003		fcnp->cn_nameiop = DELETE;
1004		VREF(fdvp);
1005		error = relookup(fdvp, &fvp, fcnp);
1006		if (error == 0)
1007			vrele(fdvp);
1008		if (fvp == NULL) {
1009#ifdef UFS_RENAME_DEBUG
1010			printf("ufs_rename: from name disappeared\n");
1011#endif
1012			return (ENOENT);
1013		}
1014		error = VOP_REMOVE(fdvp, fvp, fcnp);
1015		if (fdvp == fvp)
1016			vrele(fdvp);
1017		else
1018			vput(fdvp);
1019		vput(fvp);
1020		return (error);
1021	}
1022	if ((error = vn_lock(fvp, LK_EXCLUSIVE, td)) != 0)
1023		goto abortit;
1024	dp = VTOI(fdvp);
1025	ip = VTOI(fvp);
1026	if (ip->i_nlink >= LINK_MAX) {
1027		VOP_UNLOCK(fvp, 0, td);
1028		error = EMLINK;
1029		goto abortit;
1030	}
1031	if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))
1032	    || (dp->i_flags & APPEND)) {
1033		VOP_UNLOCK(fvp, 0, td);
1034		error = EPERM;
1035		goto abortit;
1036	}
1037	if ((ip->i_mode & IFMT) == IFDIR) {
1038		/*
1039		 * Avoid ".", "..", and aliases of "." for obvious reasons.
1040		 */
1041		if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
1042		    dp == ip || (fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT ||
1043		    (ip->i_flag & IN_RENAME)) {
1044			VOP_UNLOCK(fvp, 0, td);
1045			error = EINVAL;
1046			goto abortit;
1047		}
1048		ip->i_flag |= IN_RENAME;
1049		oldparent = dp->i_number;
1050		doingdirectory = 1;
1051	}
1052	VN_KNOTE(fdvp, NOTE_WRITE);		/* XXX right place? */
1053	vrele(fdvp);
1054
1055	/*
1056	 * When the target exists, both the directory
1057	 * and target vnodes are returned locked.
1058	 */
1059	dp = VTOI(tdvp);
1060	xp = NULL;
1061	if (tvp)
1062		xp = VTOI(tvp);
1063
1064	/*
1065	 * 1) Bump link count while we're moving stuff
1066	 *    around.  If we crash somewhere before
1067	 *    completing our work, the link count
1068	 *    may be wrong, but correctable.
1069	 */
1070	ip->i_effnlink++;
1071	ip->i_nlink++;
1072	ip->i_flag |= IN_CHANGE;
1073	if (DOINGSOFTDEP(fvp))
1074		softdep_change_linkcnt(ip);
1075	if ((error = UFS_UPDATE(fvp, !(DOINGSOFTDEP(fvp) |
1076				       DOINGASYNC(fvp)))) != 0) {
1077		VOP_UNLOCK(fvp, 0, td);
1078		goto bad;
1079	}
1080
1081	/*
1082	 * If ".." must be changed (ie the directory gets a new
1083	 * parent) then the source directory must not be in the
1084	 * directory heirarchy above the target, as this would
1085	 * orphan everything below the source directory. Also
1086	 * the user must have write permission in the source so
1087	 * as to be able to change "..". We must repeat the call
1088	 * to namei, as the parent directory is unlocked by the
1089	 * call to checkpath().
1090	 */
1091	error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_thread);
1092	VOP_UNLOCK(fvp, 0, td);
1093	if (oldparent != dp->i_number)
1094		newparent = dp->i_number;
1095	if (doingdirectory && newparent) {
1096		if (error)	/* write access check above */
1097			goto bad;
1098		if (xp != NULL)
1099			vput(tvp);
1100		error = ufs_checkpath(ip, dp, tcnp->cn_cred);
1101		if (error)
1102			goto out;
1103		if ((tcnp->cn_flags & SAVESTART) == 0)
1104			panic("ufs_rename: lost to startdir");
1105		VREF(tdvp);
1106		error = relookup(tdvp, &tvp, tcnp);
1107		if (error)
1108			goto out;
1109		vrele(tdvp);
1110		dp = VTOI(tdvp);
1111		xp = NULL;
1112		if (tvp)
1113			xp = VTOI(tvp);
1114	}
1115	/*
1116	 * 2) If target doesn't exist, link the target
1117	 *    to the source and unlink the source.
1118	 *    Otherwise, rewrite the target directory
1119	 *    entry to reference the source inode and
1120	 *    expunge the original entry's existence.
1121	 */
1122	if (xp == NULL) {
1123		if (dp->i_dev != ip->i_dev)
1124			panic("ufs_rename: EXDEV");
1125		/*
1126		 * Account for ".." in new directory.
1127		 * When source and destination have the same
1128		 * parent we don't fool with the link count.
1129		 */
1130		if (doingdirectory && newparent) {
1131			if ((nlink_t)dp->i_nlink >= LINK_MAX) {
1132				error = EMLINK;
1133				goto bad;
1134			}
1135			dp->i_effnlink++;
1136			dp->i_nlink++;
1137			dp->i_flag |= IN_CHANGE;
1138			if (DOINGSOFTDEP(tdvp))
1139				softdep_change_linkcnt(dp);
1140			error = UFS_UPDATE(tdvp, !(DOINGSOFTDEP(tdvp) |
1141						   DOINGASYNC(tdvp)));
1142			if (error)
1143				goto bad;
1144		}
1145		ufs_makedirentry(ip, tcnp, &newdir);
1146		error = ufs_direnter(tdvp, NULL, &newdir, tcnp, NULL);
1147		if (error) {
1148			if (doingdirectory && newparent) {
1149				dp->i_effnlink--;
1150				dp->i_nlink--;
1151				dp->i_flag |= IN_CHANGE;
1152				if (DOINGSOFTDEP(tdvp))
1153					softdep_change_linkcnt(dp);
1154				(void)UFS_UPDATE(tdvp, 1);
1155			}
1156			goto bad;
1157		}
1158		VN_KNOTE(tdvp, NOTE_WRITE);
1159		vput(tdvp);
1160	} else {
1161		if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
1162			panic("ufs_rename: EXDEV");
1163		/*
1164		 * Short circuit rename(foo, foo).
1165		 */
1166		if (xp->i_number == ip->i_number)
1167			panic("ufs_rename: same file");
1168		/*
1169		 * If the parent directory is "sticky", then the caller
1170		 * must possess VADMIN for the parent directory, or the
1171		 * destination of the rename.  This implements append-only
1172		 * directories.
1173		 */
1174		if ((dp->i_mode & S_ISTXT) &&
1175		    VOP_ACCESS(tdvp, VADMIN, tcnp->cn_cred, td) &&
1176		    VOP_ACCESS(tvp, VADMIN, tcnp->cn_cred, td)) {
1177			error = EPERM;
1178			goto bad;
1179		}
1180		/*
1181		 * Target must be empty if a directory and have no links
1182		 * to it. Also, ensure source and target are compatible
1183		 * (both directories, or both not directories).
1184		 */
1185		if ((xp->i_mode&IFMT) == IFDIR) {
1186			if ((xp->i_effnlink > 2) ||
1187			    !ufs_dirempty(xp, dp->i_number, tcnp->cn_cred)) {
1188				error = ENOTEMPTY;
1189				goto bad;
1190			}
1191			if (!doingdirectory) {
1192				error = ENOTDIR;
1193				goto bad;
1194			}
1195			cache_purge(tdvp);
1196		} else if (doingdirectory) {
1197			error = EISDIR;
1198			goto bad;
1199		}
1200		error = ufs_dirrewrite(dp, xp, ip->i_number,
1201		    IFTODT(ip->i_mode),
1202		    (doingdirectory && newparent) ? newparent : doingdirectory);
1203		if (error)
1204			goto bad;
1205		if (doingdirectory) {
1206			if (!newparent) {
1207				dp->i_effnlink--;
1208				if (DOINGSOFTDEP(tdvp))
1209					softdep_change_linkcnt(dp);
1210			}
1211			xp->i_effnlink--;
1212			if (DOINGSOFTDEP(tvp))
1213				softdep_change_linkcnt(xp);
1214		}
1215		if (doingdirectory && !DOINGSOFTDEP(tvp)) {
1216			/*
1217			 * Truncate inode. The only stuff left in the directory
1218			 * is "." and "..". The "." reference is inconsequential
1219			 * since we are quashing it. We have removed the "."
1220			 * reference and the reference in the parent directory,
1221			 * but there may be other hard links. The soft
1222			 * dependency code will arrange to do these operations
1223			 * after the parent directory entry has been deleted on
1224			 * disk, so when running with that code we avoid doing
1225			 * them now.
1226			 */
1227			if (!newparent) {
1228				dp->i_nlink--;
1229				dp->i_flag |= IN_CHANGE;
1230			}
1231			xp->i_nlink--;
1232			xp->i_flag |= IN_CHANGE;
1233			ioflag = DOINGASYNC(tvp) ? 0 : IO_SYNC;
1234			if ((error = UFS_TRUNCATE(tvp, (off_t)0, ioflag,
1235			    tcnp->cn_cred, tcnp->cn_thread)) != 0)
1236				goto bad;
1237		}
1238		VN_KNOTE(tdvp, NOTE_WRITE);
1239		vput(tdvp);
1240		VN_KNOTE(tvp, NOTE_DELETE);
1241		vput(tvp);
1242		xp = NULL;
1243	}
1244
1245	/*
1246	 * 3) Unlink the source.
1247	 */
1248	fcnp->cn_flags &= ~MODMASK;
1249	fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
1250	if ((fcnp->cn_flags & SAVESTART) == 0)
1251		panic("ufs_rename: lost from startdir");
1252	VREF(fdvp);
1253	error = relookup(fdvp, &fvp, fcnp);
1254	if (error == 0)
1255		vrele(fdvp);
1256	if (fvp != NULL) {
1257		xp = VTOI(fvp);
1258		dp = VTOI(fdvp);
1259	} else {
1260		/*
1261		 * From name has disappeared.  IN_RENAME is not sufficient
1262		 * to protect against directory races due to timing windows,
1263		 * so we have to remove the panic.  XXX the only real way
1264		 * to solve this issue is at a much higher level.  By the
1265		 * time we hit ufs_rename() it's too late.
1266		 */
1267#if 0
1268		if (doingdirectory)
1269			panic("ufs_rename: lost dir entry");
1270#endif
1271		vrele(ap->a_fvp);
1272		return (0);
1273	}
1274	/*
1275	 * Ensure that the directory entry still exists and has not
1276	 * changed while the new name has been entered. If the source is
1277	 * a file then the entry may have been unlinked or renamed. In
1278	 * either case there is no further work to be done. If the source
1279	 * is a directory then it cannot have been rmdir'ed; the IN_RENAME
1280	 * flag ensures that it cannot be moved by another rename or removed
1281	 * by a rmdir.
1282	 */
1283	if (xp != ip) {
1284		/*
1285		 * From name resolves to a different inode.  IN_RENAME is
1286		 * not sufficient protection against timing window races
1287		 * so we can't panic here.  XXX the only real way
1288		 * to solve this issue is at a much higher level.  By the
1289		 * time we hit ufs_rename() it's too late.
1290		 */
1291#if 0
1292		if (doingdirectory)
1293			panic("ufs_rename: lost dir entry");
1294#endif
1295	} else {
1296		/*
1297		 * If the source is a directory with a
1298		 * new parent, the link count of the old
1299		 * parent directory must be decremented
1300		 * and ".." set to point to the new parent.
1301		 */
1302		if (doingdirectory && newparent) {
1303			xp->i_offset = mastertemplate.dot_reclen;
1304			ufs_dirrewrite(xp, dp, newparent, DT_DIR, 0);
1305			cache_purge(fdvp);
1306		}
1307		error = ufs_dirremove(fdvp, xp, fcnp->cn_flags, 0);
1308		xp->i_flag &= ~IN_RENAME;
1309	}
1310	VN_KNOTE(fvp, NOTE_RENAME);
1311	if (dp)
1312		vput(fdvp);
1313	if (xp)
1314		vput(fvp);
1315	vrele(ap->a_fvp);
1316	return (error);
1317
1318bad:
1319	if (xp)
1320		vput(ITOV(xp));
1321	vput(ITOV(dp));
1322out:
1323	if (doingdirectory)
1324		ip->i_flag &= ~IN_RENAME;
1325	if (vn_lock(fvp, LK_EXCLUSIVE, td) == 0) {
1326		ip->i_effnlink--;
1327		ip->i_nlink--;
1328		ip->i_flag |= IN_CHANGE;
1329		ip->i_flag &= ~IN_RENAME;
1330		if (DOINGSOFTDEP(fvp))
1331			softdep_change_linkcnt(ip);
1332		vput(fvp);
1333	} else
1334		vrele(fvp);
1335	return (error);
1336}
1337
1338/*
1339 * Mkdir system call
1340 */
1341int
1342ufs_mkdir(ap)
1343	struct vop_mkdir_args /* {
1344		struct vnode *a_dvp;
1345		struct vnode **a_vpp;
1346		struct componentname *a_cnp;
1347		struct vattr *a_vap;
1348	} */ *ap;
1349{
1350	register struct vnode *dvp = ap->a_dvp;
1351	register struct vattr *vap = ap->a_vap;
1352	register struct componentname *cnp = ap->a_cnp;
1353	register struct inode *ip, *dp;
1354	struct vnode *tvp;
1355	struct buf *bp;
1356	struct dirtemplate dirtemplate, *dtp;
1357	struct direct newdir;
1358#ifdef UFS_ACL
1359	struct acl *acl, *dacl;
1360#endif
1361	int error, dmode;
1362	long blkoff;
1363
1364#ifdef DIAGNOSTIC
1365	if ((cnp->cn_flags & HASBUF) == 0)
1366		panic("ufs_mkdir: no name");
1367#endif
1368	dp = VTOI(dvp);
1369	if ((nlink_t)dp->i_nlink >= LINK_MAX) {
1370		error = EMLINK;
1371		goto out;
1372	}
1373	dmode = vap->va_mode & 0777;
1374	dmode |= IFDIR;
1375	/*
1376	 * Must simulate part of ufs_makeinode here to acquire the inode,
1377	 * but not have it entered in the parent directory. The entry is
1378	 * made later after writing "." and ".." entries.
1379	 */
1380	error = UFS_VALLOC(dvp, dmode, cnp->cn_cred, &tvp);
1381	if (error)
1382		goto out;
1383	ip = VTOI(tvp);
1384	ip->i_gid = dp->i_gid;
1385#ifdef SUIDDIR
1386	{
1387#ifdef QUOTA
1388		struct ucred ucred, *ucp;
1389		ucp = cnp->cn_cred;
1390#endif
1391		/*
1392		 * If we are hacking owners here, (only do this where told to)
1393		 * and we are not giving it TO root, (would subvert quotas)
1394		 * then go ahead and give it to the other user.
1395		 * The new directory also inherits the SUID bit.
1396		 * If user's UID and dir UID are the same,
1397		 * 'give it away' so that the SUID is still forced on.
1398		 */
1399		if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) &&
1400		    (dp->i_mode & ISUID) && dp->i_uid) {
1401			dmode |= ISUID;
1402			ip->i_uid = dp->i_uid;
1403#ifdef QUOTA
1404			if (dp->i_uid != cnp->cn_cred->cr_uid) {
1405				/*
1406				 * Make sure the correct user gets charged
1407				 * for the space.
1408				 * Make a dummy credential for the victim.
1409				 * XXX This seems to never be accessed out of
1410				 * our context so a stack variable is ok.
1411				 */
1412				ucred.cr_ref = 1;
1413				ucred.cr_uid = ip->i_uid;
1414				ucred.cr_ngroups = 1;
1415				ucred.cr_groups[0] = dp->i_gid;
1416				ucp = &ucred;
1417			}
1418#endif
1419		} else
1420			ip->i_uid = cnp->cn_cred->cr_uid;
1421#ifdef QUOTA
1422		if ((error = getinoquota(ip)) ||
1423	    	    (error = chkiq(ip, 1, ucp, 0))) {
1424			UFS_VFREE(tvp, ip->i_number, dmode);
1425			vput(tvp);
1426			return (error);
1427		}
1428#endif
1429	}
1430#else	/* !SUIDDIR */
1431	ip->i_uid = cnp->cn_cred->cr_uid;
1432#ifdef QUOTA
1433	if ((error = getinoquota(ip)) ||
1434	    (error = chkiq(ip, 1, cnp->cn_cred, 0))) {
1435		UFS_VFREE(tvp, ip->i_number, dmode);
1436		vput(tvp);
1437		return (error);
1438	}
1439#endif
1440#endif	/* !SUIDDIR */
1441	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
1442#ifdef UFS_ACL
1443	MALLOC(acl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK);
1444	MALLOC(dacl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK);
1445
1446	/*
1447	 * Retrieve default ACL from parent, if any.
1448	 */
1449	error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cnp->cn_cred,
1450	    cnp->cn_thread);
1451	switch (error) {
1452	case 0:
1453		/*
1454		 * Retrieved a default ACL, so merge mode and ACL if
1455		 * necessary.
1456		 */
1457		if (acl->acl_cnt != 0) {
1458			/*
1459			 * Two possible ways for default ACL to not be
1460			 * present.  First, the EA can be undefined,
1461			 * or second, the default ACL can be blank.
1462			 * If it's blank, fall through to the it's
1463			 * not defined case.
1464			 */
1465			ip->i_mode = dmode;
1466			*dacl = *acl;
1467			ufs_sync_acl_from_inode(ip, acl);
1468			break;
1469		}
1470		/* FALLTHROUGH */
1471
1472	case EOPNOTSUPP:
1473		/*
1474		 * Just use the mode as-is.
1475		 */
1476		ip->i_mode = dmode;
1477		FREE(acl, M_ACL);
1478		FREE(dacl, M_ACL);
1479		dacl = acl = NULL;
1480		break;
1481
1482	default:
1483		UFS_VFREE(tvp, ip->i_number, dmode);
1484		vput(tvp);
1485		return (error);
1486	}
1487#else /* !UFS_ACL */
1488	ip->i_mode = dmode;
1489#endif /* !UFS_ACL */
1490	tvp->v_type = VDIR;	/* Rest init'd in getnewvnode(). */
1491	ip->i_effnlink = 2;
1492	ip->i_nlink = 2;
1493	if (DOINGSOFTDEP(tvp))
1494		softdep_change_linkcnt(ip);
1495	if (cnp->cn_flags & ISWHITEOUT)
1496		ip->i_flags |= UF_OPAQUE;
1497
1498	/*
1499	 * Bump link count in parent directory to reflect work done below.
1500	 * Should be done before reference is created so cleanup is
1501	 * possible if we crash.
1502	 */
1503	dp->i_effnlink++;
1504	dp->i_nlink++;
1505	dp->i_flag |= IN_CHANGE;
1506	if (DOINGSOFTDEP(dvp))
1507		softdep_change_linkcnt(dp);
1508	error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(dvp) | DOINGASYNC(dvp)));
1509	if (error)
1510		goto bad;
1511#ifdef UFS_ACL
1512	if (acl != NULL) {
1513		/*
1514		 * XXX: If we abort now, will Soft Updates notify the extattr
1515		 * code that the EAs for the file need to be released?
1516		 */
1517		error = VOP_SETACL(tvp, ACL_TYPE_ACCESS, acl, cnp->cn_cred,
1518		    cnp->cn_thread);
1519		if (error == 0)
1520			error = VOP_SETACL(tvp, ACL_TYPE_DEFAULT, dacl,
1521			    cnp->cn_cred, cnp->cn_thread);
1522		switch (error) {
1523		case 0:
1524			break;
1525
1526		case EOPNOTSUPP:
1527			/*
1528			 * XXX: This should not happen, as EOPNOTSUPP above
1529			 * was supposed to free acl.
1530			 */
1531			printf("ufs_mkdir: VOP_GETACL() but no VOP_SETACL()\n");
1532			/*
1533			panic("ufs_mkdir: VOP_GETACL() but no VOP_SETACL()");
1534			 */
1535			break;
1536
1537		default:
1538			FREE(acl, M_ACL);
1539			FREE(dacl, M_ACL);
1540			goto bad;
1541		}
1542		FREE(acl, M_ACL);
1543		FREE(dacl, M_ACL);
1544	}
1545#endif /* !UFS_ACL */
1546
1547	/*
1548	 * Initialize directory with "." and ".." from static template.
1549	 */
1550	if (dvp->v_mount->mnt_maxsymlinklen > 0
1551	)
1552		dtp = &mastertemplate;
1553	else
1554		dtp = (struct dirtemplate *)&omastertemplate;
1555	dirtemplate = *dtp;
1556	dirtemplate.dot_ino = ip->i_number;
1557	dirtemplate.dotdot_ino = dp->i_number;
1558	if ((error = UFS_BALLOC(tvp, (off_t)0, DIRBLKSIZ, cnp->cn_cred,
1559	    B_CLRBUF, &bp)) != 0)
1560		goto bad;
1561	ip->i_size = DIRBLKSIZ;
1562	ip->i_flag |= IN_CHANGE | IN_UPDATE;
1563	vnode_pager_setsize(tvp, (u_long)ip->i_size);
1564	bcopy((caddr_t)&dirtemplate, (caddr_t)bp->b_data, sizeof dirtemplate);
1565	if (DOINGSOFTDEP(tvp)) {
1566		/*
1567		 * Ensure that the entire newly allocated block is a
1568		 * valid directory so that future growth within the
1569		 * block does not have to ensure that the block is
1570		 * written before the inode.
1571		 */
1572		blkoff = DIRBLKSIZ;
1573		while (blkoff < bp->b_bcount) {
1574			((struct direct *)
1575			   (bp->b_data + blkoff))->d_reclen = DIRBLKSIZ;
1576			blkoff += DIRBLKSIZ;
1577		}
1578	}
1579	if ((error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(tvp) |
1580				       DOINGASYNC(tvp)))) != 0) {
1581		(void)BUF_WRITE(bp);
1582		goto bad;
1583	}
1584	/*
1585	 * Directory set up, now install its entry in the parent directory.
1586	 *
1587	 * If we are not doing soft dependencies, then we must write out the
1588	 * buffer containing the new directory body before entering the new
1589	 * name in the parent. If we are doing soft dependencies, then the
1590	 * buffer containing the new directory body will be passed to and
1591	 * released in the soft dependency code after the code has attached
1592	 * an appropriate ordering dependency to the buffer which ensures that
1593	 * the buffer is written before the new name is written in the parent.
1594	 */
1595	if (DOINGASYNC(dvp))
1596		bdwrite(bp);
1597	else if (!DOINGSOFTDEP(dvp) && ((error = BUF_WRITE(bp))))
1598		goto bad;
1599	ufs_makedirentry(ip, cnp, &newdir);
1600	error = ufs_direnter(dvp, tvp, &newdir, cnp, bp);
1601
1602bad:
1603	if (error == 0) {
1604		VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
1605		*ap->a_vpp = tvp;
1606	} else {
1607		dp->i_effnlink--;
1608		dp->i_nlink--;
1609		dp->i_flag |= IN_CHANGE;
1610		if (DOINGSOFTDEP(dvp))
1611			softdep_change_linkcnt(dp);
1612		/*
1613		 * No need to do an explicit VOP_TRUNCATE here, vrele will
1614		 * do this for us because we set the link count to 0.
1615		 */
1616		ip->i_effnlink = 0;
1617		ip->i_nlink = 0;
1618		ip->i_flag |= IN_CHANGE;
1619		if (DOINGSOFTDEP(tvp))
1620			softdep_change_linkcnt(ip);
1621		vput(tvp);
1622	}
1623out:
1624	return (error);
1625}
1626
1627/*
1628 * Rmdir system call.
1629 */
1630int
1631ufs_rmdir(ap)
1632	struct vop_rmdir_args /* {
1633		struct vnode *a_dvp;
1634		struct vnode *a_vp;
1635		struct componentname *a_cnp;
1636	} */ *ap;
1637{
1638	struct vnode *vp = ap->a_vp;
1639	struct vnode *dvp = ap->a_dvp;
1640	struct componentname *cnp = ap->a_cnp;
1641	struct inode *ip, *dp;
1642	int error, ioflag;
1643
1644	ip = VTOI(vp);
1645	dp = VTOI(dvp);
1646
1647	/*
1648	 * Do not remove a directory that is in the process of being renamed.
1649	 * Verify the directory is empty (and valid). Rmdir ".." will not be
1650	 * valid since ".." will contain a reference to the current directory
1651	 * and thus be non-empty. Do not allow the removal of mounted on
1652	 * directories (this can happen when an NFS exported filesystem
1653	 * tries to remove a locally mounted on directory).
1654	 */
1655	error = 0;
1656	if (ip->i_flag & IN_RENAME) {
1657		error = EINVAL;
1658		goto out;
1659	}
1660	if (ip->i_effnlink != 2 ||
1661	    !ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) {
1662		error = ENOTEMPTY;
1663		goto out;
1664	}
1665	if ((dp->i_flags & APPEND)
1666	    || (ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))) {
1667		error = EPERM;
1668		goto out;
1669	}
1670	if (vp->v_mountedhere != 0) {
1671		error = EINVAL;
1672		goto out;
1673	}
1674	/*
1675	 * Delete reference to directory before purging
1676	 * inode.  If we crash in between, the directory
1677	 * will be reattached to lost+found,
1678	 */
1679	dp->i_effnlink--;
1680	ip->i_effnlink--;
1681	if (DOINGSOFTDEP(vp)) {
1682		softdep_change_linkcnt(dp);
1683		softdep_change_linkcnt(ip);
1684	}
1685	error = ufs_dirremove(dvp, ip, cnp->cn_flags, 1);
1686	if (error) {
1687		dp->i_effnlink++;
1688		ip->i_effnlink++;
1689		if (DOINGSOFTDEP(vp)) {
1690			softdep_change_linkcnt(dp);
1691			softdep_change_linkcnt(ip);
1692		}
1693		goto out;
1694	}
1695	VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
1696	cache_purge(dvp);
1697	/*
1698	 * Truncate inode. The only stuff left in the directory is "." and
1699	 * "..". The "." reference is inconsequential since we are quashing
1700	 * it. The soft dependency code will arrange to do these operations
1701	 * after the parent directory entry has been deleted on disk, so
1702	 * when running with that code we avoid doing them now.
1703	 */
1704	if (!DOINGSOFTDEP(vp)) {
1705		dp->i_nlink--;
1706		dp->i_flag |= IN_CHANGE;
1707		ip->i_nlink--;
1708		ip->i_flag |= IN_CHANGE;
1709		ioflag = DOINGASYNC(vp) ? 0 : IO_SYNC;
1710		error = UFS_TRUNCATE(vp, (off_t)0, ioflag, cnp->cn_cred,
1711		    cnp->cn_thread);
1712	}
1713	cache_purge(vp);
1714#ifdef UFS_DIRHASH
1715	/* Kill any active hash; i_effnlink == 0, so it will not come back. */
1716	if (ip->i_dirhash != NULL)
1717		ufsdirhash_free(ip);
1718#endif
1719out:
1720	VN_KNOTE(vp, NOTE_DELETE);
1721	return (error);
1722}
1723
1724/*
1725 * symlink -- make a symbolic link
1726 */
1727int
1728ufs_symlink(ap)
1729	struct vop_symlink_args /* {
1730		struct vnode *a_dvp;
1731		struct vnode **a_vpp;
1732		struct componentname *a_cnp;
1733		struct vattr *a_vap;
1734		char *a_target;
1735	} */ *ap;
1736{
1737	register struct vnode *vp, **vpp = ap->a_vpp;
1738	register struct inode *ip;
1739	int len, error;
1740
1741	error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp,
1742	    vpp, ap->a_cnp);
1743	if (error)
1744		return (error);
1745	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
1746	vp = *vpp;
1747	len = strlen(ap->a_target);
1748	if (len < vp->v_mount->mnt_maxsymlinklen) {
1749		ip = VTOI(vp);
1750		bcopy(ap->a_target, (char *)ip->i_shortlink, len);
1751		ip->i_size = len;
1752		ip->i_flag |= IN_CHANGE | IN_UPDATE;
1753	} else
1754		error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
1755		    UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred, (int *)0,
1756		    (struct thread *)0);
1757	if (error)
1758		vput(vp);
1759	return (error);
1760}
1761
1762/*
1763 * Vnode op for reading directories.
1764 *
1765 * The routine below assumes that the on-disk format of a directory
1766 * is the same as that defined by <sys/dirent.h>. If the on-disk
1767 * format changes, then it will be necessary to do a conversion
1768 * from the on-disk format that read returns to the format defined
1769 * by <sys/dirent.h>.
1770 */
1771int
1772ufs_readdir(ap)
1773	struct vop_readdir_args /* {
1774		struct vnode *a_vp;
1775		struct uio *a_uio;
1776		struct ucred *a_cred;
1777		int *a_eofflag;
1778		int *ncookies;
1779		u_long **a_cookies;
1780	} */ *ap;
1781{
1782	register struct uio *uio = ap->a_uio;
1783	int error;
1784	size_t count, lost;
1785	off_t off;
1786
1787	if (ap->a_ncookies != NULL)
1788		/*
1789		 * Ensure that the block is aligned.  The caller can use
1790		 * the cookies to determine where in the block to start.
1791		 */
1792		uio->uio_offset &= ~(DIRBLKSIZ - 1);
1793	off = uio->uio_offset;
1794	count = uio->uio_resid;
1795	/* Make sure we don't return partial entries. */
1796	if (count <= ((uio->uio_offset + count) & (DIRBLKSIZ -1)))
1797		return (EINVAL);
1798	count -= (uio->uio_offset + count) & (DIRBLKSIZ -1);
1799	lost = uio->uio_resid - count;
1800	uio->uio_resid = count;
1801	uio->uio_iov->iov_len = count;
1802#	if (BYTE_ORDER == LITTLE_ENDIAN)
1803		if (ap->a_vp->v_mount->mnt_maxsymlinklen > 0) {
1804			error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred);
1805		} else {
1806			struct dirent *dp, *edp;
1807			struct uio auio;
1808			struct iovec aiov;
1809			caddr_t dirbuf;
1810			int readcnt;
1811			u_char tmp;
1812
1813			auio = *uio;
1814			auio.uio_iov = &aiov;
1815			auio.uio_iovcnt = 1;
1816			auio.uio_segflg = UIO_SYSSPACE;
1817			aiov.iov_len = count;
1818			MALLOC(dirbuf, caddr_t, count, M_TEMP, M_WAITOK);
1819			aiov.iov_base = dirbuf;
1820			error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred);
1821			if (error == 0) {
1822				readcnt = count - auio.uio_resid;
1823				edp = (struct dirent *)&dirbuf[readcnt];
1824				for (dp = (struct dirent *)dirbuf; dp < edp; ) {
1825					tmp = dp->d_namlen;
1826					dp->d_namlen = dp->d_type;
1827					dp->d_type = tmp;
1828					if (dp->d_reclen > 0) {
1829						dp = (struct dirent *)
1830						    ((char *)dp + dp->d_reclen);
1831					} else {
1832						error = EIO;
1833						break;
1834					}
1835				}
1836				if (dp >= edp)
1837					error = uiomove(dirbuf, readcnt, uio);
1838			}
1839			FREE(dirbuf, M_TEMP);
1840		}
1841#	else
1842		error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred);
1843#	endif
1844	if (!error && ap->a_ncookies != NULL) {
1845		struct dirent* dpStart;
1846		struct dirent* dpEnd;
1847		struct dirent* dp;
1848		int ncookies;
1849		u_long *cookies;
1850		u_long *cookiep;
1851
1852		if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
1853			panic("ufs_readdir: unexpected uio from NFS server");
1854		dpStart = (struct dirent *)
1855		     (uio->uio_iov->iov_base - (uio->uio_offset - off));
1856		dpEnd = (struct dirent *) uio->uio_iov->iov_base;
1857		for (dp = dpStart, ncookies = 0;
1858		     dp < dpEnd;
1859		     dp = (struct dirent *)((caddr_t) dp + dp->d_reclen))
1860			ncookies++;
1861		MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
1862		    M_WAITOK);
1863		for (dp = dpStart, cookiep = cookies;
1864		     dp < dpEnd;
1865		     dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) {
1866			off += dp->d_reclen;
1867			*cookiep++ = (u_long) off;
1868		}
1869		*ap->a_ncookies = ncookies;
1870		*ap->a_cookies = cookies;
1871	}
1872	uio->uio_resid += lost;
1873	if (ap->a_eofflag)
1874	    *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset;
1875	return (error);
1876}
1877
1878/*
1879 * Return target name of a symbolic link
1880 */
1881int
1882ufs_readlink(ap)
1883	struct vop_readlink_args /* {
1884		struct vnode *a_vp;
1885		struct uio *a_uio;
1886		struct ucred *a_cred;
1887	} */ *ap;
1888{
1889	register struct vnode *vp = ap->a_vp;
1890	register struct inode *ip = VTOI(vp);
1891	int isize;
1892
1893	isize = ip->i_size;
1894	if ((isize < vp->v_mount->mnt_maxsymlinklen) ||
1895	    (ip->i_din.di_blocks == 0)) {	/* XXX - for old fastlink support */
1896		uiomove((char *)ip->i_shortlink, isize, ap->a_uio);
1897		return (0);
1898	}
1899	return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
1900}
1901
1902/*
1903 * Calculate the logical to physical mapping if not done already,
1904 * then call the device strategy routine.
1905 *
1906 * In order to be able to swap to a file, the ufs_bmaparray() operation may not
1907 * deadlock on memory.  See ufs_bmap() for details.
1908 */
1909int
1910ufs_strategy(ap)
1911	struct vop_strategy_args /* {
1912		struct vnode *a_vp;
1913		struct buf *a_bp;
1914	} */ *ap;
1915{
1916	register struct buf *bp = ap->a_bp;
1917	register struct vnode *vp = ap->a_vp;
1918	register struct inode *ip;
1919	daddr_t blkno;
1920	int error;
1921
1922	ip = VTOI(vp);
1923	if (vp->v_type == VBLK || vp->v_type == VCHR)
1924		panic("ufs_strategy: spec");
1925	if (bp->b_blkno == bp->b_lblkno) {
1926		error = ufs_bmaparray(vp, bp->b_lblkno, &blkno, NULL, NULL);
1927		bp->b_blkno = blkno;
1928		if (error) {
1929			bp->b_error = error;
1930			bp->b_ioflags |= BIO_ERROR;
1931			bufdone(bp);
1932			return (error);
1933		}
1934		if ((long)bp->b_blkno == -1)
1935			vfs_bio_clrbuf(bp);
1936	}
1937	if ((long)bp->b_blkno == -1) {
1938		bufdone(bp);
1939		return (0);
1940	}
1941	vp = ip->i_devvp;
1942	bp->b_dev = vp->v_rdev;
1943	VOP_STRATEGY(vp, bp);
1944	return (0);
1945}
1946
1947/*
1948 * Print out the contents of an inode.
1949 */
1950int
1951ufs_print(ap)
1952	struct vop_print_args /* {
1953		struct vnode *a_vp;
1954	} */ *ap;
1955{
1956	register struct vnode *vp = ap->a_vp;
1957	register struct inode *ip = VTOI(vp);
1958
1959	printf("tag VT_UFS, ino %lu, on dev %s (%d, %d)",
1960	    (u_long)ip->i_number, devtoname(ip->i_dev), major(ip->i_dev),
1961	    minor(ip->i_dev));
1962	if (vp->v_type == VFIFO)
1963		fifo_printinfo(vp);
1964	lockmgr_printinfo(&vp->v_lock);
1965	printf("\n");
1966	return (0);
1967}
1968
1969/*
1970 * Read wrapper for special devices.
1971 */
1972int
1973ufsspec_read(ap)
1974	struct vop_read_args /* {
1975		struct vnode *a_vp;
1976		struct uio *a_uio;
1977		int  a_ioflag;
1978		struct ucred *a_cred;
1979	} */ *ap;
1980{
1981	int error, resid;
1982	struct inode *ip;
1983	struct uio *uio;
1984
1985	uio = ap->a_uio;
1986	resid = uio->uio_resid;
1987	error = VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap);
1988	/*
1989	 * The inode may have been revoked during the call, so it must not
1990	 * be accessed blindly here or in the other wrapper functions.
1991	 */
1992	ip = VTOI(ap->a_vp);
1993	if (ip != NULL && (uio->uio_resid != resid || (error == 0 && resid != 0)))
1994		ip->i_flag |= IN_ACCESS;
1995	return (error);
1996}
1997
1998/*
1999 * Write wrapper for special devices.
2000 */
2001int
2002ufsspec_write(ap)
2003	struct vop_write_args /* {
2004		struct vnode *a_vp;
2005		struct uio *a_uio;
2006		int  a_ioflag;
2007		struct ucred *a_cred;
2008	} */ *ap;
2009{
2010	int error, resid;
2011	struct inode *ip;
2012	struct uio *uio;
2013
2014	uio = ap->a_uio;
2015	resid = uio->uio_resid;
2016	error = VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap);
2017	ip = VTOI(ap->a_vp);
2018	if (ip != NULL && (uio->uio_resid != resid || (error == 0 && resid != 0)))
2019		VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
2020	return (error);
2021}
2022
2023/*
2024 * Close wrapper for special devices.
2025 *
2026 * Update the times on the inode then do device close.
2027 */
2028int
2029ufsspec_close(ap)
2030	struct vop_close_args /* {
2031		struct vnode *a_vp;
2032		int  a_fflag;
2033		struct ucred *a_cred;
2034		struct thread *a_td;
2035	} */ *ap;
2036{
2037	struct vnode *vp = ap->a_vp;
2038
2039	mtx_lock(&vp->v_interlock);
2040	if (vp->v_usecount > 1)
2041		ufs_itimes(vp);
2042	mtx_unlock(&vp->v_interlock);
2043	return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
2044}
2045
2046/*
2047 * Read wrapper for fifos.
2048 */
2049int
2050ufsfifo_read(ap)
2051	struct vop_read_args /* {
2052		struct vnode *a_vp;
2053		struct uio *a_uio;
2054		int  a_ioflag;
2055		struct ucred *a_cred;
2056	} */ *ap;
2057{
2058	int error, resid;
2059	struct inode *ip;
2060	struct uio *uio;
2061
2062	uio = ap->a_uio;
2063	resid = uio->uio_resid;
2064	error = VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap);
2065	ip = VTOI(ap->a_vp);
2066	if ((ap->a_vp->v_mount->mnt_flag & MNT_NOATIME) == 0 && ip != NULL &&
2067	    (uio->uio_resid != resid || (error == 0 && resid != 0)))
2068		VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
2069	return (error);
2070}
2071
2072/*
2073 * Write wrapper for fifos.
2074 */
2075int
2076ufsfifo_write(ap)
2077	struct vop_write_args /* {
2078		struct vnode *a_vp;
2079		struct uio *a_uio;
2080		int  a_ioflag;
2081		struct ucred *a_cred;
2082	} */ *ap;
2083{
2084	int error, resid;
2085	struct inode *ip;
2086	struct uio *uio;
2087
2088	uio = ap->a_uio;
2089	resid = uio->uio_resid;
2090	error = VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap);
2091	ip = VTOI(ap->a_vp);
2092	if (ip != NULL && (uio->uio_resid != resid || (error == 0 && resid != 0)))
2093		VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
2094	return (error);
2095}
2096
2097/*
2098 * Close wrapper for fifos.
2099 *
2100 * Update the times on the inode then do device close.
2101 */
2102int
2103ufsfifo_close(ap)
2104	struct vop_close_args /* {
2105		struct vnode *a_vp;
2106		int  a_fflag;
2107		struct ucred *a_cred;
2108		struct thread *a_td;
2109	} */ *ap;
2110{
2111	struct vnode *vp = ap->a_vp;
2112
2113	mtx_lock(&vp->v_interlock);
2114	if (vp->v_usecount > 1)
2115		ufs_itimes(vp);
2116	mtx_unlock(&vp->v_interlock);
2117	return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
2118}
2119
2120/*
2121 * Kqfilter wrapper for fifos.
2122 *
2123 * Fall through to ufs kqfilter routines if needed
2124 */
2125int
2126ufsfifo_kqfilter(ap)
2127	struct vop_kqfilter_args *ap;
2128{
2129	int error;
2130
2131	error = VOCALL(fifo_vnodeop_p, VOFFSET(vop_kqfilter), ap);
2132	if (error)
2133		error = ufs_kqfilter(ap);
2134	return (error);
2135}
2136
2137/*
2138 * Return POSIX pathconf information applicable to ufs filesystems.
2139 */
2140int
2141ufs_pathconf(ap)
2142	struct vop_pathconf_args /* {
2143		struct vnode *a_vp;
2144		int a_name;
2145		int *a_retval;
2146	} */ *ap;
2147{
2148
2149	switch (ap->a_name) {
2150	case _PC_LINK_MAX:
2151		*ap->a_retval = LINK_MAX;
2152		return (0);
2153	case _PC_NAME_MAX:
2154		*ap->a_retval = NAME_MAX;
2155		return (0);
2156	case _PC_PATH_MAX:
2157		*ap->a_retval = PATH_MAX;
2158		return (0);
2159	case _PC_PIPE_BUF:
2160		*ap->a_retval = PIPE_BUF;
2161		return (0);
2162	case _PC_CHOWN_RESTRICTED:
2163		*ap->a_retval = 1;
2164		return (0);
2165	case _PC_NO_TRUNC:
2166		*ap->a_retval = 1;
2167		return (0);
2168	default:
2169		return (EINVAL);
2170	}
2171	/* NOTREACHED */
2172}
2173
2174/*
2175 * Advisory record locking support
2176 */
2177int
2178ufs_advlock(ap)
2179	struct vop_advlock_args /* {
2180		struct vnode *a_vp;
2181		caddr_t  a_id;
2182		int  a_op;
2183		struct flock *a_fl;
2184		int  a_flags;
2185	} */ *ap;
2186{
2187	register struct inode *ip = VTOI(ap->a_vp);
2188
2189	return (lf_advlock(ap, &(ip->i_lockf), ip->i_size));
2190}
2191
2192/*
2193 * Initialize the vnode associated with a new inode, handle aliased
2194 * vnodes.
2195 */
2196int
2197ufs_vinit(mntp, specops, fifoops, vpp)
2198	struct mount *mntp;
2199	vop_t **specops;
2200	vop_t **fifoops;
2201	struct vnode **vpp;
2202{
2203	struct inode *ip;
2204	struct vnode *vp;
2205	struct timeval tv;
2206
2207	vp = *vpp;
2208	ip = VTOI(vp);
2209	switch(vp->v_type = IFTOVT(ip->i_mode)) {
2210	case VCHR:
2211	case VBLK:
2212		vp->v_op = specops;
2213		vp = addaliasu(vp, ip->i_rdev);
2214		ip->i_vnode = vp;
2215		break;
2216	case VFIFO:
2217		vp->v_op = fifoops;
2218		break;
2219	default:
2220		break;
2221
2222	}
2223	if (ip->i_number == ROOTINO)
2224		vp->v_flag |= VROOT;
2225	/*
2226	 * Initialize modrev times
2227	 */
2228	getmicrouptime(&tv);
2229	SETHIGH(ip->i_modrev, tv.tv_sec);
2230	SETLOW(ip->i_modrev, tv.tv_usec * 4294);
2231	*vpp = vp;
2232	return (0);
2233}
2234
2235/*
2236 * Allocate a new inode.
2237 * Vnode dvp must be locked.
2238 */
2239int
2240ufs_makeinode(mode, dvp, vpp, cnp)
2241	int mode;
2242	struct vnode *dvp;
2243	struct vnode **vpp;
2244	struct componentname *cnp;
2245{
2246	register struct inode *ip, *pdir;
2247	struct direct newdir;
2248	struct vnode *tvp;
2249#ifdef UFS_ACL
2250	struct acl *acl;
2251#endif
2252	int error;
2253
2254	pdir = VTOI(dvp);
2255#ifdef DIAGNOSTIC
2256	if ((cnp->cn_flags & HASBUF) == 0)
2257		panic("ufs_makeinode: no name");
2258#endif
2259	*vpp = NULL;
2260	if ((mode & IFMT) == 0)
2261		mode |= IFREG;
2262
2263	error = UFS_VALLOC(dvp, mode, cnp->cn_cred, &tvp);
2264	if (error)
2265		return (error);
2266	ip = VTOI(tvp);
2267	ip->i_gid = pdir->i_gid;
2268#ifdef SUIDDIR
2269	{
2270#ifdef QUOTA
2271		struct ucred ucred, *ucp;
2272		ucp = cnp->cn_cred;
2273#endif
2274		/*
2275		 * If we are not the owner of the directory,
2276		 * and we are hacking owners here, (only do this where told to)
2277		 * and we are not giving it TO root, (would subvert quotas)
2278		 * then go ahead and give it to the other user.
2279		 * Note that this drops off the execute bits for security.
2280		 */
2281		if ((dvp->v_mount->mnt_flag & MNT_SUIDDIR) &&
2282		    (pdir->i_mode & ISUID) &&
2283		    (pdir->i_uid != cnp->cn_cred->cr_uid) && pdir->i_uid) {
2284			ip->i_uid = pdir->i_uid;
2285			mode &= ~07111;
2286#ifdef QUOTA
2287			/*
2288			 * Make sure the correct user gets charged
2289			 * for the space.
2290			 * Quickly knock up a dummy credential for the victim.
2291			 * XXX This seems to never be accessed out of our
2292			 * context so a stack variable is ok.
2293			 */
2294			ucred.cr_ref = 1;
2295			ucred.cr_uid = ip->i_uid;
2296			ucred.cr_ngroups = 1;
2297			ucred.cr_groups[0] = pdir->i_gid;
2298			ucp = &ucred;
2299#endif
2300		} else
2301			ip->i_uid = cnp->cn_cred->cr_uid;
2302
2303#ifdef QUOTA
2304		if ((error = getinoquota(ip)) ||
2305	    	    (error = chkiq(ip, 1, ucp, 0))) {
2306			UFS_VFREE(tvp, ip->i_number, mode);
2307			vput(tvp);
2308			return (error);
2309		}
2310#endif
2311	}
2312#else	/* !SUIDDIR */
2313	ip->i_uid = cnp->cn_cred->cr_uid;
2314#ifdef QUOTA
2315	if ((error = getinoquota(ip)) ||
2316	    (error = chkiq(ip, 1, cnp->cn_cred, 0))) {
2317		UFS_VFREE(tvp, ip->i_number, mode);
2318		vput(tvp);
2319		return (error);
2320	}
2321#endif
2322#endif	/* !SUIDDIR */
2323	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
2324#ifdef UFS_ACL
2325	MALLOC(acl, struct acl *, sizeof(*acl), M_ACL, M_WAITOK);
2326	/*
2327	 * Retrieve default ACL for parent, if any.
2328	 */
2329	error = VOP_GETACL(dvp, ACL_TYPE_DEFAULT, acl, cnp->cn_cred,
2330	    cnp->cn_thread);
2331	switch (error) {
2332	case 0:
2333		/*
2334		 * Retrieved a default ACL, so merge mode and ACL if
2335		 * necessary.
2336		 */
2337		if (acl->acl_cnt != 0) {
2338			/*
2339			 * Two possible ways for default ACL to not be
2340			 * present.  First, the EA can be undefined,
2341			 * or second, the default ACL can be blank.
2342			 * If it's blank, fall through to the it's
2343			 * not defined case.
2344			 */
2345			ip->i_mode = mode;
2346			ufs_sync_acl_from_inode(ip, acl);
2347			break;
2348		}
2349
2350	case EOPNOTSUPP:
2351		/*
2352		 * Just use the mode as-is.
2353		 */
2354		ip->i_mode = mode;
2355		FREE(acl, M_ACL);
2356		acl = NULL;
2357		break;
2358
2359	default:
2360		UFS_VFREE(tvp, ip->i_number, mode);
2361		vput(tvp);
2362		return (error);
2363	}
2364#else /* !UFS_ACL */
2365	ip->i_mode = mode;
2366#endif /* !UFS_ACL */
2367	tvp->v_type = IFTOVT(mode);	/* Rest init'd in getnewvnode(). */
2368	ip->i_effnlink = 1;
2369	ip->i_nlink = 1;
2370	if (DOINGSOFTDEP(tvp))
2371		softdep_change_linkcnt(ip);
2372	if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) &&
2373	    suser_xxx(cnp->cn_cred, NULL, PRISON_ROOT))
2374		ip->i_mode &= ~ISGID;
2375
2376	if (cnp->cn_flags & ISWHITEOUT)
2377		ip->i_flags |= UF_OPAQUE;
2378
2379	/*
2380	 * Make sure inode goes to disk before directory entry.
2381	 */
2382	error = UFS_UPDATE(tvp, !(DOINGSOFTDEP(tvp) | DOINGASYNC(tvp)));
2383	if (error)
2384		goto bad;
2385#ifdef UFS_ACL
2386	if (acl != NULL) {
2387		/*
2388		 * XXX: If we abort now, will Soft Updates notify the extattr
2389		 * code that the EAs for the file need to be released?
2390		 */
2391		error = VOP_SETACL(tvp, ACL_TYPE_ACCESS, acl, cnp->cn_cred,
2392		    cnp->cn_thread);
2393		switch (error) {
2394		case 0:
2395			break;
2396
2397		case EOPNOTSUPP:
2398			/*
2399			 * XXX: This should not happen, as EOPNOTSUPP above was
2400			 * supposed to free acl.
2401			 */
2402			printf("ufs_makeinode: VOP_GETACL() but no "
2403			    "VOP_SETACL()\n");
2404			/* panic("ufs_makeinode: VOP_GETACL() but no "
2405			    "VOP_SETACL()"); */
2406			break;
2407
2408		default:
2409			FREE(acl, M_ACL);
2410			goto bad;
2411		}
2412		FREE(acl, M_ACL);
2413	}
2414#endif /* !UFS_ACL */
2415	ufs_makedirentry(ip, cnp, &newdir);
2416	error = ufs_direnter(dvp, tvp, &newdir, cnp, NULL);
2417	if (error)
2418		goto bad;
2419	*vpp = tvp;
2420	return (0);
2421
2422bad:
2423	/*
2424	 * Write error occurred trying to update the inode
2425	 * or the directory so must deallocate the inode.
2426	 */
2427	ip->i_effnlink = 0;
2428	ip->i_nlink = 0;
2429	ip->i_flag |= IN_CHANGE;
2430	if (DOINGSOFTDEP(tvp))
2431		softdep_change_linkcnt(ip);
2432	vput(tvp);
2433	return (error);
2434}
2435
2436static int
2437ufs_missingop(ap)
2438	struct vop_generic_args *ap;
2439{
2440
2441	panic("no vop function for %s in ufs child", ap->a_desc->vdesc_name);
2442	return (EOPNOTSUPP);
2443}
2444
2445static struct filterops ufsread_filtops =
2446	{ 1, NULL, filt_ufsdetach, filt_ufsread };
2447static struct filterops ufswrite_filtops =
2448	{ 1, NULL, filt_ufsdetach, filt_ufswrite };
2449static struct filterops ufsvnode_filtops =
2450	{ 1, NULL, filt_ufsdetach, filt_ufsvnode };
2451
2452static int
2453ufs_kqfilter(ap)
2454	struct vop_kqfilter_args /* {
2455		struct vnode *a_vp;
2456		struct knote *a_kn;
2457	} */ *ap;
2458{
2459	struct vnode *vp = ap->a_vp;
2460	struct knote *kn = ap->a_kn;
2461
2462	switch (kn->kn_filter) {
2463	case EVFILT_READ:
2464		kn->kn_fop = &ufsread_filtops;
2465		break;
2466	case EVFILT_WRITE:
2467		kn->kn_fop = &ufswrite_filtops;
2468		break;
2469	case EVFILT_VNODE:
2470		kn->kn_fop = &ufsvnode_filtops;
2471		break;
2472	default:
2473		return (1);
2474	}
2475
2476	kn->kn_hook = (caddr_t)vp;
2477
2478	if (vp->v_pollinfo == NULL)
2479		v_addpollinfo(vp);
2480	mtx_lock(&vp->v_pollinfo->vpi_lock);
2481	SLIST_INSERT_HEAD(&vp->v_pollinfo->vpi_selinfo.si_note, kn, kn_selnext);
2482	mtx_unlock(&vp->v_pollinfo->vpi_lock);
2483
2484	return (0);
2485}
2486
2487static void
2488filt_ufsdetach(struct knote *kn)
2489{
2490	struct vnode *vp = (struct vnode *)kn->kn_hook;
2491
2492	KASSERT(vp->v_pollinfo != NULL, ("Mising v_pollinfo"));
2493	mtx_lock(&vp->v_pollinfo->vpi_lock);
2494	SLIST_REMOVE(&vp->v_pollinfo->vpi_selinfo.si_note,
2495	    kn, knote, kn_selnext);
2496	mtx_unlock(&vp->v_pollinfo->vpi_lock);
2497}
2498
2499/*ARGSUSED*/
2500static int
2501filt_ufsread(struct knote *kn, long hint)
2502{
2503	struct vnode *vp = (struct vnode *)kn->kn_hook;
2504	struct inode *ip = VTOI(vp);
2505
2506	/*
2507	 * filesystem is gone, so set the EOF flag and schedule
2508	 * the knote for deletion.
2509	 */
2510	if (hint == NOTE_REVOKE) {
2511		kn->kn_flags |= (EV_EOF | EV_ONESHOT);
2512		return (1);
2513	}
2514
2515        kn->kn_data = ip->i_size - kn->kn_fp->f_offset;
2516        return (kn->kn_data != 0);
2517}
2518
2519/*ARGSUSED*/
2520static int
2521filt_ufswrite(struct knote *kn, long hint)
2522{
2523
2524	/*
2525	 * filesystem is gone, so set the EOF flag and schedule
2526	 * the knote for deletion.
2527	 */
2528	if (hint == NOTE_REVOKE)
2529		kn->kn_flags |= (EV_EOF | EV_ONESHOT);
2530
2531        kn->kn_data = 0;
2532        return (1);
2533}
2534
2535static int
2536filt_ufsvnode(struct knote *kn, long hint)
2537{
2538
2539	if (kn->kn_sfflags & hint)
2540		kn->kn_fflags |= hint;
2541	if (hint == NOTE_REVOKE) {
2542		kn->kn_flags |= EV_EOF;
2543		return (1);
2544	}
2545	return (kn->kn_fflags != 0);
2546}
2547
2548/* Global vfs data structures for ufs. */
2549static vop_t **ufs_vnodeop_p;
2550static struct vnodeopv_entry_desc ufs_vnodeop_entries[] = {
2551	{ &vop_default_desc,		(vop_t *) vop_defaultop },
2552	{ &vop_fsync_desc,		(vop_t *) ufs_missingop },
2553	{ &vop_read_desc,		(vop_t *) ufs_missingop },
2554	{ &vop_reallocblks_desc,	(vop_t *) ufs_missingop },
2555	{ &vop_write_desc,		(vop_t *) ufs_missingop },
2556	{ &vop_access_desc,		(vop_t *) ufs_access },
2557	{ &vop_advlock_desc,		(vop_t *) ufs_advlock },
2558	{ &vop_bmap_desc,		(vop_t *) ufs_bmap },
2559	{ &vop_cachedlookup_desc,	(vop_t *) ufs_lookup },
2560	{ &vop_close_desc,		(vop_t *) ufs_close },
2561	{ &vop_create_desc,		(vop_t *) ufs_create },
2562	{ &vop_getattr_desc,		(vop_t *) ufs_getattr },
2563	{ &vop_inactive_desc,		(vop_t *) ufs_inactive },
2564	{ &vop_islocked_desc,		(vop_t *) vop_stdislocked },
2565	{ &vop_link_desc,		(vop_t *) ufs_link },
2566	{ &vop_lock_desc,		(vop_t *) vop_stdlock },
2567	{ &vop_lookup_desc,		(vop_t *) vfs_cache_lookup },
2568	{ &vop_mkdir_desc,		(vop_t *) ufs_mkdir },
2569	{ &vop_mknod_desc,		(vop_t *) ufs_mknod },
2570	{ &vop_open_desc,		(vop_t *) ufs_open },
2571	{ &vop_pathconf_desc,		(vop_t *) ufs_pathconf },
2572	{ &vop_poll_desc,		(vop_t *) vop_stdpoll },
2573	{ &vop_kqfilter_desc,		(vop_t *) ufs_kqfilter },
2574	{ &vop_getwritemount_desc, 	(vop_t *) vop_stdgetwritemount },
2575	{ &vop_print_desc,		(vop_t *) ufs_print },
2576	{ &vop_readdir_desc,		(vop_t *) ufs_readdir },
2577	{ &vop_readlink_desc,		(vop_t *) ufs_readlink },
2578	{ &vop_reclaim_desc,		(vop_t *) ufs_reclaim },
2579	{ &vop_remove_desc,		(vop_t *) ufs_remove },
2580	{ &vop_rename_desc,		(vop_t *) ufs_rename },
2581	{ &vop_rmdir_desc,		(vop_t *) ufs_rmdir },
2582	{ &vop_setattr_desc,		(vop_t *) ufs_setattr },
2583	{ &vop_strategy_desc,		(vop_t *) ufs_strategy },
2584	{ &vop_symlink_desc,		(vop_t *) ufs_symlink },
2585	{ &vop_unlock_desc,		(vop_t *) vop_stdunlock },
2586	{ &vop_whiteout_desc,		(vop_t *) ufs_whiteout },
2587#ifdef UFS_ACL
2588	{ &vop_getacl_desc,		(vop_t *) ufs_getacl },
2589	{ &vop_setacl_desc,		(vop_t *) ufs_setacl },
2590	{ &vop_aclcheck_desc,		(vop_t *) ufs_aclcheck },
2591#endif
2592	{ NULL, NULL }
2593};
2594static struct vnodeopv_desc ufs_vnodeop_opv_desc =
2595	{ &ufs_vnodeop_p, ufs_vnodeop_entries };
2596
2597static vop_t **ufs_specop_p;
2598static struct vnodeopv_entry_desc ufs_specop_entries[] = {
2599	{ &vop_default_desc,		(vop_t *) spec_vnoperate },
2600	{ &vop_fsync_desc,		(vop_t *) ufs_missingop },
2601	{ &vop_access_desc,		(vop_t *) ufs_access },
2602	{ &vop_close_desc,		(vop_t *) ufsspec_close },
2603	{ &vop_getattr_desc,		(vop_t *) ufs_getattr },
2604	{ &vop_inactive_desc,		(vop_t *) ufs_inactive },
2605	{ &vop_islocked_desc,		(vop_t *) vop_stdislocked },
2606	{ &vop_lock_desc,		(vop_t *) vop_stdlock },
2607	{ &vop_print_desc,		(vop_t *) ufs_print },
2608	{ &vop_read_desc,		(vop_t *) ufsspec_read },
2609	{ &vop_reclaim_desc,		(vop_t *) ufs_reclaim },
2610	{ &vop_setattr_desc,		(vop_t *) ufs_setattr },
2611	{ &vop_unlock_desc,		(vop_t *) vop_stdunlock },
2612	{ &vop_write_desc,		(vop_t *) ufsspec_write },
2613#ifdef UFS_ACL
2614	{ &vop_getacl_desc,		(vop_t *) ufs_getacl },
2615	{ &vop_setacl_desc,		(vop_t *) ufs_setacl },
2616	{ &vop_aclcheck_desc,		(vop_t *) ufs_aclcheck },
2617#endif
2618	{NULL, NULL}
2619};
2620static struct vnodeopv_desc ufs_specop_opv_desc =
2621	{ &ufs_specop_p, ufs_specop_entries };
2622
2623static vop_t **ufs_fifoop_p;
2624static struct vnodeopv_entry_desc ufs_fifoop_entries[] = {
2625	{ &vop_default_desc,		(vop_t *) fifo_vnoperate },
2626	{ &vop_fsync_desc,		(vop_t *) ufs_missingop },
2627	{ &vop_access_desc,		(vop_t *) ufs_access },
2628	{ &vop_close_desc,		(vop_t *) ufsfifo_close },
2629	{ &vop_getattr_desc,		(vop_t *) ufs_getattr },
2630	{ &vop_inactive_desc,		(vop_t *) ufs_inactive },
2631	{ &vop_islocked_desc,		(vop_t *) vop_stdislocked },
2632	{ &vop_kqfilter_desc,		(vop_t *) ufsfifo_kqfilter },
2633	{ &vop_lock_desc,		(vop_t *) vop_stdlock },
2634	{ &vop_print_desc,		(vop_t *) ufs_print },
2635	{ &vop_read_desc,		(vop_t *) ufsfifo_read },
2636	{ &vop_reclaim_desc,		(vop_t *) ufs_reclaim },
2637	{ &vop_setattr_desc,		(vop_t *) ufs_setattr },
2638	{ &vop_unlock_desc,		(vop_t *) vop_stdunlock },
2639	{ &vop_write_desc,		(vop_t *) ufsfifo_write },
2640#ifdef UFS_ACL
2641	{ &vop_getacl_desc,		(vop_t *) ufs_getacl },
2642	{ &vop_setacl_desc,		(vop_t *) ufs_setacl },
2643	{ &vop_aclcheck_desc,		(vop_t *) ufs_aclcheck },
2644#endif
2645	{ NULL, NULL }
2646};
2647static struct vnodeopv_desc ufs_fifoop_opv_desc =
2648	{ &ufs_fifoop_p, ufs_fifoop_entries };
2649
2650VNODEOP_SET(ufs_vnodeop_opv_desc);
2651VNODEOP_SET(ufs_specop_opv_desc);
2652VNODEOP_SET(ufs_fifoop_opv_desc);
2653
2654int
2655ufs_vnoperate(ap)
2656	struct vop_generic_args /* {
2657		struct vnodeop_desc *a_desc;
2658	} */ *ap;
2659{
2660	return (VOCALL(ufs_vnodeop_p, ap->a_desc->vdesc_offset, ap));
2661}
2662
2663int
2664ufs_vnoperatefifo(ap)
2665	struct vop_generic_args /* {
2666		struct vnodeop_desc *a_desc;
2667	} */ *ap;
2668{
2669	return (VOCALL(ufs_fifoop_p, ap->a_desc->vdesc_offset, ap));
2670}
2671
2672int
2673ufs_vnoperatespec(ap)
2674	struct vop_generic_args /* {
2675		struct vnodeop_desc *a_desc;
2676	} */ *ap;
2677{
2678	return (VOCALL(ufs_specop_p, ap->a_desc->vdesc_offset, ap));
2679}
2680