PageRenderTime 9ms CodeModel.GetById 6ms app.highlight 119ms RepoModel.GetById 1ms app.codeStats 1ms

/netbsd/src/sys/ufs/ufs/ufs_vnops.c

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