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