xref: /freebsd/sys/fs/msdosfs/msdosfs_denode.c (revision 2f9bae59d66ce0d8d74807af1036164af819f415)
12f9bae59SDavid Greenman /*	$Id: msdosfs_denode.c,v 1.16 1996/01/19 03:58:42 dyson Exp $ */
227a0bc89SDoug Rabson /*	$NetBSD: msdosfs_denode.c,v 1.9 1994/08/21 18:44:00 ws Exp $	*/
327a0bc89SDoug Rabson 
427a0bc89SDoug Rabson /*-
527a0bc89SDoug Rabson  * Copyright (C) 1994 Wolfgang Solfrank.
627a0bc89SDoug Rabson  * Copyright (C) 1994 TooLs GmbH.
727a0bc89SDoug Rabson  * All rights reserved.
827a0bc89SDoug Rabson  * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
927a0bc89SDoug Rabson  *
1027a0bc89SDoug Rabson  * Redistribution and use in source and binary forms, with or without
1127a0bc89SDoug Rabson  * modification, are permitted provided that the following conditions
1227a0bc89SDoug Rabson  * are met:
1327a0bc89SDoug Rabson  * 1. Redistributions of source code must retain the above copyright
1427a0bc89SDoug Rabson  *    notice, this list of conditions and the following disclaimer.
1527a0bc89SDoug Rabson  * 2. Redistributions in binary form must reproduce the above copyright
1627a0bc89SDoug Rabson  *    notice, this list of conditions and the following disclaimer in the
1727a0bc89SDoug Rabson  *    documentation and/or other materials provided with the distribution.
1827a0bc89SDoug Rabson  * 3. All advertising materials mentioning features or use of this software
1927a0bc89SDoug Rabson  *    must display the following acknowledgement:
2027a0bc89SDoug Rabson  *	This product includes software developed by TooLs GmbH.
2127a0bc89SDoug Rabson  * 4. The name of TooLs GmbH may not be used to endorse or promote products
2227a0bc89SDoug Rabson  *    derived from this software without specific prior written permission.
2327a0bc89SDoug Rabson  *
2427a0bc89SDoug Rabson  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
2527a0bc89SDoug Rabson  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2627a0bc89SDoug Rabson  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2727a0bc89SDoug Rabson  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2827a0bc89SDoug Rabson  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2927a0bc89SDoug Rabson  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
3027a0bc89SDoug Rabson  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
3127a0bc89SDoug Rabson  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3227a0bc89SDoug Rabson  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
3327a0bc89SDoug Rabson  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3427a0bc89SDoug Rabson  */
3527a0bc89SDoug Rabson /*
3627a0bc89SDoug Rabson  * Written by Paul Popelka (paulp@uts.amdahl.com)
3727a0bc89SDoug Rabson  *
3827a0bc89SDoug Rabson  * You can do anything you want with this software, just don't say you wrote
3927a0bc89SDoug Rabson  * it, and don't remove this notice.
4027a0bc89SDoug Rabson  *
4127a0bc89SDoug Rabson  * This software is provided "as is".
4227a0bc89SDoug Rabson  *
4327a0bc89SDoug Rabson  * The author supplies this software to be publicly redistributed on the
4427a0bc89SDoug Rabson  * understanding that the author is not responsible for the correct
4527a0bc89SDoug Rabson  * functioning of this software in any circumstances and is not liable for
4627a0bc89SDoug Rabson  * any damages caused by this software.
4727a0bc89SDoug Rabson  *
4827a0bc89SDoug Rabson  * October 1992
4927a0bc89SDoug Rabson  */
5027a0bc89SDoug Rabson 
5127a0bc89SDoug Rabson #include <sys/param.h>
5227a0bc89SDoug Rabson #include <sys/systm.h>
5327a0bc89SDoug Rabson #include <sys/mount.h>
5427a0bc89SDoug Rabson #include <sys/malloc.h>
5527a0bc89SDoug Rabson #include <sys/proc.h>
5627a0bc89SDoug Rabson #include <sys/buf.h>
5727a0bc89SDoug Rabson #include <sys/vnode.h>
58c3c6d51eSPoul-Henning Kamp #include <sys/types.h>
5927a0bc89SDoug Rabson #include <sys/kernel.h>		/* defines "time" */
6027a0bc89SDoug Rabson 
61c3c6d51eSPoul-Henning Kamp #include <vm/vm.h>
62efeaf95aSDavid Greenman #include <vm/vm_param.h>
63efeaf95aSDavid Greenman #include <vm/vm_extern.h>
64c3c6d51eSPoul-Henning Kamp 
6527a0bc89SDoug Rabson #include <msdosfs/bpb.h>
6627a0bc89SDoug Rabson #include <msdosfs/msdosfsmount.h>
6727a0bc89SDoug Rabson #include <msdosfs/direntry.h>
6827a0bc89SDoug Rabson #include <msdosfs/denode.h>
6927a0bc89SDoug Rabson #include <msdosfs/fat.h>
7027a0bc89SDoug Rabson 
7127a0bc89SDoug Rabson struct denode **dehashtbl;
7227a0bc89SDoug Rabson u_long dehash;			/* size of hash table - 1 */
7327a0bc89SDoug Rabson #define	DEHASH(dev, deno)	(((dev) + (deno)) & dehash)
7427a0bc89SDoug Rabson 
7594a8606fSDoug Rabson union _qcvt {
7694a8606fSDoug Rabson 	quad_t qcvt;
7794a8606fSDoug Rabson 	long val[2];
7894a8606fSDoug Rabson };
7994a8606fSDoug Rabson #define SETHIGH(q, h) { \
8094a8606fSDoug Rabson 	union _qcvt tmp; \
8194a8606fSDoug Rabson 	tmp.qcvt = (q); \
8294a8606fSDoug Rabson 	tmp.val[_QUAD_HIGHWORD] = (h); \
8394a8606fSDoug Rabson 	(q) = tmp.qcvt; \
8494a8606fSDoug Rabson }
8594a8606fSDoug Rabson #define SETLOW(q, l) { \
8694a8606fSDoug Rabson 	union _qcvt tmp; \
8794a8606fSDoug Rabson 	tmp.qcvt = (q); \
8894a8606fSDoug Rabson 	tmp.val[_QUAD_LOWWORD] = (l); \
8994a8606fSDoug Rabson 	(q) = tmp.qcvt; \
9094a8606fSDoug Rabson }
9194a8606fSDoug Rabson 
9258c27bcfSBruce Evans static struct denode *
9358c27bcfSBruce Evans 		msdosfs_hashget __P((dev_t dev, u_long dirclust,
9458c27bcfSBruce Evans 				     u_long diroff));
9558c27bcfSBruce Evans static void	msdosfs_hashins __P((struct denode *dep));
9658c27bcfSBruce Evans static void	msdosfs_hashrem __P((struct denode *dep));
9758c27bcfSBruce Evans 
9827a0bc89SDoug Rabson int msdosfs_init()
9927a0bc89SDoug Rabson {
10027a0bc89SDoug Rabson 	dehashtbl = hashinit(desiredvnodes/2, M_MSDOSFSMNT, &dehash);
10127a0bc89SDoug Rabson 	return 0;
10227a0bc89SDoug Rabson }
10327a0bc89SDoug Rabson 
10427a0bc89SDoug Rabson static struct denode *
10527a0bc89SDoug Rabson msdosfs_hashget(dev, dirclust, diroff)
10627a0bc89SDoug Rabson 	dev_t dev;
10727a0bc89SDoug Rabson 	u_long dirclust;
10827a0bc89SDoug Rabson 	u_long diroff;
10927a0bc89SDoug Rabson {
11027a0bc89SDoug Rabson 	struct denode *dep;
11127a0bc89SDoug Rabson 
11227a0bc89SDoug Rabson 	for (;;)
11327a0bc89SDoug Rabson 		for (dep = dehashtbl[DEHASH(dev, dirclust + diroff)];;
11427a0bc89SDoug Rabson 		     dep = dep->de_next) {
11527a0bc89SDoug Rabson 			if (dep == NULL)
11627a0bc89SDoug Rabson 				return NULL;
11727a0bc89SDoug Rabson 			if (dirclust != dep->de_dirclust
11827a0bc89SDoug Rabson 			    || diroff != dep->de_diroffset
11927a0bc89SDoug Rabson 			    || dev != dep->de_dev
12027a0bc89SDoug Rabson 			    || dep->de_refcnt == 0)
12127a0bc89SDoug Rabson 				continue;
12227a0bc89SDoug Rabson 			if (dep->de_flag & DE_LOCKED) {
12327a0bc89SDoug Rabson 				dep->de_flag |= DE_WANTED;
12482478919SDavid Greenman 				(void) tsleep((caddr_t)dep, PINOD, "msdhgt", 0);
12527a0bc89SDoug Rabson 				break;
12627a0bc89SDoug Rabson 			}
12727a0bc89SDoug Rabson 			if (!vget(DETOV(dep), 1))
12827a0bc89SDoug Rabson 				return dep;
12927a0bc89SDoug Rabson 			break;
13027a0bc89SDoug Rabson 		}
13127a0bc89SDoug Rabson 	/* NOTREACHED */
13227a0bc89SDoug Rabson }
13327a0bc89SDoug Rabson 
13427a0bc89SDoug Rabson static void
13527a0bc89SDoug Rabson msdosfs_hashins(dep)
13627a0bc89SDoug Rabson 	struct denode *dep;
13727a0bc89SDoug Rabson {
13827a0bc89SDoug Rabson 	struct denode **depp, *deq;
13927a0bc89SDoug Rabson 
14027a0bc89SDoug Rabson 	depp = &dehashtbl[DEHASH(dep->de_dev, dep->de_dirclust + dep->de_diroffset)];
141c3c6d51eSPoul-Henning Kamp 	deq = *depp;
142c3c6d51eSPoul-Henning Kamp 	if (deq)
14327a0bc89SDoug Rabson 		deq->de_prev = &dep->de_next;
14427a0bc89SDoug Rabson 	dep->de_next = deq;
14527a0bc89SDoug Rabson 	dep->de_prev = depp;
14627a0bc89SDoug Rabson 	*depp = dep;
14727a0bc89SDoug Rabson }
14827a0bc89SDoug Rabson 
14927a0bc89SDoug Rabson static void
15027a0bc89SDoug Rabson msdosfs_hashrem(dep)
15127a0bc89SDoug Rabson 	struct denode *dep;
15227a0bc89SDoug Rabson {
15327a0bc89SDoug Rabson 	struct denode *deq;
154c3c6d51eSPoul-Henning Kamp 	deq = dep->de_next;
155c3c6d51eSPoul-Henning Kamp 	if (deq)
15627a0bc89SDoug Rabson 		deq->de_prev = dep->de_prev;
15727a0bc89SDoug Rabson 	*dep->de_prev = deq;
15827a0bc89SDoug Rabson #ifdef DIAGNOSTIC
15927a0bc89SDoug Rabson 	dep->de_next = NULL;
16027a0bc89SDoug Rabson 	dep->de_prev = NULL;
16127a0bc89SDoug Rabson #endif
16227a0bc89SDoug Rabson }
16327a0bc89SDoug Rabson 
16427a0bc89SDoug Rabson /*
16527a0bc89SDoug Rabson  * If deget() succeeds it returns with the gotten denode locked().
16627a0bc89SDoug Rabson  *
16727a0bc89SDoug Rabson  * pmp	     - address of msdosfsmount structure of the filesystem containing
16827a0bc89SDoug Rabson  *	       the denode of interest.  The pm_dev field and the address of
16927a0bc89SDoug Rabson  *	       the msdosfsmount structure are used.
17027a0bc89SDoug Rabson  * dirclust  - which cluster bp contains, if dirclust is 0 (root directory)
17127a0bc89SDoug Rabson  *	       diroffset is relative to the beginning of the root directory,
17227a0bc89SDoug Rabson  *	       otherwise it is cluster relative.
17327a0bc89SDoug Rabson  * diroffset - offset past begin of cluster of denode we want
17427a0bc89SDoug Rabson  * direntptr - address of the direntry structure of interest. If direntptr is
17527a0bc89SDoug Rabson  *	       NULL, the block is read if necessary.
17627a0bc89SDoug Rabson  * depp	     - returns the address of the gotten denode.
17727a0bc89SDoug Rabson  */
17827a0bc89SDoug Rabson int
17927a0bc89SDoug Rabson deget(pmp, dirclust, diroffset, direntptr, depp)
18027a0bc89SDoug Rabson 	struct msdosfsmount *pmp;	/* so we know the maj/min number */
18127a0bc89SDoug Rabson 	u_long dirclust;		/* cluster this dir entry came from */
18227a0bc89SDoug Rabson 	u_long diroffset;		/* index of entry within the cluster */
18327a0bc89SDoug Rabson 	struct direntry *direntptr;
18427a0bc89SDoug Rabson 	struct denode **depp;		/* returns the addr of the gotten denode */
18527a0bc89SDoug Rabson {
18627a0bc89SDoug Rabson 	int error;
18727a0bc89SDoug Rabson 	dev_t dev = pmp->pm_dev;
18827a0bc89SDoug Rabson 	struct mount *mntp = pmp->pm_mountp;
18927a0bc89SDoug Rabson 	struct denode *ldep;
19027a0bc89SDoug Rabson 	struct vnode *nvp;
19127a0bc89SDoug Rabson 	struct buf *bp;
19227a0bc89SDoug Rabson 
19327a0bc89SDoug Rabson #ifdef MSDOSFS_DEBUG
194f0707215SPoul-Henning Kamp 	printf("deget(pmp %p, dirclust %ld, diroffset %x, direntptr %p, depp %p)\n",
19527a0bc89SDoug Rabson 	       pmp, dirclust, diroffset, direntptr, depp);
19627a0bc89SDoug Rabson #endif
19727a0bc89SDoug Rabson 
19827a0bc89SDoug Rabson 	/*
19927a0bc89SDoug Rabson 	 * If dir entry is given and refers to a directory, convert to
20027a0bc89SDoug Rabson 	 * canonical form
20127a0bc89SDoug Rabson 	 */
20227a0bc89SDoug Rabson 	if (direntptr && (direntptr->deAttributes & ATTR_DIRECTORY)) {
20327a0bc89SDoug Rabson 		dirclust = getushort(direntptr->deStartCluster);
20427a0bc89SDoug Rabson 		if (dirclust == MSDOSFSROOT)
20527a0bc89SDoug Rabson 			diroffset = MSDOSFSROOT_OFS;
20627a0bc89SDoug Rabson 		else
20727a0bc89SDoug Rabson 			diroffset = 0;
20827a0bc89SDoug Rabson 	}
20927a0bc89SDoug Rabson 
21027a0bc89SDoug Rabson 	/*
21127a0bc89SDoug Rabson 	 * See if the denode is in the denode cache. Use the location of
21227a0bc89SDoug Rabson 	 * the directory entry to compute the hash value. For subdir use
21327a0bc89SDoug Rabson 	 * address of "." entry. for root dir use cluster MSDOSFSROOT,
21427a0bc89SDoug Rabson 	 * offset MSDOSFSROOT_OFS
21527a0bc89SDoug Rabson 	 *
21627a0bc89SDoug Rabson 	 * NOTE: The check for de_refcnt > 0 below insures the denode being
21727a0bc89SDoug Rabson 	 * examined does not represent an unlinked but still open file.
21827a0bc89SDoug Rabson 	 * These files are not to be accessible even when the directory
21927a0bc89SDoug Rabson 	 * entry that represented the file happens to be reused while the
22027a0bc89SDoug Rabson 	 * deleted file is still open.
22127a0bc89SDoug Rabson 	 */
222c3c6d51eSPoul-Henning Kamp 	ldep = msdosfs_hashget(dev, dirclust, diroffset);
223c3c6d51eSPoul-Henning Kamp 	if (ldep) {
22427a0bc89SDoug Rabson 		*depp = ldep;
22527a0bc89SDoug Rabson 		return 0;
22627a0bc89SDoug Rabson 	}
22727a0bc89SDoug Rabson 
2282f9bae59SDavid Greenman 	/*
2292f9bae59SDavid Greenman 	 * Do the MALLOC before the getnewvnode since doing so afterward
2302f9bae59SDavid Greenman 	 * might cause a bogus v_data pointer to get dereferenced
2312f9bae59SDavid Greenman 	 * elsewhere if MALLOC should block.
2322f9bae59SDavid Greenman 	 */
2332f9bae59SDavid Greenman 	MALLOC(ldep, struct denode *, sizeof(struct denode), M_MSDOSFSNODE, M_WAITOK);
23427a0bc89SDoug Rabson 
23527a0bc89SDoug Rabson 	/*
23627a0bc89SDoug Rabson 	 * Directory entry was not in cache, have to create a vnode and
23727a0bc89SDoug Rabson 	 * copy it from the passed disk buffer.
23827a0bc89SDoug Rabson 	 */
23927a0bc89SDoug Rabson 	/* getnewvnode() does a VREF() on the vnode */
240c3c6d51eSPoul-Henning Kamp 	error = getnewvnode(VT_MSDOSFS, mntp, msdosfs_vnodeop_p, &nvp);
241c3c6d51eSPoul-Henning Kamp 	if (error) {
2422f9bae59SDavid Greenman 		*depp = NULL;
2432f9bae59SDavid Greenman 		FREE(ldep, M_MSDOSFSNODE);
24427a0bc89SDoug Rabson 		return error;
24527a0bc89SDoug Rabson 	}
24627a0bc89SDoug Rabson 	bzero((caddr_t)ldep, sizeof *ldep);
24727a0bc89SDoug Rabson 	nvp->v_data = ldep;
24827a0bc89SDoug Rabson 	ldep->de_vnode = nvp;
24927a0bc89SDoug Rabson 	ldep->de_flag = 0;
25027a0bc89SDoug Rabson 	ldep->de_devvp = 0;
25127a0bc89SDoug Rabson 	ldep->de_lockf = 0;
25227a0bc89SDoug Rabson 	ldep->de_dev = dev;
25327a0bc89SDoug Rabson 	ldep->de_dirclust = dirclust;
25427a0bc89SDoug Rabson 	ldep->de_diroffset = diroffset;
25527a0bc89SDoug Rabson 	fc_purge(ldep, 0);	/* init the fat cache for this denode */
25627a0bc89SDoug Rabson 
25727a0bc89SDoug Rabson 	/*
25827a0bc89SDoug Rabson 	 * Insert the denode into the hash queue and lock the denode so it
25927a0bc89SDoug Rabson 	 * can't be accessed until we've read it in and have done what we
26027a0bc89SDoug Rabson 	 * need to it.
26127a0bc89SDoug Rabson 	 */
2622360b9bfSBruce Evans 	VOP_LOCK(nvp);
26327a0bc89SDoug Rabson 	msdosfs_hashins(ldep);
26427a0bc89SDoug Rabson 
26527a0bc89SDoug Rabson 	/*
26627a0bc89SDoug Rabson 	 * Copy the directory entry into the denode area of the vnode.
26727a0bc89SDoug Rabson 	 */
26827a0bc89SDoug Rabson 	if (dirclust == MSDOSFSROOT && diroffset == MSDOSFSROOT_OFS) {
26927a0bc89SDoug Rabson 		/*
27027a0bc89SDoug Rabson 		 * Directory entry for the root directory. There isn't one,
27127a0bc89SDoug Rabson 		 * so we manufacture one. We should probably rummage
27227a0bc89SDoug Rabson 		 * through the root directory and find a label entry (if it
27327a0bc89SDoug Rabson 		 * exists), and then use the time and date from that entry
27427a0bc89SDoug Rabson 		 * as the time and date for the root denode.
27527a0bc89SDoug Rabson 		 */
27627a0bc89SDoug Rabson 		ldep->de_Attributes = ATTR_DIRECTORY;
27727a0bc89SDoug Rabson 		ldep->de_StartCluster = MSDOSFSROOT;
27827a0bc89SDoug Rabson 		ldep->de_FileSize = pmp->pm_rootdirsize * pmp->pm_BytesPerSec;
27927a0bc89SDoug Rabson 		/*
28027a0bc89SDoug Rabson 		 * fill in time and date so that dos2unixtime() doesn't
28127a0bc89SDoug Rabson 		 * spit up when called from msdosfs_getattr() with root
28227a0bc89SDoug Rabson 		 * denode
28327a0bc89SDoug Rabson 		 */
28427a0bc89SDoug Rabson 		ldep->de_Time = 0x0000;	/* 00:00:00	 */
28527a0bc89SDoug Rabson 		ldep->de_Date = (0 << DD_YEAR_SHIFT) | (1 << DD_MONTH_SHIFT)
28627a0bc89SDoug Rabson 		    | (1 << DD_DAY_SHIFT);
28727a0bc89SDoug Rabson 		/* Jan 1, 1980	 */
28827a0bc89SDoug Rabson 		/* leave the other fields as garbage */
28927a0bc89SDoug Rabson 	} else {
29027a0bc89SDoug Rabson 		bp = NULL;
29127a0bc89SDoug Rabson 		if (!direntptr) {
29227a0bc89SDoug Rabson 			error = readep(pmp, dirclust, diroffset, &bp,
29327a0bc89SDoug Rabson 				       &direntptr);
29427a0bc89SDoug Rabson 			if (error)
29527a0bc89SDoug Rabson 				return error;
29627a0bc89SDoug Rabson 		}
29727a0bc89SDoug Rabson 		DE_INTERNALIZE(ldep, direntptr);
29827a0bc89SDoug Rabson 		if (bp)
29927a0bc89SDoug Rabson 			brelse(bp);
30027a0bc89SDoug Rabson 	}
30127a0bc89SDoug Rabson 
30227a0bc89SDoug Rabson 	/*
30327a0bc89SDoug Rabson 	 * Fill in a few fields of the vnode and finish filling in the
30427a0bc89SDoug Rabson 	 * denode.  Then return the address of the found denode.
30527a0bc89SDoug Rabson 	 */
30627a0bc89SDoug Rabson 	ldep->de_pmp = pmp;
30727a0bc89SDoug Rabson 	ldep->de_devvp = pmp->pm_devvp;
30827a0bc89SDoug Rabson 	ldep->de_refcnt = 1;
30927a0bc89SDoug Rabson 	if (ldep->de_Attributes & ATTR_DIRECTORY) {
31027a0bc89SDoug Rabson 		/*
31127a0bc89SDoug Rabson 		 * Since DOS directory entries that describe directories
31227a0bc89SDoug Rabson 		 * have 0 in the filesize field, we take this opportunity
31327a0bc89SDoug Rabson 		 * to find out the length of the directory and plug it into
31427a0bc89SDoug Rabson 		 * the denode structure.
31527a0bc89SDoug Rabson 		 */
31627a0bc89SDoug Rabson 		u_long size;
31727a0bc89SDoug Rabson 
31827a0bc89SDoug Rabson 		nvp->v_type = VDIR;
31927a0bc89SDoug Rabson 		if (ldep->de_StartCluster == MSDOSFSROOT)
32027a0bc89SDoug Rabson 			nvp->v_flag |= VROOT;
32127a0bc89SDoug Rabson 		else {
32227a0bc89SDoug Rabson 			error = pcbmap(ldep, 0xffff, 0, &size);
32327a0bc89SDoug Rabson 			if (error == E2BIG) {
32427a0bc89SDoug Rabson 				ldep->de_FileSize = size << pmp->pm_cnshift;
32527a0bc89SDoug Rabson 				error = 0;
32627a0bc89SDoug Rabson 			} else
32727a0bc89SDoug Rabson 				printf("deget(): pcbmap returned %d\n", error);
32827a0bc89SDoug Rabson 		}
32927a0bc89SDoug Rabson 	} else
33027a0bc89SDoug Rabson 		nvp->v_type = VREG;
33194a8606fSDoug Rabson 	SETHIGH(ldep->de_modrev, mono_time.tv_sec);
33294a8606fSDoug Rabson 	SETLOW(ldep->de_modrev, mono_time.tv_usec * 4294);
33327a0bc89SDoug Rabson 	VREF(ldep->de_devvp);
33427a0bc89SDoug Rabson 	*depp = ldep;
33527a0bc89SDoug Rabson 	return 0;
33627a0bc89SDoug Rabson }
33727a0bc89SDoug Rabson 
33827a0bc89SDoug Rabson int
33927a0bc89SDoug Rabson deupdat(dep, tp, waitfor)
34027a0bc89SDoug Rabson 	struct denode *dep;
34127a0bc89SDoug Rabson 	struct timespec *tp;
34227a0bc89SDoug Rabson 	int waitfor;
34327a0bc89SDoug Rabson {
34427a0bc89SDoug Rabson 	int error;
34527a0bc89SDoug Rabson 	struct buf *bp;
34627a0bc89SDoug Rabson 	struct direntry *dirp;
34727a0bc89SDoug Rabson 	struct vnode *vp = DETOV(dep);
34827a0bc89SDoug Rabson 
34927a0bc89SDoug Rabson #ifdef MSDOSFS_DEBUG
350f0707215SPoul-Henning Kamp 	printf("deupdat(): dep %p\n", dep);
35127a0bc89SDoug Rabson #endif
35227a0bc89SDoug Rabson 
35327a0bc89SDoug Rabson 	/*
35463e4f22aSBruce Evans 	 * If the denode-modified and update-mtime bits are off,
35563e4f22aSBruce Evans 	 * or this denode is from a readonly filesystem,
35663e4f22aSBruce Evans 	 * or this denode is for a directory,
35763e4f22aSBruce Evans 	 * or the denode represents an open but unlinked file,
35863e4f22aSBruce Evans 	 * then don't do anything.  DOS directory
35963e4f22aSBruce Evans 	 * entries that describe a directory do not ever get
36063e4f22aSBruce Evans 	 * updated.  This is the way DOS treats them.
36127a0bc89SDoug Rabson 	 */
36263e4f22aSBruce Evans 	if ((dep->de_flag & (DE_MODIFIED | DE_UPDATE)) == 0 ||
36327a0bc89SDoug Rabson 	    vp->v_mount->mnt_flag & MNT_RDONLY ||
36427a0bc89SDoug Rabson 	    dep->de_Attributes & ATTR_DIRECTORY ||
36527a0bc89SDoug Rabson 	    dep->de_refcnt <= 0)
36627a0bc89SDoug Rabson 		return 0;
36727a0bc89SDoug Rabson 
36827a0bc89SDoug Rabson 	/*
36927a0bc89SDoug Rabson 	 * Read in the cluster containing the directory entry we want to
37027a0bc89SDoug Rabson 	 * update.
37127a0bc89SDoug Rabson 	 */
372c3c6d51eSPoul-Henning Kamp 	error = readde(dep, &bp, &dirp);
373c3c6d51eSPoul-Henning Kamp 	if (error)
37427a0bc89SDoug Rabson 		return error;
37527a0bc89SDoug Rabson 
37627a0bc89SDoug Rabson 	/*
37763e4f22aSBruce Evans 	 * If the mtime is to be updated, put the passed in time into the
37863e4f22aSBruce Evans 	 * directory entry.
37927a0bc89SDoug Rabson 	 */
380a176f73dSBruce Evans 	if (dep->de_flag & DE_UPDATE) {
381a176f73dSBruce Evans 		dep->de_Attributes |= ATTR_ARCHIVE;
38263e4f22aSBruce Evans 		unix2dostime(tp, &dep->de_Date, &dep->de_Time);
383a176f73dSBruce Evans 	}
38463e4f22aSBruce Evans 
38563e4f22aSBruce Evans 	/*
38663e4f22aSBruce Evans 	 * The mtime is now up to date.  The denode will be unmodifed soon.
38763e4f22aSBruce Evans 	 */
38863e4f22aSBruce Evans 	dep->de_flag &= ~(DE_MODIFIED | DE_UPDATE);
38927a0bc89SDoug Rabson 
39027a0bc89SDoug Rabson 	/*
39127a0bc89SDoug Rabson 	 * Copy the directory entry out of the denode into the cluster it
39227a0bc89SDoug Rabson 	 * came from.
39327a0bc89SDoug Rabson 	 */
39427a0bc89SDoug Rabson 	DE_EXTERNALIZE(dirp, dep);
39527a0bc89SDoug Rabson 
39627a0bc89SDoug Rabson 	/*
39727a0bc89SDoug Rabson 	 * Write the cluster back to disk.  If they asked for us to wait
39827a0bc89SDoug Rabson 	 * for the write to complete, then use bwrite() otherwise use
39927a0bc89SDoug Rabson 	 * bdwrite().
40027a0bc89SDoug Rabson 	 */
40127a0bc89SDoug Rabson 	error = 0;		/* note that error is 0 from above, but ... */
40227a0bc89SDoug Rabson 	if (waitfor)
40327a0bc89SDoug Rabson 		error = bwrite(bp);
40427a0bc89SDoug Rabson 	else
40527a0bc89SDoug Rabson 		bdwrite(bp);
40627a0bc89SDoug Rabson 	return error;
40727a0bc89SDoug Rabson }
40827a0bc89SDoug Rabson 
40927a0bc89SDoug Rabson /*
41027a0bc89SDoug Rabson  * Truncate the file described by dep to the length specified by length.
41127a0bc89SDoug Rabson  */
41227a0bc89SDoug Rabson int
41327a0bc89SDoug Rabson detrunc(dep, length, flags, cred, p)
41427a0bc89SDoug Rabson 	struct denode *dep;
41527a0bc89SDoug Rabson 	u_long length;
41627a0bc89SDoug Rabson 	int flags;
41727a0bc89SDoug Rabson 	struct ucred *cred;
41827a0bc89SDoug Rabson 	struct proc *p;
41927a0bc89SDoug Rabson {
42027a0bc89SDoug Rabson 	int error;
42127a0bc89SDoug Rabson 	int allerror;
42227a0bc89SDoug Rabson 	int vflags;
42327a0bc89SDoug Rabson 	u_long eofentry;
42427a0bc89SDoug Rabson 	u_long chaintofree;
42527a0bc89SDoug Rabson 	daddr_t bn;
42627a0bc89SDoug Rabson 	int boff;
42727a0bc89SDoug Rabson 	int isadir = dep->de_Attributes & ATTR_DIRECTORY;
42827a0bc89SDoug Rabson 	struct buf *bp;
42927a0bc89SDoug Rabson 	struct msdosfsmount *pmp = dep->de_pmp;
430c3c6d51eSPoul-Henning Kamp 	struct timespec ts;
43127a0bc89SDoug Rabson 
43227a0bc89SDoug Rabson #ifdef MSDOSFS_DEBUG
43327a0bc89SDoug Rabson 	printf("detrunc(): file %s, length %d, flags %d\n", dep->de_Name, length, flags);
43427a0bc89SDoug Rabson #endif
43527a0bc89SDoug Rabson 
43627a0bc89SDoug Rabson 	/*
43727a0bc89SDoug Rabson 	 * Disallow attempts to truncate the root directory since it is of
43827a0bc89SDoug Rabson 	 * fixed size.  That's just the way dos filesystems are.  We use
43927a0bc89SDoug Rabson 	 * the VROOT bit in the vnode because checking for the directory
44027a0bc89SDoug Rabson 	 * bit and a startcluster of 0 in the denode is not adequate to
44127a0bc89SDoug Rabson 	 * recognize the root directory at this point in a file or
44227a0bc89SDoug Rabson 	 * directory's life.
44327a0bc89SDoug Rabson 	 */
44427a0bc89SDoug Rabson 	if (DETOV(dep)->v_flag & VROOT) {
445c3c6d51eSPoul-Henning Kamp 		printf(
446c3c6d51eSPoul-Henning Kamp     "detrunc(): can't truncate root directory, clust %ld, offset %ld\n",
44727a0bc89SDoug Rabson 		    dep->de_dirclust, dep->de_diroffset);
44827a0bc89SDoug Rabson 		return EINVAL;
44927a0bc89SDoug Rabson 	}
45027a0bc89SDoug Rabson 
45127a0bc89SDoug Rabson 
452bd7e5f99SJohn Dyson 	if (dep->de_FileSize < length) {
453bd7e5f99SJohn Dyson 		vnode_pager_setsize(DETOV(dep), length);
45427a0bc89SDoug Rabson 		return deextend(dep, length, cred);
455bd7e5f99SJohn Dyson 	}
45627a0bc89SDoug Rabson 
45727a0bc89SDoug Rabson 	/*
45827a0bc89SDoug Rabson 	 * If the desired length is 0 then remember the starting cluster of
45927a0bc89SDoug Rabson 	 * the file and set the StartCluster field in the directory entry
46027a0bc89SDoug Rabson 	 * to 0.  If the desired length is not zero, then get the number of
46127a0bc89SDoug Rabson 	 * the last cluster in the shortened file.  Then get the number of
46227a0bc89SDoug Rabson 	 * the first cluster in the part of the file that is to be freed.
46327a0bc89SDoug Rabson 	 * Then set the next cluster pointer in the last cluster of the
46427a0bc89SDoug Rabson 	 * file to CLUST_EOFE.
46527a0bc89SDoug Rabson 	 */
46627a0bc89SDoug Rabson 	if (length == 0) {
46727a0bc89SDoug Rabson 		chaintofree = dep->de_StartCluster;
46827a0bc89SDoug Rabson 		dep->de_StartCluster = 0;
46927a0bc89SDoug Rabson 		eofentry = ~0;
47027a0bc89SDoug Rabson 	} else {
471c3c6d51eSPoul-Henning Kamp 		error = pcbmap(dep, de_clcount(pmp, length) - 1, 0, &eofentry);
472c3c6d51eSPoul-Henning Kamp 		if (error) {
47327a0bc89SDoug Rabson #ifdef MSDOSFS_DEBUG
47427a0bc89SDoug Rabson 			printf("detrunc(): pcbmap fails %d\n", error);
47527a0bc89SDoug Rabson #endif
47627a0bc89SDoug Rabson 			return error;
47727a0bc89SDoug Rabson 		}
47827a0bc89SDoug Rabson 	}
47927a0bc89SDoug Rabson 
48027a0bc89SDoug Rabson 	fc_purge(dep, (length + pmp->pm_crbomask) >> pmp->pm_cnshift);
48127a0bc89SDoug Rabson 
48227a0bc89SDoug Rabson 	/*
48327a0bc89SDoug Rabson 	 * If the new length is not a multiple of the cluster size then we
48427a0bc89SDoug Rabson 	 * must zero the tail end of the new last cluster in case it
48527a0bc89SDoug Rabson 	 * becomes part of the file again because of a seek.
48627a0bc89SDoug Rabson 	 */
48727a0bc89SDoug Rabson 	if ((boff = length & pmp->pm_crbomask) != 0) {
48827a0bc89SDoug Rabson 		/*
48927a0bc89SDoug Rabson 		 * should read from file vnode or filesystem vnode
49027a0bc89SDoug Rabson 		 * depending on if file or dir
49127a0bc89SDoug Rabson 		 */
49227a0bc89SDoug Rabson 		if (isadir) {
49327a0bc89SDoug Rabson 			bn = cntobn(pmp, eofentry);
49427a0bc89SDoug Rabson 			error = bread(pmp->pm_devvp, bn, pmp->pm_bpcluster,
49527a0bc89SDoug Rabson 			    NOCRED, &bp);
49627a0bc89SDoug Rabson 		} else {
49727a0bc89SDoug Rabson 			bn = de_blk(pmp, length);
49827a0bc89SDoug Rabson 			error = bread(DETOV(dep), bn, pmp->pm_bpcluster,
49927a0bc89SDoug Rabson 			    NOCRED, &bp);
50027a0bc89SDoug Rabson 		}
50127a0bc89SDoug Rabson 		if (error) {
50227a0bc89SDoug Rabson #ifdef MSDOSFS_DEBUG
50327a0bc89SDoug Rabson 			printf("detrunc(): bread fails %d\n", error);
50427a0bc89SDoug Rabson #endif
50527a0bc89SDoug Rabson 			return error;
50627a0bc89SDoug Rabson 		}
50727a0bc89SDoug Rabson 		/*
50827a0bc89SDoug Rabson 		 * is this the right place for it?
50927a0bc89SDoug Rabson 		 */
51027a0bc89SDoug Rabson 		bzero(bp->b_data + boff, pmp->pm_bpcluster - boff);
51127a0bc89SDoug Rabson 		if (flags & IO_SYNC)
51227a0bc89SDoug Rabson 			bwrite(bp);
51327a0bc89SDoug Rabson 		else
51427a0bc89SDoug Rabson 			bdwrite(bp);
51527a0bc89SDoug Rabson 	}
51627a0bc89SDoug Rabson 
51727a0bc89SDoug Rabson 	/*
51827a0bc89SDoug Rabson 	 * Write out the updated directory entry.  Even if the update fails
51927a0bc89SDoug Rabson 	 * we free the trailing clusters.
52027a0bc89SDoug Rabson 	 */
52127a0bc89SDoug Rabson 	dep->de_FileSize = length;
52227a0bc89SDoug Rabson 	dep->de_flag |= DE_UPDATE;
52327a0bc89SDoug Rabson 	vflags = (length > 0 ? V_SAVE : 0) | V_SAVEMETA;
52427a0bc89SDoug Rabson 	vinvalbuf(DETOV(dep), vflags, cred, p, 0, 0);
525bd7e5f99SJohn Dyson 	vnode_pager_setsize(DETOV(dep), length);
526c3c6d51eSPoul-Henning Kamp 	TIMEVAL_TO_TIMESPEC(&time, &ts);
527c3c6d51eSPoul-Henning Kamp 	allerror = deupdat(dep, &ts, 1);
52827a0bc89SDoug Rabson #ifdef MSDOSFS_DEBUG
52927a0bc89SDoug Rabson 	printf("detrunc(): allerror %d, eofentry %d\n",
53027a0bc89SDoug Rabson 	       allerror, eofentry);
53127a0bc89SDoug Rabson #endif
53227a0bc89SDoug Rabson 
53327a0bc89SDoug Rabson 	/*
53427a0bc89SDoug Rabson 	 * If we need to break the cluster chain for the file then do it
53527a0bc89SDoug Rabson 	 * now.
53627a0bc89SDoug Rabson 	 */
53727a0bc89SDoug Rabson 	if (eofentry != ~0) {
53827a0bc89SDoug Rabson 		error = fatentry(FAT_GET_AND_SET, pmp, eofentry,
53927a0bc89SDoug Rabson 				 &chaintofree, CLUST_EOFE);
54027a0bc89SDoug Rabson 		if (error) {
54127a0bc89SDoug Rabson #ifdef MSDOSFS_DEBUG
54227a0bc89SDoug Rabson 			printf("detrunc(): fatentry errors %d\n", error);
54327a0bc89SDoug Rabson #endif
54427a0bc89SDoug Rabson 			return error;
54527a0bc89SDoug Rabson 		}
54627a0bc89SDoug Rabson 		fc_setcache(dep, FC_LASTFC, (length - 1) >> pmp->pm_cnshift,
54727a0bc89SDoug Rabson 			    eofentry);
54827a0bc89SDoug Rabson 	}
54927a0bc89SDoug Rabson 
55027a0bc89SDoug Rabson 	/*
55127a0bc89SDoug Rabson 	 * Now free the clusters removed from the file because of the
55227a0bc89SDoug Rabson 	 * truncation.
55327a0bc89SDoug Rabson 	 */
55427a0bc89SDoug Rabson 	if (chaintofree != 0 && !MSDOSFSEOF(chaintofree))
55527a0bc89SDoug Rabson 		freeclusterchain(pmp, chaintofree);
55627a0bc89SDoug Rabson 
55727a0bc89SDoug Rabson 	return allerror;
55827a0bc89SDoug Rabson }
55927a0bc89SDoug Rabson 
56027a0bc89SDoug Rabson /*
56127a0bc89SDoug Rabson  * Extend the file described by dep to length specified by length.
56227a0bc89SDoug Rabson  */
56327a0bc89SDoug Rabson int
56427a0bc89SDoug Rabson deextend(dep, length, cred)
56527a0bc89SDoug Rabson 	struct denode *dep;
56627a0bc89SDoug Rabson 	off_t length;
56727a0bc89SDoug Rabson 	struct ucred *cred;
56827a0bc89SDoug Rabson {
56927a0bc89SDoug Rabson 	struct msdosfsmount *pmp = dep->de_pmp;
57027a0bc89SDoug Rabson 	u_long count;
57127a0bc89SDoug Rabson 	int error;
572c3c6d51eSPoul-Henning Kamp 	struct timespec ts;
57327a0bc89SDoug Rabson 
57427a0bc89SDoug Rabson 	/*
57527a0bc89SDoug Rabson 	 * The root of a DOS filesystem cannot be extended.
57627a0bc89SDoug Rabson 	 */
57727a0bc89SDoug Rabson 	if (DETOV(dep)->v_flag & VROOT)
57827a0bc89SDoug Rabson 		return EINVAL;
57927a0bc89SDoug Rabson 
58027a0bc89SDoug Rabson 	/*
58127a0bc89SDoug Rabson 	 * Directories can only be extended by the superuser.
58227a0bc89SDoug Rabson 	 * Is this really important?
58327a0bc89SDoug Rabson 	 */
58427a0bc89SDoug Rabson 	if (dep->de_Attributes & ATTR_DIRECTORY) {
585c3c6d51eSPoul-Henning Kamp 		error = suser(cred, NULL);
586c3c6d51eSPoul-Henning Kamp 		if (error)
58727a0bc89SDoug Rabson 			return error;
58827a0bc89SDoug Rabson 	}
58927a0bc89SDoug Rabson 
59027a0bc89SDoug Rabson 	if (length <= dep->de_FileSize)
59127a0bc89SDoug Rabson 		panic("deextend: file too large");
59227a0bc89SDoug Rabson 
59327a0bc89SDoug Rabson 	/*
59427a0bc89SDoug Rabson 	 * Compute the number of clusters to allocate.
59527a0bc89SDoug Rabson 	 */
59627a0bc89SDoug Rabson 	count = de_clcount(pmp, length) - de_clcount(pmp, dep->de_FileSize);
59727a0bc89SDoug Rabson 	if (count > 0) {
59827a0bc89SDoug Rabson 		if (count > pmp->pm_freeclustercount)
59927a0bc89SDoug Rabson 			return ENOSPC;
600c3c6d51eSPoul-Henning Kamp 		error = extendfile(dep, count, NULL, NULL, DE_CLEAR);
601c3c6d51eSPoul-Henning Kamp 		if (error) {
60227a0bc89SDoug Rabson 			/* truncate the added clusters away again */
60327a0bc89SDoug Rabson 			(void) detrunc(dep, dep->de_FileSize, 0, cred, NULL);
60427a0bc89SDoug Rabson 			return error;
60527a0bc89SDoug Rabson 		}
60627a0bc89SDoug Rabson 	}
60727a0bc89SDoug Rabson 
60827a0bc89SDoug Rabson 	dep->de_flag |= DE_UPDATE;
60927a0bc89SDoug Rabson 	dep->de_FileSize = length;
610c3c6d51eSPoul-Henning Kamp 	TIMEVAL_TO_TIMESPEC(&time, &ts);
611c3c6d51eSPoul-Henning Kamp 	return deupdat(dep, &ts, 1);
61227a0bc89SDoug Rabson }
61327a0bc89SDoug Rabson 
61427a0bc89SDoug Rabson /*
61527a0bc89SDoug Rabson  * Move a denode to its correct hash queue after the file it represents has
61627a0bc89SDoug Rabson  * been moved to a new directory.
61727a0bc89SDoug Rabson  */
61827a0bc89SDoug Rabson int reinsert(dep)
61927a0bc89SDoug Rabson 	struct denode *dep;
62027a0bc89SDoug Rabson {
62127a0bc89SDoug Rabson 	/*
62227a0bc89SDoug Rabson 	 * Fix up the denode cache.  If the denode is for a directory,
62327a0bc89SDoug Rabson 	 * there is nothing to do since the hash is based on the starting
62427a0bc89SDoug Rabson 	 * cluster of the directory file and that hasn't changed.  If for a
62527a0bc89SDoug Rabson 	 * file the hash is based on the location of the directory entry,
62627a0bc89SDoug Rabson 	 * so we must remove it from the cache and re-enter it with the
62727a0bc89SDoug Rabson 	 * hash based on the new location of the directory entry.
62827a0bc89SDoug Rabson 	 */
62927a0bc89SDoug Rabson 	if ((dep->de_Attributes & ATTR_DIRECTORY) == 0) {
63027a0bc89SDoug Rabson 		msdosfs_hashrem(dep);
63127a0bc89SDoug Rabson 		msdosfs_hashins(dep);
63227a0bc89SDoug Rabson 	}
63327a0bc89SDoug Rabson 	return 0;
63427a0bc89SDoug Rabson }
63527a0bc89SDoug Rabson 
63627a0bc89SDoug Rabson int
63727a0bc89SDoug Rabson msdosfs_reclaim(ap)
63827a0bc89SDoug Rabson 	struct vop_reclaim_args /* {
63927a0bc89SDoug Rabson 		struct vnode *a_vp;
64027a0bc89SDoug Rabson 	} */ *ap;
64127a0bc89SDoug Rabson {
64227a0bc89SDoug Rabson 	struct vnode *vp = ap->a_vp;
64327a0bc89SDoug Rabson 	struct denode *dep = VTODE(vp);
64427a0bc89SDoug Rabson 
64527a0bc89SDoug Rabson #ifdef MSDOSFS_DEBUG
646f0707215SPoul-Henning Kamp 	printf("msdosfs_reclaim(): dep %p, file %s, refcnt %ld\n",
64727a0bc89SDoug Rabson 	    dep, dep->de_Name, dep->de_refcnt);
64827a0bc89SDoug Rabson #endif
64927a0bc89SDoug Rabson 
65027a0bc89SDoug Rabson 	if (prtactive && vp->v_usecount != 0)
65127a0bc89SDoug Rabson 		vprint("msdosfs_reclaim(): pushing active", vp);
65227a0bc89SDoug Rabson 
65327a0bc89SDoug Rabson 	/*
65427a0bc89SDoug Rabson 	 * Remove the denode from the denode hash chain we are in.
65527a0bc89SDoug Rabson 	 */
65627a0bc89SDoug Rabson 	msdosfs_hashrem(dep);
65727a0bc89SDoug Rabson 
65827a0bc89SDoug Rabson 	cache_purge(vp);
65927a0bc89SDoug Rabson 	/*
66027a0bc89SDoug Rabson 	 * Indicate that one less file on the filesystem is open.
66127a0bc89SDoug Rabson 	 */
66227a0bc89SDoug Rabson 	if (dep->de_devvp) {
66327a0bc89SDoug Rabson 		vrele(dep->de_devvp);
66427a0bc89SDoug Rabson 		dep->de_devvp = 0;
66527a0bc89SDoug Rabson 	}
66627a0bc89SDoug Rabson 
66727a0bc89SDoug Rabson 	dep->de_flag = 0;
66827a0bc89SDoug Rabson 
66927a0bc89SDoug Rabson 	FREE(dep, M_MSDOSFSNODE);
67027a0bc89SDoug Rabson 	vp->v_data = NULL;
67127a0bc89SDoug Rabson 
67227a0bc89SDoug Rabson 	return 0;
67327a0bc89SDoug Rabson }
67427a0bc89SDoug Rabson 
67527a0bc89SDoug Rabson int
67627a0bc89SDoug Rabson msdosfs_inactive(ap)
67727a0bc89SDoug Rabson 	struct vop_inactive_args /* {
67827a0bc89SDoug Rabson 		struct vnode *a_vp;
67927a0bc89SDoug Rabson 	} */ *ap;
68027a0bc89SDoug Rabson {
68127a0bc89SDoug Rabson 	struct vnode *vp = ap->a_vp;
68227a0bc89SDoug Rabson 	struct denode *dep = VTODE(vp);
68327a0bc89SDoug Rabson 	int error = 0;
684c3c6d51eSPoul-Henning Kamp 	struct timespec ts;
68527a0bc89SDoug Rabson 
68627a0bc89SDoug Rabson #ifdef MSDOSFS_DEBUG
687f0707215SPoul-Henning Kamp 	printf("msdosfs_inactive(): dep %p, de_Name[0] %x\n", dep, dep->de_Name[0]);
68827a0bc89SDoug Rabson #endif
68927a0bc89SDoug Rabson 
69027a0bc89SDoug Rabson 	if (prtactive && vp->v_usecount != 0)
69127a0bc89SDoug Rabson 		vprint("msdosfs_inactive(): pushing active", vp);
69227a0bc89SDoug Rabson 
69327a0bc89SDoug Rabson 	/*
69427a0bc89SDoug Rabson 	 * Get rid of denodes related to stale file handles. Hmmm, what
69527a0bc89SDoug Rabson 	 * does this really do?
69627a0bc89SDoug Rabson 	 */
69727a0bc89SDoug Rabson 	if (dep->de_Name[0] == SLOT_DELETED) {
69827a0bc89SDoug Rabson 		if ((vp->v_flag & VXLOCK) == 0)
69927a0bc89SDoug Rabson 			vgone(vp);
70027a0bc89SDoug Rabson 		return 0;
70127a0bc89SDoug Rabson 	}
70227a0bc89SDoug Rabson 
70327a0bc89SDoug Rabson 	/*
70427a0bc89SDoug Rabson 	 * If the file has been deleted and it is on a read/write
70527a0bc89SDoug Rabson 	 * filesystem, then truncate the file, and mark the directory slot
70627a0bc89SDoug Rabson 	 * as empty.  (This may not be necessary for the dos filesystem.)
70727a0bc89SDoug Rabson 	 */
70827a0bc89SDoug Rabson #ifdef MSDOSFS_DEBUG
709f0707215SPoul-Henning Kamp 	printf("msdosfs_inactive(): dep %p, refcnt %ld, mntflag %x, MNT_RDONLY %x\n",
71027a0bc89SDoug Rabson 	       dep, dep->de_refcnt, vp->v_mount->mnt_flag, MNT_RDONLY);
71127a0bc89SDoug Rabson #endif
71227a0bc89SDoug Rabson 	VOP_LOCK(vp);
71327a0bc89SDoug Rabson 	if (dep->de_refcnt <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
71427a0bc89SDoug Rabson 		error = detrunc(dep, (u_long) 0, 0, NOCRED, NULL);
71527a0bc89SDoug Rabson 		dep->de_flag |= DE_UPDATE;
71627a0bc89SDoug Rabson 		dep->de_Name[0] = SLOT_DELETED;
71727a0bc89SDoug Rabson 	}
718a176f73dSBruce Evans 	if (dep->de_flag & (DE_MODIFIED | DE_UPDATE)) {
719c3c6d51eSPoul-Henning Kamp 		TIMEVAL_TO_TIMESPEC(&time, &ts);
720a176f73dSBruce Evans 		deupdat(dep, &ts, 0);
721a176f73dSBruce Evans 	}
72227a0bc89SDoug Rabson 	VOP_UNLOCK(vp);
72327a0bc89SDoug Rabson 	dep->de_flag = 0;
72427a0bc89SDoug Rabson 
72527a0bc89SDoug Rabson 	/*
72627a0bc89SDoug Rabson 	 * If we are done with the denode, then reclaim it so that it can
72727a0bc89SDoug Rabson 	 * be reused now.
72827a0bc89SDoug Rabson 	 */
72927a0bc89SDoug Rabson #ifdef MSDOSFS_DEBUG
73027a0bc89SDoug Rabson 	printf("msdosfs_inactive(): v_usecount %d, de_Name[0] %x\n", vp->v_usecount,
73127a0bc89SDoug Rabson 	       dep->de_Name[0]);
73227a0bc89SDoug Rabson #endif
73327a0bc89SDoug Rabson 	if (vp->v_usecount == 0 && dep->de_Name[0] == SLOT_DELETED)
73427a0bc89SDoug Rabson 		vgone(vp);
73527a0bc89SDoug Rabson 	return error;
73627a0bc89SDoug Rabson }
737