ufs_vnops.c revision 24101
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 * $Id: ufs_vnops.c,v 1.47 1997/03/09 06:10:36 mpp Exp $
40 */
41
42#include "opt_quota.h"
43
44#include <sys/param.h>
45#include <sys/systm.h>
46#include <sys/namei.h>
47#include <sys/resourcevar.h>
48#include <sys/kernel.h>
49#include <sys/fcntl.h>
50#include <sys/stat.h>
51#include <sys/buf.h>
52#include <sys/proc.h>
53#include <sys/conf.h>
54#include <sys/mount.h>
55#include <sys/unistd.h>
56#include <sys/vnode.h>
57#include <sys/malloc.h>
58#include <sys/dirent.h>
59#include <sys/lockf.h>
60
61#include <vm/vm.h>
62
63#include <miscfs/specfs/specdev.h>
64#include <miscfs/fifofs/fifo.h>
65
66#include <ufs/ufs/quota.h>
67#include <ufs/ufs/inode.h>
68#include <ufs/ufs/dir.h>
69#include <ufs/ufs/ufsmount.h>
70#include <ufs/ufs/ufs_extern.h>
71
72static int ufs_chmod __P((struct vnode *, int, struct ucred *, struct proc *));
73static int ufs_chown
74	__P((struct vnode *, uid_t, gid_t, struct ucred *, struct proc *));
75
76#ifdef EXT2FS
77#include <gnu/ext2fs/ext2_extern.h>
78#include <gnu/ext2fs/ext2_fs.h>
79#include <gnu/ext2fs/ext2_fs_sb.h>
80#endif /* EXT2FS */
81
82union _qcvt {
83	int64_t qcvt;
84	int32_t val[2];
85};
86#define SETHIGH(q, h) { \
87	union _qcvt tmp; \
88	tmp.qcvt = (q); \
89	tmp.val[_QUAD_HIGHWORD] = (h); \
90	(q) = tmp.qcvt; \
91}
92#define SETLOW(q, l) { \
93	union _qcvt tmp; \
94	tmp.qcvt = (q); \
95	tmp.val[_QUAD_LOWWORD] = (l); \
96	(q) = tmp.qcvt; \
97}
98
99/*
100 * Create a regular file
101 */
102int
103ufs_create(ap)
104	struct vop_create_args /* {
105		struct vnode *a_dvp;
106		struct vnode **a_vpp;
107		struct componentname *a_cnp;
108		struct vattr *a_vap;
109	} */ *ap;
110{
111	int error;
112
113	error =
114	    ufs_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode),
115	    ap->a_dvp, ap->a_vpp, ap->a_cnp);
116	if (error)
117		return (error);
118	return (0);
119}
120
121/*
122 * Mknod vnode call
123 */
124/* ARGSUSED */
125int
126ufs_mknod(ap)
127	struct vop_mknod_args /* {
128		struct vnode *a_dvp;
129		struct vnode **a_vpp;
130		struct componentname *a_cnp;
131		struct vattr *a_vap;
132	} */ *ap;
133{
134	struct vattr *vap = ap->a_vap;
135	struct vnode **vpp = ap->a_vpp;
136	struct inode *ip;
137	int error;
138
139	error = ufs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode),
140	    ap->a_dvp, vpp, ap->a_cnp);
141	if (error)
142		return (error);
143	ip = VTOI(*vpp);
144	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
145	if (vap->va_rdev != VNOVAL) {
146		/*
147		 * Want to be able to use this to make badblock
148		 * inodes, so don't truncate the dev number.
149		 */
150		ip->i_rdev = vap->va_rdev;
151	}
152	/*
153	 * Remove inode so that it will be reloaded by VFS_VGET and
154	 * checked to see if it is an alias of an existing entry in
155	 * the inode cache.
156	 */
157	vput(*vpp);
158	(*vpp)->v_type = VNON;
159	vgone(*vpp);
160	*vpp = 0;
161	return (0);
162}
163
164/*
165 * Open called.
166 *
167 * Nothing to do.
168 */
169/* ARGSUSED */
170int
171ufs_open(ap)
172	struct vop_open_args /* {
173		struct vnode *a_vp;
174		int  a_mode;
175		struct ucred *a_cred;
176		struct proc *a_p;
177	} */ *ap;
178{
179
180	/*
181	 * Files marked append-only must be opened for appending.
182	 */
183	if ((VTOI(ap->a_vp)->i_flags & APPEND) &&
184	    (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE)
185		return (EPERM);
186	return (0);
187}
188
189/*
190 * Close called.
191 *
192 * Update the times on the inode.
193 */
194/* ARGSUSED */
195int
196ufs_close(ap)
197	struct vop_close_args /* {
198		struct vnode *a_vp;
199		int  a_fflag;
200		struct ucred *a_cred;
201		struct proc *a_p;
202	} */ *ap;
203{
204	register struct vnode *vp = ap->a_vp;
205	register struct inode *ip = VTOI(vp);
206
207	simple_lock(&vp->v_interlock);
208	if (vp->v_usecount > 1)
209		ITIMES(ip, &time, &time);
210	simple_unlock(&vp->v_interlock);
211	return (0);
212}
213
214int
215ufs_access(ap)
216	struct vop_access_args /* {
217		struct vnode *a_vp;
218		int  a_mode;
219		struct ucred *a_cred;
220		struct proc *a_p;
221	} */ *ap;
222{
223	struct vnode *vp = ap->a_vp;
224	struct inode *ip = VTOI(vp);
225	struct ucred *cred = ap->a_cred;
226	mode_t mask, mode = ap->a_mode;
227	register gid_t *gp;
228	int i;
229#ifdef QUOTA
230	int error;
231#endif
232
233	/*
234	 * Disallow write attempts on read-only file systems;
235	 * unless the file is a socket, fifo, or a block or
236	 * character device resident on the file system.
237	 */
238	if (mode & VWRITE) {
239		switch (vp->v_type) {
240		case VDIR:
241		case VLNK:
242		case VREG:
243			if (vp->v_mount->mnt_flag & MNT_RDONLY)
244				return (EROFS);
245#ifdef QUOTA
246			if (error = getinoquota(ip))
247				return (error);
248#endif
249			break;
250		}
251	}
252
253	/* If immutable bit set, nobody gets to write it. */
254	if ((mode & VWRITE) && (ip->i_flags & IMMUTABLE))
255		return (EPERM);
256
257	/* Otherwise, user id 0 always gets access. */
258	if (cred->cr_uid == 0)
259		return (0);
260
261	mask = 0;
262
263	/* Otherwise, check the owner. */
264	if (cred->cr_uid == ip->i_uid) {
265		if (mode & VEXEC)
266			mask |= S_IXUSR;
267		if (mode & VREAD)
268			mask |= S_IRUSR;
269		if (mode & VWRITE)
270			mask |= S_IWUSR;
271		return ((ip->i_mode & mask) == mask ? 0 : EACCES);
272	}
273
274	/* Otherwise, check the groups. */
275	for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
276		if (ip->i_gid == *gp) {
277			if (mode & VEXEC)
278				mask |= S_IXGRP;
279			if (mode & VREAD)
280				mask |= S_IRGRP;
281			if (mode & VWRITE)
282				mask |= S_IWGRP;
283			return ((ip->i_mode & mask) == mask ? 0 : EACCES);
284		}
285
286	/* Otherwise, check everyone else. */
287	if (mode & VEXEC)
288		mask |= S_IXOTH;
289	if (mode & VREAD)
290		mask |= S_IROTH;
291	if (mode & VWRITE)
292		mask |= S_IWOTH;
293	return ((ip->i_mode & mask) == mask ? 0 : EACCES);
294}
295
296/* ARGSUSED */
297int
298ufs_getattr(ap)
299	struct vop_getattr_args /* {
300		struct vnode *a_vp;
301		struct vattr *a_vap;
302		struct ucred *a_cred;
303		struct proc *a_p;
304	} */ *ap;
305{
306	register struct vnode *vp = ap->a_vp;
307	register struct inode *ip = VTOI(vp);
308	register struct vattr *vap = ap->a_vap;
309
310	ITIMES(ip, &time, &time);
311	/*
312	 * Copy from inode table
313	 */
314	vap->va_fsid = ip->i_dev;
315	vap->va_fileid = ip->i_number;
316	vap->va_mode = ip->i_mode & ~IFMT;
317	vap->va_nlink = ip->i_nlink;
318	vap->va_uid = ip->i_uid;
319	vap->va_gid = ip->i_gid;
320	vap->va_rdev = (dev_t)ip->i_rdev;
321	vap->va_size = ip->i_din.di_size;
322	vap->va_atime.tv_sec = ip->i_atime;
323	vap->va_atime.tv_nsec = ip->i_atimensec;
324	vap->va_mtime.tv_sec = ip->i_mtime;
325	vap->va_mtime.tv_nsec = ip->i_mtimensec;
326	vap->va_ctime.tv_sec = ip->i_ctime;
327	vap->va_ctime.tv_nsec = ip->i_ctimensec;
328	vap->va_flags = ip->i_flags;
329	vap->va_gen = ip->i_gen;
330	/* this doesn't belong here */
331	if (vp->v_type == VBLK)
332		vap->va_blocksize = BLKDEV_IOSIZE;
333	else if (vp->v_type == VCHR)
334		vap->va_blocksize = MAXBSIZE;
335	else
336		vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize;
337	vap->va_bytes = dbtob((u_quad_t)ip->i_blocks);
338	vap->va_type = vp->v_type;
339	vap->va_filerev = ip->i_modrev;
340	return (0);
341}
342
343/*
344 * Set attribute vnode op. called from several syscalls
345 */
346int
347ufs_setattr(ap)
348	struct vop_setattr_args /* {
349		struct vnode *a_vp;
350		struct vattr *a_vap;
351		struct ucred *a_cred;
352		struct proc *a_p;
353	} */ *ap;
354{
355	struct vattr *vap = ap->a_vap;
356	struct vnode *vp = ap->a_vp;
357	struct inode *ip = VTOI(vp);
358	struct ucred *cred = ap->a_cred;
359	struct proc *p = ap->a_p;
360	struct timeval atimeval, mtimeval;
361	int error;
362
363	/*
364	 * Check for unsettable attributes.
365	 */
366	if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
367	    (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
368	    (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
369	    ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
370		return (EINVAL);
371	}
372	if (vap->va_flags != VNOVAL) {
373		if (vp->v_mount->mnt_flag & MNT_RDONLY)
374			return (EROFS);
375		if (cred->cr_uid != ip->i_uid &&
376		    (error = suser(cred, &p->p_acflag)))
377			return (error);
378		if (cred->cr_uid == 0) {
379			if ((ip->i_flags & (SF_IMMUTABLE | SF_APPEND)) &&
380			    securelevel > 0)
381				return (EPERM);
382			ip->i_flags = vap->va_flags;
383		} else {
384			if (ip->i_flags & (SF_IMMUTABLE | SF_APPEND) ||
385			    (vap->va_flags & UF_SETTABLE) != vap->va_flags)
386				return (EPERM);
387			ip->i_flags &= SF_SETTABLE;
388			ip->i_flags |= (vap->va_flags & UF_SETTABLE);
389		}
390		ip->i_flag |= IN_CHANGE;
391		if (vap->va_flags & (IMMUTABLE | APPEND))
392			return (0);
393	}
394	if (ip->i_flags & (IMMUTABLE | APPEND))
395		return (EPERM);
396	/*
397	 * Go through the fields and update iff not VNOVAL.
398	 */
399	if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
400		if (vp->v_mount->mnt_flag & MNT_RDONLY)
401			return (EROFS);
402		if (error = ufs_chown(vp, vap->va_uid, vap->va_gid, cred, p))
403			return (error);
404	}
405	if (vap->va_size != VNOVAL) {
406		/*
407		 * Disallow write attempts on read-only file systems;
408		 * unless the file is a socket, fifo, or a block or
409		 * character device resident on the file system.
410		 */
411		switch (vp->v_type) {
412		case VDIR:
413			return (EISDIR);
414		case VLNK:
415		case VREG:
416			if (vp->v_mount->mnt_flag & MNT_RDONLY)
417				return (EROFS);
418			break;
419		}
420		if (error = VOP_TRUNCATE(vp, vap->va_size, 0, cred, p))
421			return (error);
422	}
423	ip = VTOI(vp);
424	if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
425		if (vp->v_mount->mnt_flag & MNT_RDONLY)
426			return (EROFS);
427		if (cred->cr_uid != ip->i_uid &&
428		    (error = suser(cred, &p->p_acflag)) &&
429		    ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
430		    (error = VOP_ACCESS(vp, VWRITE, cred, p))))
431			return (error);
432		if (vap->va_atime.tv_sec != VNOVAL)
433			ip->i_flag |= IN_ACCESS;
434		if (vap->va_mtime.tv_sec != VNOVAL)
435			ip->i_flag |= IN_CHANGE | IN_UPDATE;
436		atimeval.tv_sec = vap->va_atime.tv_sec;
437		atimeval.tv_usec = vap->va_atime.tv_nsec / 1000;
438		mtimeval.tv_sec = vap->va_mtime.tv_sec;
439		mtimeval.tv_usec = vap->va_mtime.tv_nsec / 1000;
440		error = VOP_UPDATE(vp, &atimeval, &mtimeval, 1);
441		if (error)
442			return (error);
443	}
444	error = 0;
445	if (vap->va_mode != (mode_t)VNOVAL) {
446		if (vp->v_mount->mnt_flag & MNT_RDONLY)
447			return (EROFS);
448		error = ufs_chmod(vp, (int)vap->va_mode, cred, p);
449	}
450	return (error);
451}
452
453/*
454 * Change the mode on a file.
455 * Inode must be locked before calling.
456 */
457static int
458ufs_chmod(vp, mode, cred, p)
459	register struct vnode *vp;
460	register int mode;
461	register struct ucred *cred;
462	struct proc *p;
463{
464	register struct inode *ip = VTOI(vp);
465	int error;
466
467	if (cred->cr_uid != ip->i_uid) {
468	    error = suser(cred, &p->p_acflag);
469	    if (error)
470		return (error);
471	}
472	if (cred->cr_uid) {
473		if (vp->v_type != VDIR && (mode & S_ISTXT))
474			return (EFTYPE);
475		if (!groupmember(ip->i_gid, cred) && (mode & ISGID))
476			return (EPERM);
477	}
478	ip->i_mode &= ~ALLPERMS;
479	ip->i_mode |= (mode & ALLPERMS);
480	ip->i_flag |= IN_CHANGE;
481	return (0);
482}
483
484/*
485 * Perform chown operation on inode ip;
486 * inode must be locked prior to call.
487 */
488static int
489ufs_chown(vp, uid, gid, cred, p)
490	register struct vnode *vp;
491	uid_t uid;
492	gid_t gid;
493	struct ucred *cred;
494	struct proc *p;
495{
496	register struct inode *ip = VTOI(vp);
497	uid_t ouid;
498	gid_t ogid;
499	int error = 0;
500#ifdef QUOTA
501	register int i;
502	long change;
503#endif
504
505	if (uid == (uid_t)VNOVAL)
506		uid = ip->i_uid;
507	if (gid == (gid_t)VNOVAL)
508		gid = ip->i_gid;
509	/*
510	 * If we don't own the file, are trying to change the owner
511	 * of the file, or are not a member of the target group,
512	 * the caller must be superuser or the call fails.
513	 */
514	if ((cred->cr_uid != ip->i_uid || uid != ip->i_uid ||
515	    (gid != ip->i_gid && !groupmember((gid_t)gid, cred))) &&
516	    (error = suser(cred, &p->p_acflag)))
517		return (error);
518	ogid = ip->i_gid;
519	ouid = ip->i_uid;
520#ifdef QUOTA
521	if (error = getinoquota(ip))
522		return (error);
523	if (ouid == uid) {
524		dqrele(vp, ip->i_dquot[USRQUOTA]);
525		ip->i_dquot[USRQUOTA] = NODQUOT;
526	}
527	if (ogid == gid) {
528		dqrele(vp, ip->i_dquot[GRPQUOTA]);
529		ip->i_dquot[GRPQUOTA] = NODQUOT;
530	}
531	change = ip->i_blocks;
532	(void) chkdq(ip, -change, cred, CHOWN);
533	(void) chkiq(ip, -1, cred, CHOWN);
534	for (i = 0; i < MAXQUOTAS; i++) {
535		dqrele(vp, ip->i_dquot[i]);
536		ip->i_dquot[i] = NODQUOT;
537	}
538#endif
539	ip->i_gid = gid;
540	ip->i_uid = uid;
541#ifdef QUOTA
542	if ((error = getinoquota(ip)) == 0) {
543		if (ouid == uid) {
544			dqrele(vp, ip->i_dquot[USRQUOTA]);
545			ip->i_dquot[USRQUOTA] = NODQUOT;
546		}
547		if (ogid == gid) {
548			dqrele(vp, ip->i_dquot[GRPQUOTA]);
549			ip->i_dquot[GRPQUOTA] = NODQUOT;
550		}
551		if ((error = chkdq(ip, change, cred, CHOWN)) == 0) {
552			if ((error = chkiq(ip, 1, cred, CHOWN)) == 0)
553				goto good;
554			else
555				(void) chkdq(ip, -change, cred, CHOWN|FORCE);
556		}
557		for (i = 0; i < MAXQUOTAS; i++) {
558			dqrele(vp, ip->i_dquot[i]);
559			ip->i_dquot[i] = NODQUOT;
560		}
561	}
562	ip->i_gid = ogid;
563	ip->i_uid = ouid;
564	if (getinoquota(ip) == 0) {
565		if (ouid == uid) {
566			dqrele(vp, ip->i_dquot[USRQUOTA]);
567			ip->i_dquot[USRQUOTA] = NODQUOT;
568		}
569		if (ogid == gid) {
570			dqrele(vp, ip->i_dquot[GRPQUOTA]);
571			ip->i_dquot[GRPQUOTA] = NODQUOT;
572		}
573		(void) chkdq(ip, change, cred, FORCE|CHOWN);
574		(void) chkiq(ip, 1, cred, FORCE|CHOWN);
575		(void) getinoquota(ip);
576	}
577	return (error);
578good:
579	if (getinoquota(ip))
580		panic("ufs_chown: lost quota");
581#endif /* QUOTA */
582	if (ouid != uid || ogid != gid)
583		ip->i_flag |= IN_CHANGE;
584	if (ouid != uid && cred->cr_uid != 0)
585		ip->i_mode &= ~ISUID;
586	if (ogid != gid && cred->cr_uid != 0)
587		ip->i_mode &= ~ISGID;
588	return (0);
589}
590
591/* ARGSUSED */
592int
593ufs_ioctl(ap)
594	struct vop_ioctl_args /* {
595		struct vnode *a_vp;
596		int  a_command;
597		caddr_t  a_data;
598		int  a_fflag;
599		struct ucred *a_cred;
600		struct proc *a_p;
601	} */ *ap;
602{
603
604	return (ENOTTY);
605}
606
607/* ARGSUSED */
608int
609ufs_select(ap)
610	struct vop_select_args /* {
611		struct vnode *a_vp;
612		int  a_which;
613		int  a_fflags;
614		struct ucred *a_cred;
615		struct proc *a_p;
616	} */ *ap;
617{
618
619	/*
620	 * We should really check to see if I/O is possible.
621	 */
622	return (1);
623}
624
625/*
626 * Mmap a file
627 *
628 * NB Currently unsupported.
629 */
630/* ARGSUSED */
631int
632ufs_mmap(ap)
633	struct vop_mmap_args /* {
634		struct vnode *a_vp;
635		int  a_fflags;
636		struct ucred *a_cred;
637		struct proc *a_p;
638	} */ *ap;
639{
640
641	return (EINVAL);
642}
643
644/*
645 * Seek on a file
646 *
647 * Nothing to do, so just return.
648 */
649/* ARGSUSED */
650int
651ufs_seek(ap)
652	struct vop_seek_args /* {
653		struct vnode *a_vp;
654		off_t  a_oldoff;
655		off_t  a_newoff;
656		struct ucred *a_cred;
657	} */ *ap;
658{
659
660	return (0);
661}
662
663int
664ufs_remove(ap)
665	struct vop_remove_args /* {
666		struct vnode *a_dvp;
667		struct vnode *a_vp;
668		struct componentname *a_cnp;
669	} */ *ap;
670{
671	struct inode *ip;
672	struct vnode *vp = ap->a_vp;
673	struct vnode *dvp = ap->a_dvp;
674	int error;
675
676	ip = VTOI(vp);
677	if ((ip->i_flags & (IMMUTABLE | APPEND)) ||
678	    (VTOI(dvp)->i_flags & APPEND)) {
679		error = EPERM;
680		goto out;
681	}
682#ifdef EXT2FS
683	if (IS_EXT2_VNODE(dvp)) {
684		error = ext2_dirremove(dvp, ap->a_cnp);
685	} else {
686		error = ufs_dirremove(dvp, ap->a_cnp);
687	}
688#else
689	error = ufs_dirremove(dvp, ap->a_cnp);
690#endif /* EXT2FS */
691	if (error == 0) {
692		ip->i_nlink--;
693		ip->i_flag |= IN_CHANGE;
694	}
695out:
696	if (dvp == vp)
697		vrele(vp);
698	else
699		vput(vp);
700	vput(dvp);
701	return (error);
702}
703
704/*
705 * link vnode call
706 */
707int
708ufs_link(ap)
709	struct vop_link_args /* {
710		struct vnode *a_tdvp;
711		struct vnode *a_vp;
712		struct componentname *a_cnp;
713	} */ *ap;
714{
715	struct vnode *vp = ap->a_vp;
716	struct vnode *tdvp = ap->a_tdvp;
717	struct componentname *cnp = ap->a_cnp;
718	struct proc *p = cnp->cn_proc;
719	struct inode *ip;
720	struct timeval tv;
721	int error;
722
723#ifdef DIAGNOSTIC
724	if ((cnp->cn_flags & HASBUF) == 0)
725		panic("ufs_link: no name");
726#endif
727	if (tdvp->v_mount != vp->v_mount) {
728		VOP_ABORTOP(tdvp, cnp);
729		error = EXDEV;
730		goto out2;
731	}
732	if (tdvp != vp && (error = vn_lock(vp, LK_EXCLUSIVE, p))) {
733		VOP_ABORTOP(tdvp, cnp);
734		goto out2;
735	}
736	ip = VTOI(vp);
737	if ((nlink_t)ip->i_nlink >= LINK_MAX) {
738		VOP_ABORTOP(tdvp, cnp);
739		error = EMLINK;
740		goto out1;
741	}
742	if (ip->i_flags & (IMMUTABLE | APPEND)) {
743		VOP_ABORTOP(tdvp, cnp);
744		error = EPERM;
745		goto out1;
746	}
747	ip->i_nlink++;
748	ip->i_flag |= IN_CHANGE;
749	gettime(&tv);
750	error = VOP_UPDATE(vp, &tv, &tv, 1);
751	if (!error) {
752#ifdef EXT2FS
753		if (IS_EXT2_VNODE(tdvp)) {
754			error = ext2_direnter(ip, tdvp, cnp);
755		} else {
756			error = ufs_direnter(ip, tdvp, cnp);
757		}
758#else
759		error = ufs_direnter(ip, tdvp, cnp);
760#endif /* EXT2FS */
761	}
762
763	if (error) {
764		ip->i_nlink--;
765		ip->i_flag |= IN_CHANGE;
766	}
767	FREE(cnp->cn_pnbuf, M_NAMEI);
768out1:
769	if (tdvp != vp)
770		VOP_UNLOCK(vp, 0, p);
771out2:
772	vput(tdvp);
773	return (error);
774}
775
776/*
777 * whiteout vnode call
778 */
779int
780ufs_whiteout(ap)
781	struct vop_whiteout_args /* {
782		struct vnode *a_dvp;
783		struct componentname *a_cnp;
784		int a_flags;
785	} */ *ap;
786{
787	struct vnode *dvp = ap->a_dvp;
788	struct componentname *cnp = ap->a_cnp;
789	struct direct newdir;
790	int error = 0;
791
792	switch (ap->a_flags) {
793	case LOOKUP:
794		/* 4.4 format directories support whiteout operations */
795		if (dvp->v_mount->mnt_maxsymlinklen > 0)
796			return (0);
797		return (EOPNOTSUPP);
798
799	case CREATE:
800		/* create a new directory whiteout */
801#ifdef DIAGNOSTIC
802		if ((cnp->cn_flags & SAVENAME) == 0)
803			panic("ufs_whiteout: missing name");
804		if (dvp->v_mount->mnt_maxsymlinklen <= 0)
805			panic("ufs_whiteout: old format filesystem");
806#endif
807
808		newdir.d_ino = WINO;
809		newdir.d_namlen = cnp->cn_namelen;
810		bcopy(cnp->cn_nameptr, newdir.d_name, (unsigned)cnp->cn_namelen + 1);
811		newdir.d_type = DT_WHT;
812		error = ufs_direnter2(dvp, &newdir, cnp->cn_cred, cnp->cn_proc);
813		break;
814
815	case DELETE:
816		/* remove an existing directory whiteout */
817#ifdef DIAGNOSTIC
818		if (dvp->v_mount->mnt_maxsymlinklen <= 0)
819			panic("ufs_whiteout: old format filesystem");
820#endif
821
822		cnp->cn_flags &= ~DOWHITEOUT;
823		error = ufs_dirremove(dvp, cnp);
824		break;
825	}
826	if (cnp->cn_flags & HASBUF) {
827		FREE(cnp->cn_pnbuf, M_NAMEI);
828		cnp->cn_flags &= ~HASBUF;
829	}
830	return (error);
831}
832
833/*
834 * Rename system call.
835 * 	rename("foo", "bar");
836 * is essentially
837 *	unlink("bar");
838 *	link("foo", "bar");
839 *	unlink("foo");
840 * but ``atomically''.  Can't do full commit without saving state in the
841 * inode on disk which isn't feasible at this time.  Best we can do is
842 * always guarantee the target exists.
843 *
844 * Basic algorithm is:
845 *
846 * 1) Bump link count on source while we're linking it to the
847 *    target.  This also ensure the inode won't be deleted out
848 *    from underneath us while we work (it may be truncated by
849 *    a concurrent `trunc' or `open' for creation).
850 * 2) Link source to destination.  If destination already exists,
851 *    delete it first.
852 * 3) Unlink source reference to inode if still around. If a
853 *    directory was moved and the parent of the destination
854 *    is different from the source, patch the ".." entry in the
855 *    directory.
856 */
857int
858ufs_rename(ap)
859	struct vop_rename_args  /* {
860		struct vnode *a_fdvp;
861		struct vnode *a_fvp;
862		struct componentname *a_fcnp;
863		struct vnode *a_tdvp;
864		struct vnode *a_tvp;
865		struct componentname *a_tcnp;
866	} */ *ap;
867{
868	struct vnode *tvp = ap->a_tvp;
869	register struct vnode *tdvp = ap->a_tdvp;
870	struct vnode *fvp = ap->a_fvp;
871	struct vnode *fdvp = ap->a_fdvp;
872	struct componentname *tcnp = ap->a_tcnp;
873	struct componentname *fcnp = ap->a_fcnp;
874	struct proc *p = fcnp->cn_proc;
875	struct inode *ip, *xp, *dp;
876	struct dirtemplate dirbuf;
877	struct timeval tv;
878	int doingdirectory = 0, oldparent = 0, newparent = 0;
879	int error = 0;
880	u_char namlen;
881
882#ifdef DIAGNOSTIC
883	if ((tcnp->cn_flags & HASBUF) == 0 ||
884	    (fcnp->cn_flags & HASBUF) == 0)
885		panic("ufs_rename: no name");
886#endif
887	/*
888	 * Check for cross-device rename.
889	 */
890	if ((fvp->v_mount != tdvp->v_mount) ||
891	    (tvp && (fvp->v_mount != tvp->v_mount))) {
892		error = EXDEV;
893abortit:
894		VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
895		if (tdvp == tvp)
896			vrele(tdvp);
897		else
898			vput(tdvp);
899		if (tvp)
900			vput(tvp);
901		VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
902		vrele(fdvp);
903		vrele(fvp);
904		return (error);
905	}
906
907	if (tvp && ((VTOI(tvp)->i_flags & (IMMUTABLE | APPEND)) ||
908	    (VTOI(tdvp)->i_flags & APPEND))) {
909		error = EPERM;
910		goto abortit;
911	}
912
913	/*
914	 * Check if just deleting a link name or if we've lost a race.
915	 * If another process completes the same rename after we've looked
916	 * up the source and have blocked looking up the target, then the
917	 * source and target inodes may be identical now although the
918	 * names were never linked.
919	 */
920	if (fvp == tvp) {
921		if (fvp->v_type == VDIR) {
922			/*
923			 * Linked directories are impossible, so we must
924			 * have lost the race.  Pretend that the rename
925			 * completed before the lookup.
926			 */
927#ifdef UFS_RENAME_DEBUG
928			printf("ufs_rename: fvp == tvp for directories\n");
929#endif
930			error = ENOENT;
931			goto abortit;
932		}
933
934		/* Release destination completely. */
935		VOP_ABORTOP(tdvp, tcnp);
936		vput(tdvp);
937		vput(tvp);
938
939		/*
940		 * Delete source.  There is another race now that everything
941		 * is unlocked, but this doesn't cause any new complications.
942		 * Relookup() may find a file that is unrelated to the
943		 * original one, or it may fail.  Too bad.
944		 */
945		vrele(fdvp);
946		vrele(fvp);
947		fcnp->cn_flags &= ~MODMASK;
948		fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
949		if ((fcnp->cn_flags & SAVESTART) == 0)
950			panic("ufs_rename: lost from startdir");
951		fcnp->cn_nameiop = DELETE;
952		VREF(fdvp);
953		error = relookup(fdvp, &fvp, fcnp);
954		if (error == 0)
955			vrele(fdvp);
956		if (fvp == NULL) {
957#ifdef UFS_RENAME_DEBUG
958			printf("ufs_rename: from name disappeared\n");
959#endif
960			return (ENOENT);
961		}
962		return (VOP_REMOVE(fdvp, fvp, fcnp));
963	}
964	if (error = vn_lock(fvp, LK_EXCLUSIVE, p))
965		goto abortit;
966	dp = VTOI(fdvp);
967	ip = VTOI(fvp);
968	if ((ip->i_flags & (IMMUTABLE | APPEND)) || (dp->i_flags & APPEND)) {
969		VOP_UNLOCK(fvp, 0, p);
970		error = EPERM;
971		goto abortit;
972	}
973	if ((ip->i_mode & IFMT) == IFDIR) {
974		/*
975		 * Avoid ".", "..", and aliases of "." for obvious reasons.
976		 */
977		if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') ||
978		    dp == ip || (fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT ||
979		    (ip->i_flag & IN_RENAME)) {
980			VOP_UNLOCK(fvp, 0, p);
981			error = EINVAL;
982			goto abortit;
983		}
984		ip->i_flag |= IN_RENAME;
985		oldparent = dp->i_number;
986		doingdirectory++;
987	}
988	vrele(fdvp);
989
990	/*
991	 * When the target exists, both the directory
992	 * and target vnodes are returned locked.
993	 */
994	dp = VTOI(tdvp);
995	xp = NULL;
996	if (tvp)
997		xp = VTOI(tvp);
998
999	/*
1000	 * 1) Bump link count while we're moving stuff
1001	 *    around.  If we crash somewhere before
1002	 *    completing our work, the link count
1003	 *    may be wrong, but correctable.
1004	 */
1005	ip->i_nlink++;
1006	ip->i_flag |= IN_CHANGE;
1007	gettime(&tv);
1008	if (error = VOP_UPDATE(fvp, &tv, &tv, 1)) {
1009		VOP_UNLOCK(fvp, 0, p);
1010		goto bad;
1011	}
1012
1013	/*
1014	 * If ".." must be changed (ie the directory gets a new
1015	 * parent) then the source directory must not be in the
1016	 * directory heirarchy above the target, as this would
1017	 * orphan everything below the source directory. Also
1018	 * the user must have write permission in the source so
1019	 * as to be able to change "..". We must repeat the call
1020	 * to namei, as the parent directory is unlocked by the
1021	 * call to checkpath().
1022	 */
1023	error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_proc);
1024	VOP_UNLOCK(fvp, 0, p);
1025	if (oldparent != dp->i_number)
1026		newparent = dp->i_number;
1027	if (doingdirectory && newparent) {
1028		if (error)	/* write access check above */
1029			goto bad;
1030		if (xp != NULL)
1031			vput(tvp);
1032#ifdef EXT2FS
1033		if (IS_EXT2_VNODE(tdvp)) {
1034			error = ext2_checkpath(ip, dp, tcnp->cn_cred);
1035		} else {
1036			error = ufs_checkpath(ip, dp, tcnp->cn_cred);
1037		}
1038#else
1039		error = ufs_checkpath(ip, dp, tcnp->cn_cred);
1040#endif /* EXT2FS */
1041		if (error)
1042			goto out;
1043		if ((tcnp->cn_flags & SAVESTART) == 0)
1044			panic("ufs_rename: lost to startdir");
1045		VREF(tdvp);
1046		error = relookup(tdvp, &tvp, tcnp);
1047		if (error)
1048			goto out;
1049		vrele(tdvp);
1050		dp = VTOI(tdvp);
1051		xp = NULL;
1052		if (tvp)
1053			xp = VTOI(tvp);
1054	}
1055	/*
1056	 * 2) If target doesn't exist, link the target
1057	 *    to the source and unlink the source.
1058	 *    Otherwise, rewrite the target directory
1059	 *    entry to reference the source inode and
1060	 *    expunge the original entry's existence.
1061	 */
1062	if (xp == NULL) {
1063		if (dp->i_dev != ip->i_dev)
1064			panic("ufs_rename: EXDEV");
1065		/*
1066		 * Account for ".." in new directory.
1067		 * When source and destination have the same
1068		 * parent we don't fool with the link count.
1069		 */
1070		if (doingdirectory && newparent) {
1071			if ((nlink_t)dp->i_nlink >= LINK_MAX) {
1072				error = EMLINK;
1073				goto bad;
1074			}
1075			dp->i_nlink++;
1076			dp->i_flag |= IN_CHANGE;
1077			error = VOP_UPDATE(tdvp, &tv, &tv, 1);
1078			if (error)
1079				goto bad;
1080		}
1081#ifdef EXT2FS
1082		if (IS_EXT2_VNODE(tdvp)) {
1083			error = ext2_direnter(ip, tdvp, tcnp);
1084		} else {
1085			error = ufs_direnter(ip, tdvp, tcnp);
1086		}
1087#else
1088		error = ufs_direnter(ip, tdvp, tcnp);
1089#endif /* EXT2FS */
1090		if (error) {
1091			if (doingdirectory && newparent) {
1092				dp->i_nlink--;
1093				dp->i_flag |= IN_CHANGE;
1094				(void)VOP_UPDATE(tdvp, &tv, &tv, 1);
1095			}
1096			goto bad;
1097		}
1098		vput(tdvp);
1099	} else {
1100		if (xp->i_dev != dp->i_dev || xp->i_dev != ip->i_dev)
1101			panic("ufs_rename: EXDEV");
1102		/*
1103		 * Short circuit rename(foo, foo).
1104		 */
1105		if (xp->i_number == ip->i_number)
1106			panic("ufs_rename: same file");
1107		/*
1108		 * If the parent directory is "sticky", then the user must
1109		 * own the parent directory, or the destination of the rename,
1110		 * otherwise the destination may not be changed (except by
1111		 * root). This implements append-only directories.
1112		 */
1113		if ((dp->i_mode & S_ISTXT) && tcnp->cn_cred->cr_uid != 0 &&
1114		    tcnp->cn_cred->cr_uid != dp->i_uid &&
1115		    xp->i_uid != tcnp->cn_cred->cr_uid) {
1116			error = EPERM;
1117			goto bad;
1118		}
1119		/*
1120		 * Target must be empty if a directory and have no links
1121		 * to it. Also, ensure source and target are compatible
1122		 * (both directories, or both not directories).
1123		 */
1124		if ((xp->i_mode&IFMT) == IFDIR) {
1125#ifdef EXT2FS
1126			if (! (IS_EXT2_VNODE(ITOV(xp)) ?
1127					ext2_dirempty : ufs_dirempty)
1128#else
1129			if (! ufs_dirempty
1130#endif /* EXT2FS */
1131					 (xp, dp->i_number, tcnp->cn_cred) ||
1132			    xp->i_nlink > 2) {
1133				error = ENOTEMPTY;
1134				goto bad;
1135			}
1136			if (!doingdirectory) {
1137				error = ENOTDIR;
1138				goto bad;
1139			}
1140			cache_purge(tdvp);
1141		} else if (doingdirectory) {
1142			error = EISDIR;
1143			goto bad;
1144		}
1145#ifdef EXT2FS
1146		if (IS_EXT2_VNODE(ITOV(dp))) {
1147			error = ext2_dirrewrite(dp, ip, tcnp);
1148		} else {
1149			error = ufs_dirrewrite(dp, ip, tcnp);
1150		}
1151#else
1152		error = ufs_dirrewrite(dp, ip, tcnp);
1153#endif /* EXT2FS */
1154		if (error)
1155			goto bad;
1156		/*
1157		 * If the target directory is in the same
1158		 * directory as the source directory,
1159		 * decrement the link count on the parent
1160		 * of the target directory.
1161		 */
1162		 if (doingdirectory && !newparent) {
1163			dp->i_nlink--;
1164			dp->i_flag |= IN_CHANGE;
1165		}
1166		vput(tdvp);
1167		/*
1168		 * Adjust the link count of the target to
1169		 * reflect the dirrewrite above.  If this is
1170		 * a directory it is empty and there are
1171		 * no links to it, so we can squash the inode and
1172		 * any space associated with it.  We disallowed
1173		 * renaming over top of a directory with links to
1174		 * it above, as the remaining link would point to
1175		 * a directory without "." or ".." entries.
1176		 */
1177		xp->i_nlink--;
1178		if (doingdirectory) {
1179			if (--xp->i_nlink != 0)
1180				panic("ufs_rename: linked directory");
1181			error = VOP_TRUNCATE(tvp, (off_t)0, IO_SYNC,
1182			    tcnp->cn_cred, tcnp->cn_proc);
1183		}
1184		xp->i_flag |= IN_CHANGE;
1185		vput(tvp);
1186		xp = NULL;
1187	}
1188
1189	/*
1190	 * 3) Unlink the source.
1191	 */
1192	fcnp->cn_flags &= ~MODMASK;
1193	fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
1194	if ((fcnp->cn_flags & SAVESTART) == 0)
1195		panic("ufs_rename: lost from startdir");
1196	VREF(fdvp);
1197	error = relookup(fdvp, &fvp, fcnp);
1198	if (error == 0)
1199		vrele(fdvp);
1200	if (fvp != NULL) {
1201		xp = VTOI(fvp);
1202		dp = VTOI(fdvp);
1203	} else {
1204		/*
1205		 * From name has disappeared.
1206		 */
1207		if (doingdirectory)
1208			panic("ufs_rename: lost dir entry");
1209		vrele(ap->a_fvp);
1210		return (0);
1211	}
1212	/*
1213	 * Ensure that the directory entry still exists and has not
1214	 * changed while the new name has been entered. If the source is
1215	 * a file then the entry may have been unlinked or renamed. In
1216	 * either case there is no further work to be done. If the source
1217	 * is a directory then it cannot have been rmdir'ed; its link
1218	 * count of three would cause a rmdir to fail with ENOTEMPTY.
1219	 * The IN_RENAME flag ensures that it cannot be moved by another
1220	 * rename.
1221	 */
1222	if (xp != ip) {
1223		if (doingdirectory)
1224			panic("ufs_rename: lost dir entry");
1225	} else {
1226		/*
1227		 * If the source is a directory with a
1228		 * new parent, the link count of the old
1229		 * parent directory must be decremented
1230		 * and ".." set to point to the new parent.
1231		 */
1232		if (doingdirectory && newparent) {
1233			dp->i_nlink--;
1234			dp->i_flag |= IN_CHANGE;
1235			error = vn_rdwr(UIO_READ, fvp, (caddr_t)&dirbuf,
1236				sizeof (struct dirtemplate), (off_t)0,
1237				UIO_SYSSPACE, IO_NODELOCKED,
1238				tcnp->cn_cred, (int *)0, (struct proc *)0);
1239			if (error == 0) {
1240#				if (BYTE_ORDER == LITTLE_ENDIAN)
1241					if (fvp->v_mount->mnt_maxsymlinklen <= 0)
1242						namlen = dirbuf.dotdot_type;
1243					else
1244						namlen = dirbuf.dotdot_namlen;
1245#				else
1246					namlen = dirbuf.dotdot_namlen;
1247#				endif
1248#ifdef EXT2FS
1249				if(IS_EXT2_VNODE(fvp))
1250					namlen = ((struct odirtemplate *)
1251						    &dirbuf)->dotdot_namlen;
1252#endif /* EXT2FS */
1253				if (namlen != 2 ||
1254				    dirbuf.dotdot_name[0] != '.' ||
1255				    dirbuf.dotdot_name[1] != '.') {
1256					ufs_dirbad(xp, (doff_t)12,
1257					    "rename: mangled dir");
1258				} else {
1259					dirbuf.dotdot_ino = newparent;
1260					(void) vn_rdwr(UIO_WRITE, fvp,
1261					    (caddr_t)&dirbuf,
1262					    sizeof (struct dirtemplate),
1263					    (off_t)0, UIO_SYSSPACE,
1264					    IO_NODELOCKED|IO_SYNC,
1265					    tcnp->cn_cred, (int *)0,
1266					    (struct proc *)0);
1267					cache_purge(fdvp);
1268				}
1269			}
1270		}
1271#ifdef EXT2FS
1272		if (IS_EXT2_VNODE(fdvp)) {
1273			error = ext2_dirremove(fdvp, fcnp);
1274		} else {
1275			error = ufs_dirremove(fdvp, fcnp);
1276		}
1277#else
1278		error = ufs_dirremove(fdvp, fcnp);
1279#endif /* EXT2FS */
1280		if (!error) {
1281			xp->i_nlink--;
1282			xp->i_flag |= IN_CHANGE;
1283		}
1284		xp->i_flag &= ~IN_RENAME;
1285	}
1286	if (dp)
1287		vput(fdvp);
1288	if (xp)
1289		vput(fvp);
1290	vrele(ap->a_fvp);
1291	return (error);
1292
1293bad:
1294	if (xp)
1295		vput(ITOV(xp));
1296	vput(ITOV(dp));
1297out:
1298	if (doingdirectory)
1299		ip->i_flag &= ~IN_RENAME;
1300	if (vn_lock(fvp, LK_EXCLUSIVE, p) == 0) {
1301		ip->i_nlink--;
1302		ip->i_flag |= IN_CHANGE;
1303		ip->i_flag &= ~IN_RENAME;
1304		vput(fvp);
1305	} else
1306		vrele(fvp);
1307	return (error);
1308}
1309
1310/*
1311 * A virgin directory (no blushing please).
1312 */
1313static struct dirtemplate mastertemplate = {
1314	0, 12, DT_DIR, 1, { '.', 0 },
1315	0, DIRBLKSIZ - 12, DT_DIR, 2, { '.', '.', 0 }
1316};
1317static struct odirtemplate omastertemplate = {
1318	0, 12, 1, { '.', 0 },
1319	0, DIRBLKSIZ - 12, 2, { '.', '.', 0 }
1320};
1321
1322/*
1323 * Mkdir system call
1324 */
1325int
1326ufs_mkdir(ap)
1327	struct vop_mkdir_args /* {
1328		struct vnode *a_dvp;
1329		struct vnode **a_vpp;
1330		struct componentname *a_cnp;
1331		struct vattr *a_vap;
1332	} */ *ap;
1333{
1334	register struct vnode *dvp = ap->a_dvp;
1335	register struct vattr *vap = ap->a_vap;
1336	register struct componentname *cnp = ap->a_cnp;
1337	register struct inode *ip, *dp;
1338	struct vnode *tvp;
1339	struct dirtemplate dirtemplate, *dtp;
1340	struct timeval tv;
1341	int error, dmode;
1342
1343#ifdef DIAGNOSTIC
1344	if ((cnp->cn_flags & HASBUF) == 0)
1345		panic("ufs_mkdir: no name");
1346#endif
1347	dp = VTOI(dvp);
1348	if ((nlink_t)dp->i_nlink >= LINK_MAX) {
1349		error = EMLINK;
1350		goto out;
1351	}
1352	dmode = vap->va_mode & 0777;
1353	dmode |= IFDIR;
1354	/*
1355	 * Must simulate part of ufs_makeinode here to acquire the inode,
1356	 * but not have it entered in the parent directory. The entry is
1357	 * made later after writing "." and ".." entries.
1358	 */
1359	error = VOP_VALLOC(dvp, dmode, cnp->cn_cred, &tvp);
1360	if (error)
1361		goto out;
1362	ip = VTOI(tvp);
1363	ip->i_uid = cnp->cn_cred->cr_uid;
1364	ip->i_gid = dp->i_gid;
1365#ifdef QUOTA
1366	if ((error = getinoquota(ip)) ||
1367	    (error = chkiq(ip, 1, cnp->cn_cred, 0))) {
1368		free(cnp->cn_pnbuf, M_NAMEI);
1369		VOP_VFREE(tvp, ip->i_number, dmode);
1370		vput(tvp);
1371		vput(dvp);
1372		return (error);
1373	}
1374#endif
1375	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
1376	ip->i_mode = dmode;
1377	tvp->v_type = VDIR;	/* Rest init'd in getnewvnode(). */
1378	ip->i_nlink = 2;
1379	if (cnp->cn_flags & ISWHITEOUT)
1380		ip->i_flags |= UF_OPAQUE;
1381	gettime(&tv);
1382	error = VOP_UPDATE(tvp, &tv, &tv, 1);
1383
1384	/*
1385	 * Bump link count in parent directory
1386	 * to reflect work done below.  Should
1387	 * be done before reference is created
1388	 * so reparation is possible if we crash.
1389	 */
1390	dp->i_nlink++;
1391	dp->i_flag |= IN_CHANGE;
1392	error = VOP_UPDATE(dvp, &tv, &tv, 1);
1393	if (error)
1394		goto bad;
1395
1396	/* Initialize directory with "." and ".." from static template. */
1397	if (dvp->v_mount->mnt_maxsymlinklen > 0
1398#ifdef EXT2FS
1399		/* omastertemplate is want we want for EXT2 */
1400		&& !IS_EXT2_VNODE(dvp)
1401#endif /* EXT2FS */
1402	)
1403		dtp = &mastertemplate;
1404	else
1405		dtp = (struct dirtemplate *)&omastertemplate;
1406	dirtemplate = *dtp;
1407	dirtemplate.dot_ino = ip->i_number;
1408	dirtemplate.dotdot_ino = dp->i_number;
1409#ifdef EXT2FS
1410	/* note that in ext2 DIRBLKSIZ == blocksize, not DEV_BSIZE
1411	 * so let's just redefine it - for this function only
1412	 */
1413#undef  DIRBLKSIZ
1414#define DIRBLKSIZ (IS_EXT2_VNODE(dvp) ? \
1415		   VTOI(dvp)->i_e2fs->s_blocksize : DEV_BSIZE)
1416	if(IS_EXT2_VNODE(dvp))
1417		dirtemplate.dotdot_reclen = DIRBLKSIZ - 12;
1418#endif /* EXT2FS */
1419	error = vn_rdwr(UIO_WRITE, tvp, (caddr_t)&dirtemplate,
1420	    sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE,
1421	    IO_NODELOCKED|IO_SYNC, cnp->cn_cred, (int *)0, (struct proc *)0);
1422	if (error) {
1423		dp->i_nlink--;
1424		dp->i_flag |= IN_CHANGE;
1425		goto bad;
1426	}
1427	if (DIRBLKSIZ > VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize)
1428		panic("ufs_mkdir: blksize"); /* XXX should grow with balloc() */
1429	else {
1430		ip->i_size = DIRBLKSIZ;
1431		ip->i_flag |= IN_CHANGE;
1432	}
1433
1434	/* Directory set up, now install it's entry in the parent directory. */
1435#ifdef EXT2FS
1436	if (IS_EXT2_VNODE(dvp)) {
1437		error = ext2_direnter(ip, dvp, cnp);
1438	} else {
1439		error = ufs_direnter(ip, dvp, cnp);
1440	}
1441#else
1442	error = ufs_direnter(ip, dvp, cnp);
1443#endif /* EXT2FS */
1444	if (error) {
1445		dp->i_nlink--;
1446		dp->i_flag |= IN_CHANGE;
1447	}
1448bad:
1449	/*
1450	 * No need to do an explicit VOP_TRUNCATE here, vrele will do this
1451	 * for us because we set the link count to 0.
1452	 */
1453	if (error) {
1454		ip->i_nlink = 0;
1455		ip->i_flag |= IN_CHANGE;
1456		vput(tvp);
1457	} else
1458		*ap->a_vpp = tvp;
1459out:
1460	FREE(cnp->cn_pnbuf, M_NAMEI);
1461	vput(dvp);
1462	return (error);
1463#ifdef EXT2FS
1464#undef  DIRBLKSIZ
1465#define DIRBLKSIZ  DEV_BSIZE
1466#endif /* EXT2FS */
1467}
1468
1469/*
1470 * Rmdir system call.
1471 */
1472int
1473ufs_rmdir(ap)
1474	struct vop_rmdir_args /* {
1475		struct vnode *a_dvp;
1476		struct vnode *a_vp;
1477		struct componentname *a_cnp;
1478	} */ *ap;
1479{
1480	struct vnode *vp = ap->a_vp;
1481	struct vnode *dvp = ap->a_dvp;
1482	struct componentname *cnp = ap->a_cnp;
1483	struct inode *ip, *dp;
1484	int error;
1485
1486	ip = VTOI(vp);
1487	dp = VTOI(dvp);
1488	/*
1489	 * No rmdir "." please.
1490	 */
1491	if (dp == ip) {
1492		vrele(dvp);
1493		vput(vp);
1494		return (EINVAL);
1495	}
1496	/*
1497	 * Verify the directory is empty (and valid).
1498	 * (Rmdir ".." won't be valid since
1499	 *  ".." will contain a reference to
1500	 *  the current directory and thus be
1501	 *  non-empty.)
1502	 */
1503	error = 0;
1504	if (ip->i_nlink != 2 ||
1505#ifdef EXT2FS
1506	    !(IS_EXT2_VNODE(ITOV(ip)) ? ext2_dirempty : ufs_dirempty)
1507	    		 (ip, dp->i_number, cnp->cn_cred)) {
1508#else
1509	    !ufs_dirempty(ip, dp->i_number, cnp->cn_cred)) {
1510#endif /* EXT2FS */
1511		error = ENOTEMPTY;
1512		goto out;
1513	}
1514	if ((dp->i_flags & APPEND) || (ip->i_flags & (IMMUTABLE | APPEND))) {
1515		error = EPERM;
1516		goto out;
1517	}
1518	/*
1519	 * Delete reference to directory before purging
1520	 * inode.  If we crash in between, the directory
1521	 * will be reattached to lost+found,
1522	 */
1523#ifdef EXT2FS
1524	if (IS_EXT2_VNODE(dvp)) {
1525		error = ext2_dirremove(dvp, cnp);
1526	} else {
1527		error = ufs_dirremove(dvp, cnp);
1528	}
1529#else
1530	error = ufs_dirremove(dvp, cnp);
1531#endif /* EXT2FS */
1532	if (error)
1533		goto out;
1534	dp->i_nlink--;
1535	dp->i_flag |= IN_CHANGE;
1536	cache_purge(dvp);
1537	vput(dvp);
1538	dvp = NULL;
1539	/*
1540	 * Truncate inode.  The only stuff left
1541	 * in the directory is "." and "..".  The
1542	 * "." reference is inconsequential since
1543	 * we're quashing it.  The ".." reference
1544	 * has already been adjusted above.  We've
1545	 * removed the "." reference and the reference
1546	 * in the parent directory, but there may be
1547	 * other hard links so decrement by 2 and
1548	 * worry about them later.
1549	 */
1550	ip->i_nlink -= 2;
1551	error = VOP_TRUNCATE(vp, (off_t)0, IO_SYNC, cnp->cn_cred,
1552	    cnp->cn_proc);
1553	cache_purge(ITOV(ip));
1554out:
1555	if (dvp)
1556		vput(dvp);
1557	vput(vp);
1558	return (error);
1559}
1560
1561/*
1562 * symlink -- make a symbolic link
1563 */
1564int
1565ufs_symlink(ap)
1566	struct vop_symlink_args /* {
1567		struct vnode *a_dvp;
1568		struct vnode **a_vpp;
1569		struct componentname *a_cnp;
1570		struct vattr *a_vap;
1571		char *a_target;
1572	} */ *ap;
1573{
1574	register struct vnode *vp, **vpp = ap->a_vpp;
1575	register struct inode *ip;
1576	int len, error;
1577
1578	error = ufs_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp,
1579	    vpp, ap->a_cnp);
1580	if (error)
1581		return (error);
1582	vp = *vpp;
1583	len = strlen(ap->a_target);
1584	if (len < vp->v_mount->mnt_maxsymlinklen) {
1585		ip = VTOI(vp);
1586		bcopy(ap->a_target, (char *)ip->i_shortlink, len);
1587		ip->i_size = len;
1588		ip->i_flag |= IN_CHANGE | IN_UPDATE;
1589	} else
1590		error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
1591		    UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred, (int *)0,
1592		    (struct proc *)0);
1593	vput(vp);
1594	return (error);
1595}
1596
1597/*
1598 * Vnode op for reading directories.
1599 *
1600 * The routine below assumes that the on-disk format of a directory
1601 * is the same as that defined by <sys/dirent.h>. If the on-disk
1602 * format changes, then it will be necessary to do a conversion
1603 * from the on-disk format that read returns to the format defined
1604 * by <sys/dirent.h>.
1605 */
1606int
1607ufs_readdir(ap)
1608	struct vop_readdir_args /* {
1609		struct vnode *a_vp;
1610		struct uio *a_uio;
1611		struct ucred *a_cred;
1612		int *a_eofflag;
1613		int *ncookies;
1614		u_long **a_cookies;
1615	} */ *ap;
1616{
1617	register struct uio *uio = ap->a_uio;
1618	int error;
1619	size_t count, lost;
1620	off_t off;
1621
1622	if (ap->a_ncookies != NULL)
1623		/*
1624		 * Ensure that the block is aligned.  The caller can use
1625		 * the cookies to determine where in the block to start.
1626		 */
1627		uio->uio_offset &= ~(DIRBLKSIZ - 1);
1628	off = uio->uio_offset;
1629	count = uio->uio_resid;
1630	/* Make sure we don't return partial entries. */
1631	count -= (uio->uio_offset + count) & (DIRBLKSIZ -1);
1632	if (count <= 0)
1633		return (EINVAL);
1634	lost = uio->uio_resid - count;
1635	uio->uio_resid = count;
1636	uio->uio_iov->iov_len = count;
1637#	if (BYTE_ORDER == LITTLE_ENDIAN)
1638		if (ap->a_vp->v_mount->mnt_maxsymlinklen > 0) {
1639			error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred);
1640		} else {
1641			struct dirent *dp, *edp;
1642			struct uio auio;
1643			struct iovec aiov;
1644			caddr_t dirbuf;
1645			int readcnt;
1646			u_char tmp;
1647
1648			auio = *uio;
1649			auio.uio_iov = &aiov;
1650			auio.uio_iovcnt = 1;
1651			auio.uio_segflg = UIO_SYSSPACE;
1652			aiov.iov_len = count;
1653			MALLOC(dirbuf, caddr_t, count, M_TEMP, M_WAITOK);
1654			aiov.iov_base = dirbuf;
1655			error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred);
1656			if (error == 0) {
1657				readcnt = count - auio.uio_resid;
1658				edp = (struct dirent *)&dirbuf[readcnt];
1659				for (dp = (struct dirent *)dirbuf; dp < edp; ) {
1660					tmp = dp->d_namlen;
1661					dp->d_namlen = dp->d_type;
1662					dp->d_type = tmp;
1663					if (dp->d_reclen > 0) {
1664						dp = (struct dirent *)
1665						    ((char *)dp + dp->d_reclen);
1666					} else {
1667						error = EIO;
1668						break;
1669					}
1670				}
1671				if (dp >= edp)
1672					error = uiomove(dirbuf, readcnt, uio);
1673			}
1674			FREE(dirbuf, M_TEMP);
1675		}
1676#	else
1677		error = VOP_READ(ap->a_vp, uio, 0, ap->a_cred);
1678#	endif
1679	if (!error && ap->a_ncookies != NULL) {
1680		struct dirent* dpStart;
1681		struct dirent* dpEnd;
1682		struct dirent* dp;
1683		int ncookies;
1684		u_long *cookies;
1685		u_long *cookiep;
1686
1687		if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
1688			panic("ufs_readdir: unexpected uio from NFS server");
1689		dpStart = (struct dirent *)
1690		     (uio->uio_iov->iov_base - (uio->uio_offset - off));
1691		dpEnd = (struct dirent *) uio->uio_iov->iov_base;
1692		for (dp = dpStart, ncookies = 0;
1693		     dp < dpEnd;
1694		     dp = (struct dirent *)((caddr_t) dp + dp->d_reclen))
1695			ncookies++;
1696		MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
1697		    M_WAITOK);
1698		for (dp = dpStart, cookiep = cookies;
1699		     dp < dpEnd;
1700		     dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) {
1701			off += dp->d_reclen;
1702			*cookiep++ = (u_long) off;
1703		}
1704		*ap->a_ncookies = ncookies;
1705		*ap->a_cookies = cookies;
1706	}
1707	uio->uio_resid += lost;
1708	if (ap->a_eofflag)
1709	    *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset;
1710	return (error);
1711}
1712
1713/*
1714 * Return target name of a symbolic link
1715 */
1716int
1717ufs_readlink(ap)
1718	struct vop_readlink_args /* {
1719		struct vnode *a_vp;
1720		struct uio *a_uio;
1721		struct ucred *a_cred;
1722	} */ *ap;
1723{
1724	register struct vnode *vp = ap->a_vp;
1725	register struct inode *ip = VTOI(vp);
1726	int isize;
1727
1728	isize = ip->i_size;
1729	if ((isize < vp->v_mount->mnt_maxsymlinklen) ||
1730	    (ip->i_din.di_blocks == 0)) {	/* XXX - for old fastlink support */
1731		uiomove((char *)ip->i_shortlink, isize, ap->a_uio);
1732		return (0);
1733	}
1734	return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred));
1735}
1736
1737/*
1738 * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
1739 * done. If a buffer has been saved in anticipation of a CREATE, delete it.
1740 */
1741/* ARGSUSED */
1742int
1743ufs_abortop(ap)
1744	struct vop_abortop_args /* {
1745		struct vnode *a_dvp;
1746		struct componentname *a_cnp;
1747	} */ *ap;
1748{
1749	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
1750		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
1751	return (0);
1752}
1753
1754/*
1755 * Lock an inode. If its already locked, set the WANT bit and sleep.
1756 */
1757int
1758ufs_lock(ap)
1759	struct vop_lock_args /* {
1760		struct vnode *a_vp;
1761		int a_flags;
1762		struct proc *a_p;
1763	} */ *ap;
1764{
1765	struct vnode *vp = ap->a_vp;
1766
1767	return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, &vp->v_interlock,
1768		ap->a_p));
1769}
1770
1771/*
1772 * Unlock an inode.
1773 */
1774int
1775ufs_unlock(ap)
1776	struct vop_unlock_args /* {
1777		struct vnode *a_vp;
1778		int a_flags;
1779		struct proc *a_p;
1780	} */ *ap;
1781{
1782	struct vnode *vp = ap->a_vp;
1783
1784	return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE,
1785		&vp->v_interlock, ap->a_p));
1786}
1787
1788/*
1789 * Check for a locked inode.
1790 */
1791int
1792ufs_islocked(ap)
1793	struct vop_islocked_args /* {
1794		struct vnode *a_vp;
1795	} */ *ap;
1796{
1797
1798	return (lockstatus(&VTOI(ap->a_vp)->i_lock));
1799}
1800
1801/*
1802 * Calculate the logical to physical mapping if not done already,
1803 * then call the device strategy routine.
1804 */
1805int
1806ufs_strategy(ap)
1807	struct vop_strategy_args /* {
1808		struct buf *a_bp;
1809	} */ *ap;
1810{
1811	register struct buf *bp = ap->a_bp;
1812	register struct vnode *vp = bp->b_vp;
1813	register struct inode *ip;
1814	int error;
1815
1816	ip = VTOI(vp);
1817	if (vp->v_type == VBLK || vp->v_type == VCHR)
1818		panic("ufs_strategy: spec");
1819	if (bp->b_blkno == bp->b_lblkno) {
1820		error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL, NULL);
1821		if (error) {
1822			bp->b_error = error;
1823			bp->b_flags |= B_ERROR;
1824			biodone(bp);
1825			return (error);
1826		}
1827		if ((long)bp->b_blkno == -1)
1828			vfs_bio_clrbuf(bp);
1829	}
1830	if ((long)bp->b_blkno == -1) {
1831		biodone(bp);
1832		return (0);
1833	}
1834	vp = ip->i_devvp;
1835	bp->b_dev = vp->v_rdev;
1836	VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
1837	return (0);
1838}
1839
1840/*
1841 * Print out the contents of an inode.
1842 */
1843int
1844ufs_print(ap)
1845	struct vop_print_args /* {
1846		struct vnode *a_vp;
1847	} */ *ap;
1848{
1849	register struct vnode *vp = ap->a_vp;
1850	register struct inode *ip = VTOI(vp);
1851
1852	printf("tag VT_UFS, ino %ld, on dev %d, %d", ip->i_number,
1853		major(ip->i_dev), minor(ip->i_dev));
1854	if (vp->v_type == VFIFO)
1855		fifo_printinfo(vp);
1856	lockmgr_printinfo(&ip->i_lock);
1857	printf("\n");
1858	return (0);
1859}
1860
1861/*
1862 * Read wrapper for special devices.
1863 */
1864int
1865ufsspec_read(ap)
1866	struct vop_read_args /* {
1867		struct vnode *a_vp;
1868		struct uio *a_uio;
1869		int  a_ioflag;
1870		struct ucred *a_cred;
1871	} */ *ap;
1872{
1873
1874	/*
1875	 * Set access flag.
1876	 */
1877	VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
1878	return (VOCALL (spec_vnodeop_p, VOFFSET(vop_read), ap));
1879}
1880
1881/*
1882 * Write wrapper for special devices.
1883 */
1884int
1885ufsspec_write(ap)
1886	struct vop_write_args /* {
1887		struct vnode *a_vp;
1888		struct uio *a_uio;
1889		int  a_ioflag;
1890		struct ucred *a_cred;
1891	} */ *ap;
1892{
1893
1894	/*
1895	 * Set update and change flags.
1896	 */
1897	VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
1898	return (VOCALL (spec_vnodeop_p, VOFFSET(vop_write), ap));
1899}
1900
1901/*
1902 * Close wrapper for special devices.
1903 *
1904 * Update the times on the inode then do device close.
1905 */
1906int
1907ufsspec_close(ap)
1908	struct vop_close_args /* {
1909		struct vnode *a_vp;
1910		int  a_fflag;
1911		struct ucred *a_cred;
1912		struct proc *a_p;
1913	} */ *ap;
1914{
1915	struct vnode *vp = ap->a_vp;
1916	struct inode *ip = VTOI(vp);
1917
1918	simple_lock(&vp->v_interlock);
1919	if (ap->a_vp->v_usecount > 1)
1920		ITIMES(ip, &time, &time);
1921	simple_unlock(&vp->v_interlock);
1922	return (VOCALL (spec_vnodeop_p, VOFFSET(vop_close), ap));
1923}
1924
1925/*
1926 * Read wrapper for fifo's
1927 */
1928int
1929ufsfifo_read(ap)
1930	struct vop_read_args /* {
1931		struct vnode *a_vp;
1932		struct uio *a_uio;
1933		int  a_ioflag;
1934		struct ucred *a_cred;
1935	} */ *ap;
1936{
1937	/*
1938	 * Set access flag.
1939	 */
1940	VTOI(ap->a_vp)->i_flag |= IN_ACCESS;
1941	return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_read), ap));
1942}
1943
1944/*
1945 * Write wrapper for fifo's.
1946 */
1947int
1948ufsfifo_write(ap)
1949	struct vop_write_args /* {
1950		struct vnode *a_vp;
1951		struct uio *a_uio;
1952		int  a_ioflag;
1953		struct ucred *a_cred;
1954	} */ *ap;
1955{
1956	/*
1957	 * Set update and change flags.
1958	 */
1959	VTOI(ap->a_vp)->i_flag |= IN_CHANGE | IN_UPDATE;
1960	return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_write), ap));
1961}
1962
1963/*
1964 * Close wrapper for fifo's.
1965 *
1966 * Update the times on the inode then do device close.
1967 */
1968int
1969ufsfifo_close(ap)
1970	struct vop_close_args /* {
1971		struct vnode *a_vp;
1972		int  a_fflag;
1973		struct ucred *a_cred;
1974		struct proc *a_p;
1975	} */ *ap;
1976{
1977	struct vnode *vp = ap->a_vp;
1978	struct inode *ip = VTOI(vp);
1979
1980	simple_lock(&vp->v_interlock);
1981	if (ap->a_vp->v_usecount > 1)
1982		ITIMES(ip, &time, &time);
1983	simple_unlock(&vp->v_interlock);
1984	return (VOCALL (fifo_vnodeop_p, VOFFSET(vop_close), ap));
1985}
1986
1987/*
1988 * Return POSIX pathconf information applicable to ufs filesystems.
1989 */
1990int
1991ufs_pathconf(ap)
1992	struct vop_pathconf_args /* {
1993		struct vnode *a_vp;
1994		int a_name;
1995		int *a_retval;
1996	} */ *ap;
1997{
1998
1999	switch (ap->a_name) {
2000	case _PC_LINK_MAX:
2001		*ap->a_retval = LINK_MAX;
2002		return (0);
2003	case _PC_NAME_MAX:
2004		*ap->a_retval = NAME_MAX;
2005		return (0);
2006	case _PC_PATH_MAX:
2007		*ap->a_retval = PATH_MAX;
2008		return (0);
2009	case _PC_PIPE_BUF:
2010		*ap->a_retval = PIPE_BUF;
2011		return (0);
2012	case _PC_CHOWN_RESTRICTED:
2013		*ap->a_retval = 1;
2014		return (0);
2015	case _PC_NO_TRUNC:
2016		*ap->a_retval = 1;
2017		return (0);
2018	default:
2019		return (EINVAL);
2020	}
2021	/* NOTREACHED */
2022}
2023
2024/*
2025 * Advisory record locking support
2026 */
2027int
2028ufs_advlock(ap)
2029	struct vop_advlock_args /* {
2030		struct vnode *a_vp;
2031		caddr_t  a_id;
2032		int  a_op;
2033		struct flock *a_fl;
2034		int  a_flags;
2035	} */ *ap;
2036{
2037	register struct inode *ip = VTOI(ap->a_vp);
2038
2039	return (lf_advlock(ap, &(ip->i_lockf), ip->i_size));
2040}
2041
2042/*
2043 * Initialize the vnode associated with a new inode, handle aliased
2044 * vnodes.
2045 */
2046int
2047ufs_vinit(mntp, specops, fifoops, vpp)
2048	struct mount *mntp;
2049	vop_t **specops;
2050	vop_t **fifoops;
2051	struct vnode **vpp;
2052{
2053	struct inode *ip;
2054	struct vnode *vp, *nvp;
2055
2056	vp = *vpp;
2057	ip = VTOI(vp);
2058	switch(vp->v_type = IFTOVT(ip->i_mode)) {
2059	case VCHR:
2060	case VBLK:
2061		vp->v_op = specops;
2062		nvp = checkalias(vp, ip->i_rdev, mntp);
2063		if (nvp) {
2064			/*
2065			 * Discard unneeded vnode, but save its inode.
2066			 * Note that the lock is carried over in the inode
2067			 * to the replacement vnode.
2068			 */
2069			nvp->v_data = vp->v_data;
2070			vp->v_data = NULL;
2071			vp->v_op = spec_vnodeop_p;
2072			vrele(vp);
2073			vgone(vp);
2074			/*
2075			 * Reinitialize aliased inode.
2076			 */
2077			vp = nvp;
2078			ip->i_vnode = vp;
2079		}
2080		break;
2081	case VFIFO:
2082		vp->v_op = fifoops;
2083		break;
2084	default:
2085		break;
2086
2087	}
2088	if (ip->i_number == ROOTINO)
2089                vp->v_flag |= VROOT;
2090	/*
2091	 * Initialize modrev times
2092	 */
2093	SETHIGH(ip->i_modrev, mono_time.tv_sec);
2094	SETLOW(ip->i_modrev, mono_time.tv_usec * 4294);
2095	*vpp = vp;
2096	return (0);
2097}
2098
2099/*
2100 * Allocate a new inode.
2101 */
2102int
2103ufs_makeinode(mode, dvp, vpp, cnp)
2104	int mode;
2105	struct vnode *dvp;
2106	struct vnode **vpp;
2107	struct componentname *cnp;
2108{
2109	register struct inode *ip, *pdir;
2110	struct timeval tv;
2111	struct vnode *tvp;
2112	int error;
2113
2114	pdir = VTOI(dvp);
2115#ifdef DIAGNOSTIC
2116	if ((cnp->cn_flags & HASBUF) == 0)
2117		panic("ufs_makeinode: no name");
2118#endif
2119	*vpp = NULL;
2120	if ((mode & IFMT) == 0)
2121		mode |= IFREG;
2122
2123	error = VOP_VALLOC(dvp, mode, cnp->cn_cred, &tvp);
2124	if (error) {
2125		free(cnp->cn_pnbuf, M_NAMEI);
2126		vput(dvp);
2127		return (error);
2128	}
2129	ip = VTOI(tvp);
2130	ip->i_gid = pdir->i_gid;
2131	if ((mode & IFMT) == IFLNK)
2132		ip->i_uid = pdir->i_uid;
2133	else
2134		ip->i_uid = cnp->cn_cred->cr_uid;
2135#ifdef QUOTA
2136	if ((error = getinoquota(ip)) ||
2137	    (error = chkiq(ip, 1, cnp->cn_cred, 0))) {
2138		free(cnp->cn_pnbuf, M_NAMEI);
2139		VOP_VFREE(tvp, ip->i_number, mode);
2140		vput(tvp);
2141		vput(dvp);
2142		return (error);
2143	}
2144#endif
2145	ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE;
2146	ip->i_mode = mode;
2147	tvp->v_type = IFTOVT(mode);	/* Rest init'd in getnewvnode(). */
2148	ip->i_nlink = 1;
2149	if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) &&
2150	    suser(cnp->cn_cred, NULL))
2151		ip->i_mode &= ~ISGID;
2152
2153	if (cnp->cn_flags & ISWHITEOUT)
2154		ip->i_flags |= UF_OPAQUE;
2155
2156	/*
2157	 * Make sure inode goes to disk before directory entry.
2158	 */
2159	gettime(&tv);
2160	error = VOP_UPDATE(tvp, &tv, &tv, 1);
2161	if (error)
2162		goto bad;
2163#ifdef EXT2FS
2164	if (IS_EXT2_VNODE(dvp)) {
2165		error = ext2_direnter(ip, dvp, cnp);
2166	} else {
2167		error = ufs_direnter(ip, dvp, cnp);
2168	}
2169#else
2170	error = ufs_direnter(ip, dvp, cnp);
2171#endif  /* EXT2FS */
2172	if (error)
2173		goto bad;
2174
2175	if ((cnp->cn_flags & SAVESTART) == 0)
2176		FREE(cnp->cn_pnbuf, M_NAMEI);
2177	vput(dvp);
2178	*vpp = tvp;
2179	return (0);
2180
2181bad:
2182	/*
2183	 * Write error occurred trying to update the inode
2184	 * or the directory so must deallocate the inode.
2185	 */
2186	free(cnp->cn_pnbuf, M_NAMEI);
2187	vput(dvp);
2188	ip->i_nlink = 0;
2189	ip->i_flag |= IN_CHANGE;
2190	vput(tvp);
2191	return (error);
2192}
2193