Annotation of src/sys/fs/msdosfs/msdosfs_denode.c, Revision 1.8.2.5
1.8.2.5 ! yamt 1: /* $NetBSD: msdosfs_denode.c,v 1.8.2.4 2007/09/03 14:40:24 yamt Exp $ */
1.1 jdolecek 2:
3: /*-
4: * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
5: * Copyright (C) 1994, 1995, 1997 TooLs GmbH.
6: * All rights reserved.
7: * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by TooLs GmbH.
20: * 4. The name of TooLs GmbH may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26: * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33: */
34: /*
35: * Written by Paul Popelka (paulp@uts.amdahl.com)
36: *
37: * You can do anything you want with this software, just don't say you wrote
38: * it, and don't remove this notice.
39: *
40: * This software is provided "as is".
41: *
42: * The author supplies this software to be publicly redistributed on the
43: * understanding that the author is not responsible for the correct
44: * functioning of this software in any circumstances and is not liable for
45: * any damages caused by this software.
46: *
47: * October 1992
48: */
49:
50: #include <sys/cdefs.h>
1.8.2.5 ! yamt 51: __KERNEL_RCSID(0, "$NetBSD: msdosfs_denode.c,v 1.8.2.4 2007/09/03 14:40:24 yamt Exp $");
1.1 jdolecek 52:
53: #include <sys/param.h>
54: #include <sys/systm.h>
55: #include <sys/mount.h>
56: #include <sys/malloc.h>
57: #include <sys/pool.h>
58: #include <sys/proc.h>
59: #include <sys/buf.h>
60: #include <sys/vnode.h>
61: #include <sys/kernel.h> /* defines "time" */
62: #include <sys/dirent.h>
63: #include <sys/namei.h>
1.8.2.1 yamt 64: #include <sys/kauth.h>
1.1 jdolecek 65:
66: #include <uvm/uvm_extern.h>
67:
68: #include <fs/msdosfs/bpb.h>
69: #include <fs/msdosfs/msdosfsmount.h>
70: #include <fs/msdosfs/direntry.h>
71: #include <fs/msdosfs/denode.h>
72: #include <fs/msdosfs/fat.h>
73:
74: LIST_HEAD(ihashhead, denode) *dehashtbl;
75: u_long dehash; /* size of hash table - 1 */
76: #define DEHASH(dev, dcl, doff) \
77: (((dev) + (dcl) + (doff) / sizeof(struct direntry)) & dehash)
78:
79: struct simplelock msdosfs_ihash_slock;
80:
1.8.2.4 yamt 81: struct pool msdosfs_denode_pool;
1.1 jdolecek 82:
83: extern int prtactive;
84:
1.8 yamt 85: static const struct genfs_ops msdosfs_genfsops = {
86: .gop_size = genfs_size,
87: .gop_alloc = msdosfs_gop_alloc,
88: .gop_write = genfs_gop_write,
1.8.2.1 yamt 89: .gop_markupdate = msdosfs_gop_markupdate,
1.1 jdolecek 90: };
91:
1.8.2.1 yamt 92: static struct denode *msdosfs_hashget(dev_t, u_long, u_long);
93: static void msdosfs_hashins(struct denode *);
94: static void msdosfs_hashrem(struct denode *);
1.1 jdolecek 95:
1.5 atatat 96: MALLOC_DECLARE(M_MSDOSFSFAT);
97:
1.1 jdolecek 98: void
99: msdosfs_init()
100: {
1.8.2.4 yamt 101:
1.5 atatat 102: malloc_type_attach(M_MSDOSFSMNT);
103: malloc_type_attach(M_MSDOSFSFAT);
1.8.2.5 ! yamt 104: malloc_type_attach(M_MSDOSFSTMP);
1.7 atatat 105: pool_init(&msdosfs_denode_pool, sizeof(struct denode), 0, 0, 0,
1.8.2.4 yamt 106: "msdosnopl", &pool_allocator_nointr, IPL_NONE);
1.1 jdolecek 107: dehashtbl = hashinit(desiredvnodes / 2, HASH_LIST, M_MSDOSFSMNT,
108: M_WAITOK, &dehash);
109: simple_lock_init(&msdosfs_ihash_slock);
110: }
111:
112: /*
113: * Reinitialize inode hash table.
114: */
115:
116: void
117: msdosfs_reinit()
118: {
119: struct denode *dep;
120: struct ihashhead *oldhash, *hash;
121: u_long oldmask, mask, val;
122: int i;
123:
124: hash = hashinit(desiredvnodes / 2, HASH_LIST, M_MSDOSFSMNT, M_WAITOK,
125: &mask);
126:
127: simple_lock(&msdosfs_ihash_slock);
128: oldhash = dehashtbl;
129: oldmask = dehash;
130: dehashtbl = hash;
131: dehash = mask;
132: for (i = 0; i <= oldmask; i++) {
133: while ((dep = LIST_FIRST(&oldhash[i])) != NULL) {
134: LIST_REMOVE(dep, de_hash);
135: val = DEHASH(dep->de_dev, dep->de_dirclust,
136: dep->de_diroffset);
137: LIST_INSERT_HEAD(&hash[val], dep, de_hash);
138: }
139: }
140: simple_unlock(&msdosfs_ihash_slock);
141: hashdone(oldhash, M_MSDOSFSMNT);
142: }
143:
144: void
145: msdosfs_done()
146: {
147: hashdone(dehashtbl, M_MSDOSFSMNT);
148: pool_destroy(&msdosfs_denode_pool);
1.8.2.5 ! yamt 149: malloc_type_detach(M_MSDOSFSTMP);
1.5 atatat 150: malloc_type_detach(M_MSDOSFSFAT);
151: malloc_type_detach(M_MSDOSFSMNT);
1.1 jdolecek 152: }
153:
154: static struct denode *
1.4 fvdl 155: msdosfs_hashget(dev, dirclust, diroff)
1.1 jdolecek 156: dev_t dev;
157: u_long dirclust;
158: u_long diroff;
159: {
160: struct denode *dep;
161: struct vnode *vp;
162:
163: loop:
164: simple_lock(&msdosfs_ihash_slock);
165: LIST_FOREACH(dep, &dehashtbl[DEHASH(dev, dirclust, diroff)], de_hash) {
166: if (dirclust == dep->de_dirclust &&
167: diroff == dep->de_diroffset &&
168: dev == dep->de_dev &&
169: dep->de_refcnt != 0) {
170: vp = DETOV(dep);
171: simple_lock(&vp->v_interlock);
172: simple_unlock(&msdosfs_ihash_slock);
1.3 thorpej 173: if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK))
1.1 jdolecek 174: goto loop;
175: return (dep);
176: }
177: }
178: simple_unlock(&msdosfs_ihash_slock);
179: return (NULL);
180: }
181:
182: static void
183: msdosfs_hashins(dep)
184: struct denode *dep;
185: {
186: struct ihashhead *depp;
187: int val;
188:
189: simple_lock(&msdosfs_ihash_slock);
190: val = DEHASH(dep->de_dev, dep->de_dirclust, dep->de_diroffset);
191: depp = &dehashtbl[val];
192: LIST_INSERT_HEAD(depp, dep, de_hash);
193: simple_unlock(&msdosfs_ihash_slock);
194: }
195:
196: static void
197: msdosfs_hashrem(dep)
198: struct denode *dep;
199: {
200: simple_lock(&msdosfs_ihash_slock);
201: LIST_REMOVE(dep, de_hash);
202: simple_unlock(&msdosfs_ihash_slock);
203: }
204:
205: /*
206: * If deget() succeeds it returns with the gotten denode locked().
207: *
208: * pmp - address of msdosfsmount structure of the filesystem containing
209: * the denode of interest. The pm_dev field and the address of
210: * the msdosfsmount structure are used.
211: * dirclust - which cluster bp contains, if dirclust is 0 (root directory)
212: * diroffset is relative to the beginning of the root directory,
213: * otherwise it is cluster relative.
214: * diroffset - offset past begin of cluster of denode we want
215: * depp - returns the address of the gotten denode.
216: */
217: int
218: deget(pmp, dirclust, diroffset, depp)
219: struct msdosfsmount *pmp; /* so we know the maj/min number */
220: u_long dirclust; /* cluster this dir entry came from */
221: u_long diroffset; /* index of entry within the cluster */
222: struct denode **depp; /* returns the addr of the gotten denode */
223: {
224: int error;
1.8.2.1 yamt 225: extern int (**msdosfs_vnodeop_p)(void *);
1.1 jdolecek 226: struct direntry *direntptr;
227: struct denode *ldep;
228: struct vnode *nvp;
229: struct buf *bp;
230:
231: #ifdef MSDOSFS_DEBUG
232: printf("deget(pmp %p, dirclust %lu, diroffset %lx, depp %p)\n",
233: pmp, dirclust, diroffset, depp);
234: #endif
235:
236: /*
237: * On FAT32 filesystems, root is a (more or less) normal
238: * directory
239: */
240: if (FAT32(pmp) && dirclust == MSDOSFSROOT)
241: dirclust = pmp->pm_rootdirblk;
242:
243: /*
244: * See if the denode is in the denode cache. Use the location of
245: * the directory entry to compute the hash value. For subdir use
246: * address of "." entry. For root dir (if not FAT32) use cluster
247: * MSDOSFSROOT, offset MSDOSFSROOT_OFS
248: *
249: * NOTE: The check for de_refcnt > 0 below insures the denode being
250: * examined does not represent an unlinked but still open file.
251: * These files are not to be accessible even when the directory
252: * entry that represented the file happens to be reused while the
253: * deleted file is still open.
254: */
1.4 fvdl 255: ldep = msdosfs_hashget(pmp->pm_dev, dirclust, diroffset);
1.1 jdolecek 256: if (ldep) {
257: *depp = ldep;
258: return (0);
259: }
260:
261: /*
262: * Directory entry was not in cache, have to create a vnode and
263: * copy it from the passed disk buffer.
264: */
265: /* getnewvnode() does a VREF() on the vnode */
266: error = getnewvnode(VT_MSDOSFS, pmp->pm_mountp,
267: msdosfs_vnodeop_p, &nvp);
268: if (error) {
269: *depp = 0;
270: return (error);
271: }
272: ldep = pool_get(&msdosfs_denode_pool, PR_WAITOK);
273: memset(ldep, 0, sizeof *ldep);
274: nvp->v_data = ldep;
275: ldep->de_vnode = nvp;
276: ldep->de_flag = 0;
277: ldep->de_devvp = 0;
278: ldep->de_lockf = 0;
279: ldep->de_dev = pmp->pm_dev;
280: ldep->de_dirclust = dirclust;
281: ldep->de_diroffset = diroffset;
282: fc_purge(ldep, 0); /* init the fat cache for this denode */
283:
284: /*
285: * Insert the denode into the hash queue and lock the denode so it
286: * can't be accessed until we've read it in and have done what we
287: * need to it.
288: */
289: vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY);
1.8.2.5 ! yamt 290: genfs_node_init(nvp, &msdosfs_genfsops);
1.1 jdolecek 291: msdosfs_hashins(ldep);
292:
293: ldep->de_pmp = pmp;
294: ldep->de_devvp = pmp->pm_devvp;
295: ldep->de_refcnt = 1;
296: /*
297: * Copy the directory entry into the denode area of the vnode.
298: */
299: if ((dirclust == MSDOSFSROOT
300: || (FAT32(pmp) && dirclust == pmp->pm_rootdirblk))
301: && diroffset == MSDOSFSROOT_OFS) {
302: /*
303: * Directory entry for the root directory. There isn't one,
304: * so we manufacture one. We should probably rummage
305: * through the root directory and find a label entry (if it
306: * exists), and then use the time and date from that entry
307: * as the time and date for the root denode.
308: */
1.8.2.5 ! yamt 309: nvp->v_vflag |= VV_ROOT; /* should be further down XXX */
1.1 jdolecek 310:
311: ldep->de_Attributes = ATTR_DIRECTORY;
312: if (FAT32(pmp))
313: ldep->de_StartCluster = pmp->pm_rootdirblk;
314: /* de_FileSize will be filled in further down */
315: else {
316: ldep->de_StartCluster = MSDOSFSROOT;
317: ldep->de_FileSize = pmp->pm_rootdirsize * pmp->pm_BytesPerSec;
318: }
319: /*
320: * fill in time and date so that dos2unixtime() doesn't
321: * spit up when called from msdosfs_getattr() with root
322: * denode
323: */
324: ldep->de_CHun = 0;
325: ldep->de_CTime = 0x0000; /* 00:00:00 */
326: ldep->de_CDate = (0 << DD_YEAR_SHIFT) | (1 << DD_MONTH_SHIFT)
327: | (1 << DD_DAY_SHIFT);
328: /* Jan 1, 1980 */
329: ldep->de_ADate = ldep->de_CDate;
330: ldep->de_MTime = ldep->de_CTime;
331: ldep->de_MDate = ldep->de_CDate;
332: /* leave the other fields as garbage */
333: } else {
334: error = readep(pmp, dirclust, diroffset, &bp, &direntptr);
1.8.2.5 ! yamt 335: if (error) {
! 336: ldep->de_devvp = NULL;
! 337: ldep->de_Name[0] = SLOT_DELETED;
! 338: vput(nvp);
1.1 jdolecek 339: return (error);
1.8.2.5 ! yamt 340: }
1.1 jdolecek 341: DE_INTERNALIZE(ldep, direntptr);
1.8.2.5 ! yamt 342: brelse(bp, 0);
1.1 jdolecek 343: }
344:
345: /*
346: * Fill in a few fields of the vnode and finish filling in the
347: * denode. Then return the address of the found denode.
348: */
349: if (ldep->de_Attributes & ATTR_DIRECTORY) {
350: /*
351: * Since DOS directory entries that describe directories
352: * have 0 in the filesize field, we take this opportunity
353: * to find out the length of the directory and plug it into
354: * the denode structure.
355: */
356: u_long size;
357:
358: nvp->v_type = VDIR;
359: if (ldep->de_StartCluster != MSDOSFSROOT) {
360: error = pcbmap(ldep, CLUST_END, 0, &size, 0);
361: if (error == E2BIG) {
362: ldep->de_FileSize = de_cn2off(pmp, size);
363: error = 0;
364: } else
365: printf("deget(): pcbmap returned %d\n", error);
366: }
367: } else
368: nvp->v_type = VREG;
369: VREF(ldep->de_devvp);
370: *depp = ldep;
1.8.2.4 yamt 371: uvm_vnp_setsize(nvp, ldep->de_FileSize);
1.1 jdolecek 372: return (0);
373: }
374:
375: int
376: deupdat(dep, waitfor)
377: struct denode *dep;
378: int waitfor;
379: {
380:
1.8.2.1 yamt 381: return (msdosfs_update(DETOV(dep), NULL, NULL,
382: waitfor ? UPDATE_WAIT : 0));
1.1 jdolecek 383: }
384:
385: /*
386: * Truncate the file described by dep to the length specified by length.
387: */
388: int
1.8.2.2 yamt 389: detrunc(struct denode *dep, u_long length, int flags, kauth_cred_t cred,
390: struct lwp *l)
1.1 jdolecek 391: {
392: int error;
393: int allerror;
394: u_long eofentry;
1.8.2.1 yamt 395: u_long chaintofree = 0;
1.1 jdolecek 396: daddr_t bn, lastblock;
397: int boff;
398: int isadir = dep->de_Attributes & ATTR_DIRECTORY;
399: struct buf *bp;
400: struct msdosfsmount *pmp = dep->de_pmp;
401:
402: #ifdef MSDOSFS_DEBUG
403: printf("detrunc(): file %s, length %lu, flags %x\n", dep->de_Name, length, flags);
404: #endif
405:
406: /*
407: * Disallow attempts to truncate the root directory since it is of
408: * fixed size. That's just the way dos filesystems are. We use
409: * the VROOT bit in the vnode because checking for the directory
410: * bit and a startcluster of 0 in the denode is not adequate to
411: * recognize the root directory at this point in a file or
412: * directory's life.
413: */
1.8.2.5 ! yamt 414: if ((DETOV(dep)->v_vflag & VV_ROOT) && !FAT32(pmp)) {
1.1 jdolecek 415: printf("detrunc(): can't truncate root directory, clust %ld, offset %ld\n",
416: dep->de_dirclust, dep->de_diroffset);
417: return (EINVAL);
418: }
419:
420: uvm_vnp_setsize(DETOV(dep), length);
421:
422: if (dep->de_FileSize < length)
423: return (deextend(dep, length, cred));
424: lastblock = de_clcount(pmp, length) - 1;
425:
426: /*
427: * If the desired length is 0 then remember the starting cluster of
428: * the file and set the StartCluster field in the directory entry
429: * to 0. If the desired length is not zero, then get the number of
430: * the last cluster in the shortened file. Then get the number of
431: * the first cluster in the part of the file that is to be freed.
432: * Then set the next cluster pointer in the last cluster of the
433: * file to CLUST_EOFE.
434: */
435: if (length == 0) {
436: chaintofree = dep->de_StartCluster;
437: dep->de_StartCluster = 0;
438: eofentry = ~0;
439: } else {
440: error = pcbmap(dep, lastblock, 0, &eofentry, 0);
441: if (error) {
442: #ifdef MSDOSFS_DEBUG
443: printf("detrunc(): pcbmap fails %d\n", error);
444: #endif
445: return (error);
446: }
447: }
448:
449: fc_purge(dep, lastblock + 1);
450:
451: /*
452: * If the new length is not a multiple of the cluster size then we
453: * must zero the tail end of the new last cluster in case it
454: * becomes part of the file again because of a seek.
455: */
456: if ((boff = length & pmp->pm_crbomask) != 0) {
457: if (isadir) {
458: bn = cntobn(pmp, eofentry);
1.8.2.2 yamt 459: error = bread(pmp->pm_devvp, de_bn2kb(pmp, bn),
460: pmp->pm_bpcluster, NOCRED, &bp);
1.1 jdolecek 461: if (error) {
1.8.2.5 ! yamt 462: brelse(bp, 0);
1.1 jdolecek 463: #ifdef MSDOSFS_DEBUG
464: printf("detrunc(): bread fails %d\n", error);
465: #endif
466: return (error);
467: }
1.8.2.4 yamt 468: memset((char *)bp->b_data + boff, 0,
469: pmp->pm_bpcluster - boff);
1.1 jdolecek 470: if (flags & IO_SYNC)
471: bwrite(bp);
472: else
473: bdwrite(bp);
474: } else {
475: uvm_vnp_zerorange(DETOV(dep), length,
476: pmp->pm_bpcluster - boff);
477: }
478: }
479:
480: /*
481: * Write out the updated directory entry. Even if the update fails
482: * we free the trailing clusters.
483: */
484: dep->de_FileSize = length;
485: if (!isadir)
486: dep->de_flag |= DE_UPDATE|DE_MODIFIED;
487: vtruncbuf(DETOV(dep), lastblock + 1, 0, 0);
488: allerror = deupdat(dep, 1);
489: #ifdef MSDOSFS_DEBUG
490: printf("detrunc(): allerror %d, eofentry %lu\n",
491: allerror, eofentry);
492: #endif
493:
494: /*
495: * If we need to break the cluster chain for the file then do it
496: * now.
497: */
498: if (eofentry != ~0) {
499: error = fatentry(FAT_GET_AND_SET, pmp, eofentry,
500: &chaintofree, CLUST_EOFE);
501: if (error) {
502: #ifdef MSDOSFS_DEBUG
503: printf("detrunc(): fatentry errors %d\n", error);
504: #endif
505: return (error);
506: }
507: fc_setcache(dep, FC_LASTFC, de_cluster(pmp, length - 1),
508: eofentry);
509: }
510:
511: /*
512: * Now free the clusters removed from the file because of the
513: * truncation.
514: */
515: if (chaintofree != 0 && !MSDOSFSEOF(chaintofree, pmp->pm_fatmask))
516: freeclusterchain(pmp, chaintofree);
517:
518: return (allerror);
519: }
520:
521: /*
522: * Extend the file described by dep to length specified by length.
523: */
524: int
525: deextend(dep, length, cred)
526: struct denode *dep;
527: u_long length;
1.8.2.1 yamt 528: kauth_cred_t cred;
1.1 jdolecek 529: {
530: struct msdosfsmount *pmp = dep->de_pmp;
531: u_long count, osize;
532: int error;
533:
534: /*
535: * The root of a DOS filesystem cannot be extended.
536: */
1.8.2.5 ! yamt 537: if ((DETOV(dep)->v_vflag & VV_ROOT) && !FAT32(pmp))
1.1 jdolecek 538: return (EINVAL);
539:
540: /*
541: * Directories cannot be extended.
542: */
543: if (dep->de_Attributes & ATTR_DIRECTORY)
544: return (EISDIR);
545:
546: if (length <= dep->de_FileSize)
547: panic("deextend: file too large");
548:
549: /*
550: * Compute the number of clusters to allocate.
551: */
552: count = de_clcount(pmp, length) - de_clcount(pmp, dep->de_FileSize);
553: if (count > 0) {
554: if (count > pmp->pm_freeclustercount)
555: return (ENOSPC);
556: error = extendfile(dep, count, NULL, NULL, DE_CLEAR);
557: if (error) {
558: /* truncate the added clusters away again */
559: (void) detrunc(dep, dep->de_FileSize, 0, cred, NULL);
560: return (error);
561: }
562: }
563:
564: osize = dep->de_FileSize;
565: dep->de_FileSize = length;
566: uvm_vnp_setsize(DETOV(dep), (voff_t)dep->de_FileSize);
567: dep->de_flag |= DE_UPDATE|DE_MODIFIED;
568: uvm_vnp_zerorange(DETOV(dep), (off_t)osize,
569: (size_t)(dep->de_FileSize - osize));
570: return (deupdat(dep, 1));
571: }
572:
573: /*
574: * Move a denode to its correct hash queue after the file it represents has
575: * been moved to a new directory.
576: */
577: void
578: reinsert(dep)
579: struct denode *dep;
580: {
581: /*
582: * Fix up the denode cache. If the denode is for a directory,
583: * there is nothing to do since the hash is based on the starting
584: * cluster of the directory file and that hasn't changed. If for a
585: * file the hash is based on the location of the directory entry,
586: * so we must remove it from the cache and re-enter it with the
587: * hash based on the new location of the directory entry.
588: */
589: if (dep->de_Attributes & ATTR_DIRECTORY)
590: return;
591: msdosfs_hashrem(dep);
592: msdosfs_hashins(dep);
593: }
594:
595: int
596: msdosfs_reclaim(v)
597: void *v;
598: {
599: struct vop_reclaim_args /* {
600: struct vnode *a_vp;
601: } */ *ap = v;
602: struct vnode *vp = ap->a_vp;
603: struct denode *dep = VTODE(vp);
604:
605: #ifdef MSDOSFS_DEBUG
606: printf("msdosfs_reclaim(): dep %p, file %s, refcnt %ld\n",
607: dep, dep->de_Name, dep->de_refcnt);
608: #endif
609:
610: if (prtactive && vp->v_usecount != 0)
611: vprint("msdosfs_reclaim(): pushing active", vp);
612: /*
613: * Remove the denode from its hash chain.
614: */
615: msdosfs_hashrem(dep);
616: /*
617: * Purge old data structures associated with the denode.
618: */
619: cache_purge(vp);
620: if (dep->de_devvp) {
621: vrele(dep->de_devvp);
622: dep->de_devvp = 0;
623: }
624: #if 0 /* XXX */
625: dep->de_flag = 0;
626: #endif
1.8.2.3 yamt 627: genfs_node_destroy(vp);
1.1 jdolecek 628: pool_put(&msdosfs_denode_pool, dep);
629: vp->v_data = NULL;
630: return (0);
631: }
632:
633: int
634: msdosfs_inactive(v)
635: void *v;
636: {
637: struct vop_inactive_args /* {
638: struct vnode *a_vp;
1.8.2.1 yamt 639: struct lwp *a_l;
1.1 jdolecek 640: } */ *ap = v;
1.8.2.1 yamt 641: struct lwp *l = ap->a_l;
1.1 jdolecek 642: struct vnode *vp = ap->a_vp;
643: struct denode *dep = VTODE(vp);
644: int error = 0;
645:
646: #ifdef MSDOSFS_DEBUG
647: printf("msdosfs_inactive(): dep %p, de_Name[0] %x\n", dep, dep->de_Name[0]);
648: #endif
649:
650: if (prtactive && vp->v_usecount != 0)
651: vprint("msdosfs_inactive(): pushing active", vp);
652:
653: /*
654: * Get rid of denodes related to stale file handles.
655: */
656: if (dep->de_Name[0] == SLOT_DELETED)
657: goto out;
658:
659: /*
660: * If the file has been deleted and it is on a read/write
661: * filesystem, then truncate the file, and mark the directory slot
662: * as empty. (This may not be necessary for the dos filesystem.)
663: */
664: #ifdef MSDOSFS_DEBUG
665: printf("msdosfs_inactive(): dep %p, refcnt %ld, mntflag %x %s\n",
666: dep, dep->de_refcnt, vp->v_mount->mnt_flag,
667: (vp->v_mount->mnt_flag & MNT_RDONLY) ? "MNT_RDONLY" : "");
668: #endif
669: if (dep->de_refcnt <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
670: if (dep->de_FileSize != 0) {
671: error = detrunc(dep, (u_long)0, 0, NOCRED, NULL);
672: }
673: dep->de_Name[0] = SLOT_DELETED;
674: }
675: deupdat(dep, 0);
676: out:
677: VOP_UNLOCK(vp, 0);
678: /*
679: * If we are done with the denode, reclaim it
680: * so that it can be reused immediately.
681: */
682: #ifdef MSDOSFS_DEBUG
683: printf("msdosfs_inactive(): v_usecount %d, de_Name[0] %x\n",
684: vp->v_usecount, dep->de_Name[0]);
685: #endif
686: if (dep->de_Name[0] == SLOT_DELETED)
1.8.2.1 yamt 687: vrecycle(vp, (struct simplelock *)0, l);
1.1 jdolecek 688: return (error);
689: }
690:
691: int
1.8.2.2 yamt 692: msdosfs_gop_alloc(struct vnode *vp, off_t off,
693: off_t len, int flags, kauth_cred_t cred)
1.1 jdolecek 694: {
695: return 0;
696: }
1.8.2.1 yamt 697:
698: void
699: msdosfs_gop_markupdate(struct vnode *vp, int flags)
700: {
701: u_long mask = 0;
702:
703: if ((flags & GOP_UPDATE_ACCESSED) != 0) {
704: mask = DE_ACCESS;
705: }
706: if ((flags & GOP_UPDATE_MODIFIED) != 0) {
707: mask |= DE_UPDATE;
708: }
709: if (mask) {
710: struct denode *dep = VTODE(vp);
711:
712: dep->de_flag |= mask;
713: }
714: }
CVSweb <webmaster@jp.NetBSD.org>