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