1 /* $FreeBSD$ */ 2 /* $NetBSD: msdosfs_denode.c,v 1.28 1998/02/10 14:10:00 mrg Exp $ */ 3 4 /*- 5 * SPDX-License-Identifier: BSD-4-Clause 6 * 7 * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. 8 * Copyright (C) 1994, 1995, 1997 TooLs GmbH. 9 * All rights reserved. 10 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). 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 TooLs GmbH. 23 * 4. The name of TooLs GmbH may not be used to endorse or promote products 24 * derived from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 31 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 32 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 33 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 34 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 */ 37 /*- 38 * Written by Paul Popelka (paulp@uts.amdahl.com) 39 * 40 * You can do anything you want with this software, just don't say you wrote 41 * it, and don't remove this notice. 42 * 43 * This software is provided "as is". 44 * 45 * The author supplies this software to be publicly redistributed on the 46 * understanding that the author is not responsible for the correct 47 * functioning of this software in any circumstances and is not liable for 48 * any damages caused by this software. 49 * 50 * October 1992 51 */ 52 53 #include <sys/param.h> 54 #include <sys/systm.h> 55 #include <sys/buf.h> 56 #include <sys/kernel.h> 57 #include <sys/malloc.h> 58 #include <sys/proc.h> 59 #include <sys/mount.h> 60 #include <sys/vnode.h> 61 62 #include <vm/vm.h> 63 #include <vm/vm_extern.h> 64 65 #include <sys/buf2.h> 66 67 #include "bpb.h" 68 #include "msdosfsmount.h" 69 #include "direntry.h" 70 #include "denode.h" 71 #include "fat.h" 72 73 static MALLOC_DEFINE(M_MSDOSFSNODE, "MSDOSFS node", "MSDOSFS vnode private part"); 74 75 /* 76 * Hash table caching denode instances. 77 * 78 * denodes are keyed by the disk location (cluster num, entry offset) of the 79 * directory entry of the file they represent. 80 * 81 * denodes representing deleted but still opened files are left in this cache 82 * until reclaimed. Deleted directory entries can be reused when files are 83 * renamed or new files created. As a consequence, several denodes associated 84 * with the same entry may coexist in this cache as long as a single one of 85 * them map to an existing file (de_refcnt > 0). 86 * 87 * R/w access to this cache is protected by dehash_token. 88 */ 89 static struct denode **dehashtbl; 90 static u_long dehash; /* size of hash table - 1 */ 91 static struct lwkt_token dehash_token; 92 93 #define DEHASH(dev, dcl, doff) (dehashtbl[(minor(dev) + (dcl) + (doff) / \ 94 sizeof(struct direntry)) & dehash]) 95 96 union _qcvt { 97 quad_t qcvt; 98 long val[2]; 99 }; 100 #define SETHIGH(q, h) { \ 101 union _qcvt tmp; \ 102 tmp.qcvt = (q); \ 103 tmp.val[_QUAD_HIGHWORD] = (h); \ 104 (q) = tmp.qcvt; \ 105 } 106 #define SETLOW(q, l) { \ 107 union _qcvt tmp; \ 108 tmp.qcvt = (q); \ 109 tmp.val[_QUAD_LOWWORD] = (l); \ 110 (q) = tmp.qcvt; \ 111 } 112 113 /*ARGSUSED*/ 114 int 115 msdosfs_init(struct vfsconf *vfsp) 116 { 117 dehash = vfs_inodehashsize(); 118 dehashtbl = kmalloc(sizeof(void *) * dehash, 119 M_MSDOSFSMNT, M_WAITOK|M_ZERO); 120 --dehash; 121 lwkt_token_init(&dehash_token, "msdosihash"); 122 123 return (0); 124 } 125 126 int 127 msdosfs_uninit(struct vfsconf *vfsp) 128 { 129 if (dehashtbl) 130 kfree(dehashtbl, M_MSDOSFSMNT); 131 return (0); 132 } 133 134 static struct denode * 135 msdosfs_hashget(cdev_t dev, u_long dirclust, u_long diroff) 136 { 137 struct denode *dep; 138 struct vnode *vp; 139 140 lwkt_gettoken(&dehash_token); 141 loop: 142 for (dep = DEHASH(dev, dirclust, diroff); dep; dep = dep->de_next) { 143 if (dirclust != dep->de_dirclust 144 || diroff != dep->de_diroffset 145 || dev != dep->de_dev 146 || dep->de_refcnt <= 0) { 147 continue; 148 } 149 vp = DETOV(dep); 150 if (vget(vp, LK_EXCLUSIVE)) 151 goto loop; 152 153 /* 154 * We must check to see if the inode has been ripped 155 * out from under us after blocking. 156 */ 157 for (dep = DEHASH(dev, dirclust, diroff); dep; 158 dep = dep->de_next) { 159 if (dirclust == dep->de_dirclust 160 && diroff == dep->de_diroffset 161 && dev == dep->de_dev 162 && dep->de_refcnt > 0) { 163 break; 164 } 165 } 166 if (dep == NULL || DETOV(dep) != vp) { 167 vput(vp); 168 goto loop; 169 } 170 lwkt_reltoken(&dehash_token); 171 return (dep); 172 } 173 lwkt_reltoken(&dehash_token); 174 return (NULL); 175 } 176 177 /* 178 * Try to insert specified denode into the hash table. Return 0 on success 179 * and EBUSY if there is already a denode with the same key. 180 */ 181 static 182 int 183 msdosfs_hashins(struct denode *dep) 184 { 185 struct denode **depp, *deq; 186 187 lwkt_gettoken(&dehash_token); 188 depp = &DEHASH(dep->de_dev, dep->de_dirclust, dep->de_diroffset); 189 while ((deq = *depp) != NULL) { 190 if (deq->de_dev == dep->de_dev && 191 deq->de_dirclust == dep->de_dirclust && 192 deq->de_diroffset == dep->de_diroffset && 193 deq->de_refcnt > 0) { 194 lwkt_reltoken(&dehash_token); 195 return(EBUSY); 196 } 197 depp = &deq->de_next; 198 } 199 dep->de_next = NULL; 200 *depp = dep; 201 lwkt_reltoken(&dehash_token); 202 return(0); 203 } 204 205 static 206 void 207 msdosfs_hashrem(struct denode *dep) 208 { 209 struct denode **depp, *deq; 210 211 lwkt_gettoken(&dehash_token); 212 depp = &DEHASH(dep->de_dev, dep->de_dirclust, dep->de_diroffset); 213 while ((deq = *depp) != NULL) { 214 if (dep == deq) 215 break; 216 depp = &deq->de_next; 217 } 218 KKASSERT(dep == deq); 219 *depp = dep->de_next; 220 dep->de_next = NULL; 221 lwkt_reltoken(&dehash_token); 222 } 223 224 void 225 msdosfs_reinsert(struct denode *ip, u_long new_dirclust, u_long new_diroffset) 226 { 227 int error; 228 229 lwkt_gettoken(&dehash_token); 230 msdosfs_hashrem(ip); 231 ip->de_dirclust = new_dirclust; 232 ip->de_diroffset = new_diroffset; 233 error = msdosfs_hashins(ip); 234 KASSERT(!error, ("msdosfs_reinsert: insertion failed %d", error)); 235 lwkt_reltoken(&dehash_token); 236 } 237 238 /* 239 * If deget() succeeds it returns with the gotten denode locked(). 240 * 241 * pmp - address of msdosfsmount structure of the filesystem containing 242 * the denode of interest. The pm_dev field and the address of 243 * the msdosfsmount structure are used. 244 * dirclust - which cluster bp contains, if dirclust is 0 (root directory) 245 * diroffset is relative to the beginning of the root directory, 246 * otherwise it is cluster relative. 247 * diroffset - offset past begin of cluster of denode we want 248 * depp - returns the address of the gotten denode. 249 */ 250 int 251 deget(struct msdosfsmount *pmp, /* so we know the maj/min number */ 252 u_long dirclust, /* cluster this dir entry came from */ 253 u_long diroffset, /* index of entry within the cluster */ 254 struct denode **depp) /* returns the addr of the gotten denode */ 255 { 256 int error; 257 cdev_t dev = pmp->pm_dev; 258 struct mount *mntp = pmp->pm_mountp; 259 struct direntry *direntptr; 260 struct denode *ldep; 261 struct vnode *nvp; 262 struct buf *bp; 263 struct timeval tv; 264 265 mprintf("deget(pmp %p, dirclust %lu, diroffset %lx, depp %p)\n", 266 pmp, dirclust, diroffset, depp); 267 268 /* 269 * On FAT32 filesystems, root is a (more or less) normal 270 * directory 271 */ 272 if (FAT32(pmp) && dirclust == MSDOSFSROOT) 273 dirclust = pmp->pm_rootdirblk; 274 275 again: 276 /* 277 * See if the denode is in the denode cache. Use the location of 278 * the directory entry to compute the hash value. For subdir use 279 * address of "." entry. For root dir (if not FAT32) use cluster 280 * MSDOSFSROOT, offset MSDOSFSROOT_OFS 281 * 282 * NOTE: The check for de_refcnt > 0 below insures the denode being 283 * examined does not represent an unlinked but still open file. 284 * These files are not to be accessible even when the directory 285 * entry that represented the file happens to be reused while the 286 * deleted file is still open. 287 */ 288 ldep = msdosfs_hashget(dev, dirclust, diroffset); 289 if (ldep) { 290 *depp = ldep; 291 return (0); 292 } 293 294 /* 295 * Do the MALLOC before the getnewvnode since doing so afterward 296 * might cause a bogus v_data pointer to get dereferenced 297 * elsewhere if MALLOC should block. 298 */ 299 ldep = kmalloc(sizeof(struct denode), M_MSDOSFSNODE, M_WAITOK | M_ZERO); 300 301 /* 302 * Directory entry was not in cache, have to create a vnode and 303 * copy it from the passed disk buffer. 304 */ 305 306 /* getnewvnode() does a vref() on the vnode */ 307 error = getnewvnode(VT_MSDOSFS, mntp, &nvp, VLKTIMEOUT, 0); 308 if (error) { 309 *depp = NULL; 310 kfree(ldep, M_MSDOSFSNODE); 311 return error; 312 } 313 314 ldep->de_vnode = nvp; 315 ldep->de_flag = 0; 316 ldep->de_devvp = 0; 317 ldep->de_dev = dev; 318 ldep->de_dirclust = dirclust; 319 ldep->de_diroffset = diroffset; 320 fc_purge(ldep, 0); /* init the fat cache for this denode */ 321 322 /* 323 * Insert the denode into the hash queue. If a collision occurs 324 * throw away the vnode and try again. 325 */ 326 error = msdosfs_hashins(ldep); 327 if (error == EBUSY) { 328 nvp->v_type = VBAD; 329 vx_put(nvp); 330 kfree(ldep, M_MSDOSFSNODE); 331 goto again; 332 } else if (error) { 333 nvp->v_type = VBAD; 334 vx_put(nvp); 335 kfree(ldep, M_MSDOSFSNODE); 336 *depp = NULL; 337 return (EINVAL); 338 } 339 nvp->v_data = ldep; 340 ldep->de_pmp = pmp; 341 ldep->de_refcnt = 1; 342 /* 343 * Copy the directory entry into the denode area of the vnode. 344 */ 345 if ((dirclust == MSDOSFSROOT 346 || (FAT32(pmp) && dirclust == pmp->pm_rootdirblk)) 347 && diroffset == MSDOSFSROOT_OFS) { 348 /* 349 * Directory entry for the root directory. There isn't one, 350 * so we manufacture one. We should probably rummage 351 * through the root directory and find a label entry (if it 352 * exists), and then use the time and date from that entry 353 * as the time and date for the root denode. 354 */ 355 vsetflags(nvp, VROOT); /* should be further down XXX */ 356 357 ldep->de_Attributes = ATTR_DIRECTORY; 358 ldep->de_LowerCase = 0; 359 if (FAT32(pmp)) { 360 ldep->de_StartCluster = pmp->pm_rootdirblk; 361 /* de_FileSize will be filled in further down */ 362 } else { 363 ldep->de_StartCluster = MSDOSFSROOT; 364 ldep->de_FileSize = pmp->pm_rootdirsize * DEV_BSIZE; 365 } 366 /* 367 * fill in time and date so that dos2unixtime() doesn't 368 * spit up when called from msdosfs_getattr() with root 369 * denode 370 */ 371 ldep->de_CHun = 0; 372 ldep->de_CTime = 0x0000; /* 00:00:00 */ 373 ldep->de_CDate = (0 << DD_YEAR_SHIFT) | (1 << DD_MONTH_SHIFT) 374 | (1 << DD_DAY_SHIFT); 375 /* Jan 1, 1980 */ 376 ldep->de_ADate = ldep->de_CDate; 377 ldep->de_MTime = ldep->de_CTime; 378 ldep->de_MDate = ldep->de_CDate; 379 /* leave the other fields as garbage */ 380 } else { 381 error = readep(pmp, dirclust, diroffset, &bp, &direntptr); 382 if (error) { 383 /* 384 * The denode does not contain anything useful, so 385 * it would be wrong to leave it on its hash chain. 386 * Arrange for vput() to just forget about it. 387 */ 388 ldep->de_Name[0] = SLOT_DELETED; 389 nvp->v_type = VBAD; 390 391 vx_put(nvp); 392 *depp = NULL; 393 return (error); 394 } 395 DE_INTERNALIZE(ldep, direntptr); 396 brelse(bp); 397 } 398 399 /* 400 * Fill in a few fields of the vnode and finish filling in the 401 * denode. Then return the address of the found denode. 402 */ 403 if (ldep->de_Attributes & ATTR_DIRECTORY) { 404 /* 405 * Since DOS directory entries that describe directories 406 * have 0 in the filesize field, we take this opportunity 407 * to find out the length of the directory and plug it into 408 * the denode structure. 409 */ 410 u_long size; 411 412 /* 413 * XXX Sometimes, these arrives that . entry have cluster 414 * number 0, when it shouldn't. Use real cluster number 415 * instead of what is written in directory entry. 416 */ 417 if ((diroffset == 0) && (ldep->de_StartCluster != dirclust)) { 418 kprintf("deget(): . entry at clust %ld != %ld\n", 419 dirclust, ldep->de_StartCluster); 420 ldep->de_StartCluster = dirclust; 421 } 422 423 nvp->v_type = VDIR; 424 if (ldep->de_StartCluster != MSDOSFSROOT) { 425 error = pcbmap(ldep, 0xffff, NULL, &size, NULL); 426 if (error == E2BIG) { 427 ldep->de_FileSize = de_cn2off(pmp, size); 428 error = 0; 429 } else 430 kprintf("deget(): pcbmap returned %d\n", error); 431 } 432 } else { 433 nvp->v_type = VREG; 434 } 435 getmicrouptime(&tv); 436 SETHIGH(ldep->de_modrev, tv.tv_sec); 437 SETLOW(ldep->de_modrev, tv.tv_usec * 4294); 438 ldep->de_devvp = pmp->pm_devvp; 439 vref(ldep->de_devvp); 440 vinitvmio(nvp, ldep->de_FileSize, PAGE_SIZE, -1); 441 /* 442 * Leave nvp locked and refd so the returned inode is effectively 443 * locked and refd. 444 */ 445 *depp = ldep; 446 return (0); 447 } 448 449 int 450 deupdat(struct denode *dep, int waitfor) 451 { 452 int error; 453 struct buf *bp; 454 struct direntry *dirp; 455 struct timespec ts; 456 457 if (DETOV(dep)->v_mount->mnt_flag & MNT_RDONLY) 458 return (0); 459 getnanotime(&ts); 460 DETIMES(dep, &ts, &ts, &ts); 461 if ((dep->de_flag & DE_MODIFIED) == 0) 462 return (0); 463 dep->de_flag &= ~DE_MODIFIED; 464 if (dep->de_Attributes & ATTR_DIRECTORY) 465 return (0); 466 if (dep->de_refcnt <= 0) 467 return (0); 468 error = readde(dep, &bp, &dirp); 469 if (error) 470 return (error); 471 DE_EXTERNALIZE(dirp, dep); 472 if (waitfor) { 473 return (bwrite(bp)); 474 } else { 475 bdwrite(bp); 476 return (0); 477 } 478 } 479 480 /* 481 * Truncate the file described by dep to the length specified by length. 482 */ 483 int 484 detrunc(struct denode *dep, u_long length, int flags) 485 { 486 int error; 487 int allerror; 488 u_long eofentry; 489 u_long chaintofree; 490 daddr_t bn, cn; 491 int boff; 492 int isadir = dep->de_Attributes & ATTR_DIRECTORY; 493 struct buf *bp; 494 struct msdosfsmount *pmp = dep->de_pmp; 495 496 mprintf("detrunc(): file %s, length %lu, flags %x\n", dep->de_Name, 497 length, flags); 498 499 /* 500 * Disallow attempts to truncate the root directory since it is of 501 * fixed size. That's just the way dos filesystems are. We use 502 * the VROOT bit in the vnode because checking for the directory 503 * bit and a startcluster of 0 in the denode is not adequate to 504 * recognize the root directory at this point in a file or 505 * directory's life. 506 */ 507 if ((DETOV(dep)->v_flag & VROOT) && !FAT32(pmp)) { 508 kprintf("detrunc(): can't truncate root directory, clust %ld, " 509 "offset %ld\n", 510 dep->de_dirclust, dep->de_diroffset); 511 return (EINVAL); 512 } 513 514 if (dep->de_FileSize < length) { 515 vnode_pager_setsize(DETOV(dep), length); 516 return deextend(dep, length); 517 } 518 519 /* 520 * If the desired length is 0 then remember the starting cluster of 521 * the file and set the StartCluster field in the directory entry 522 * to 0. If the desired length is not zero, then get the number of 523 * the last cluster in the shortened file. Then get the number of 524 * the first cluster in the part of the file that is to be freed. 525 * Then set the next cluster pointer in the last cluster of the 526 * file to CLUST_EOFE. 527 */ 528 if (length == 0) { 529 chaintofree = dep->de_StartCluster; 530 dep->de_StartCluster = 0; 531 eofentry = ~0; 532 } else { 533 error = pcbmap(dep, de_clcount(pmp, length) - 1, 534 NULL, &eofentry, NULL); 535 if (error) { 536 mprintf("detrunc(): pcbmap fails %d\n", error); 537 return (error); 538 } 539 } 540 541 fc_purge(dep, de_clcount(pmp, length)); 542 543 /* 544 * If the new length is not a multiple of the cluster size then we 545 * must zero the tail end of the new last cluster in case it 546 * becomes part of the file again because of a seek. 547 */ 548 if ((boff = length & pmp->pm_crbomask) != 0) { 549 if (isadir) { 550 bn = xcntobn(pmp, eofentry); 551 error = bread(pmp->pm_devvp, de_bntodoff(pmp, bn), 552 pmp->pm_bpcluster, &bp); 553 } else { 554 cn = de_cluster(pmp, length); 555 error = bread(DETOV(dep), de_cn2doff(pmp, cn), 556 pmp->pm_bpcluster, &bp); 557 } 558 if (error) { 559 brelse(bp); 560 mprintf("detrunc(): bread fails %d\n", error); 561 return (error); 562 } 563 /* 564 * is this the right place for it? 565 */ 566 bzero(bp->b_data + boff, pmp->pm_bpcluster - boff); 567 if (flags & IO_SYNC) 568 bwrite(bp); 569 else 570 bdwrite(bp); 571 } 572 573 /* 574 * Write out the updated directory entry. Even if the update fails 575 * we free the trailing clusters. 576 */ 577 dep->de_FileSize = length; 578 if (!isadir) 579 dep->de_flag |= DE_UPDATE|DE_MODIFIED; 580 allerror = vtruncbuf(DETOV(dep), length, pmp->pm_bpcluster); 581 #ifdef MSDOSFS_DEBUG 582 if (allerror) 583 kprintf("detrunc(): vtruncbuf error %d\n", allerror); 584 #endif 585 error = deupdat(dep, 1); 586 if (error && (allerror == 0)) 587 allerror = error; 588 mprintf("detrunc(): allerror %d, eofentry %lu\n", 589 allerror, eofentry); 590 591 /* 592 * If we need to break the cluster chain for the file then do it 593 * now. 594 */ 595 if (eofentry != ~0) { 596 error = fatentry(FAT_GET_AND_SET, pmp, eofentry, 597 &chaintofree, CLUST_EOFE); 598 if (error) { 599 mprintf("detrunc(): fatentry errors %d\n", error); 600 return (error); 601 } 602 fc_setcache(dep, FC_LASTFC, de_cluster(pmp, length - 1), 603 eofentry); 604 } 605 606 /* 607 * Now free the clusters removed from the file because of the 608 * truncation. 609 */ 610 if (chaintofree != 0 && !MSDOSFSEOF(pmp, chaintofree)) 611 freeclusterchain(pmp, chaintofree); 612 613 return (allerror); 614 } 615 616 /* 617 * Extend the file described by dep to length specified by length. 618 */ 619 int 620 deextend(struct denode *dep, u_long length) 621 { 622 struct msdosfsmount *pmp = dep->de_pmp; 623 u_long count; 624 int error; 625 626 /* 627 * The root of a DOS filesystem cannot be extended. 628 */ 629 if ((DETOV(dep)->v_flag & VROOT) && !FAT32(pmp)) 630 return (EINVAL); 631 632 /* 633 * Directories cannot be extended. 634 */ 635 if (dep->de_Attributes & ATTR_DIRECTORY) 636 return (EISDIR); 637 638 if (length <= dep->de_FileSize) 639 panic("deextend: file too large"); 640 641 /* 642 * Compute the number of clusters to allocate. 643 */ 644 count = de_clcount(pmp, length) - de_clcount(pmp, dep->de_FileSize); 645 if (count > 0) { 646 if (count > pmp->pm_freeclustercount) 647 return (ENOSPC); 648 error = extendfile(dep, count, NULL, NULL, DE_CLEAR); 649 if (error) { 650 /* truncate the added clusters away again */ 651 detrunc(dep, dep->de_FileSize, 0); 652 return (error); 653 } 654 } 655 dep->de_FileSize = length; 656 dep->de_flag |= DE_UPDATE|DE_MODIFIED; 657 return (deupdat(dep, 1)); 658 } 659 660 /* 661 * msdosfs_reclaim(struct vnode *a_vp) 662 */ 663 int 664 msdosfs_reclaim(struct vop_reclaim_args *ap) 665 { 666 struct vnode *vp = ap->a_vp; 667 struct denode *dep = VTODE(vp); 668 669 mprintf("msdosfs_reclaim(): dep %p, file %s, refcnt %ld\n", 670 dep, dep ? (char *)dep->de_Name : "?", dep ? dep->de_refcnt : -1); 671 672 if (prtactive && VREFCNT(vp) > 1) 673 vprint("msdosfs_reclaim(): pushing active", vp); 674 /* 675 * Remove the denode from its hash chain. 676 */ 677 vp->v_data = NULL; 678 if (dep) { 679 msdosfs_hashrem(dep); 680 if (dep->de_devvp) { 681 vrele(dep->de_devvp); 682 dep->de_devvp = 0; 683 } 684 kfree(dep, M_MSDOSFSNODE); 685 } 686 return (0); 687 } 688 689 /* 690 * msdosfs_inactive(struct vnode *a_vp) 691 */ 692 int 693 msdosfs_inactive(struct vop_inactive_args *ap) 694 { 695 struct vnode *vp = ap->a_vp; 696 struct denode *dep = VTODE(vp); 697 int error = 0; 698 699 mprintf("msdosfs_inactive(): dep %p, de_Name[0] %x\n", 700 dep, (dep ? dep->de_Name[0] : 0)); 701 702 if (prtactive && VREFCNT(vp) > 1) 703 vprint("msdosfs_inactive(): pushing active", vp); 704 705 /* 706 * Ignore denodes related to stale file handles. 707 */ 708 if (dep == NULL || dep->de_Name[0] == SLOT_DELETED) 709 goto out; 710 711 /* 712 * If the file has been deleted and it is on a read/write 713 * filesystem, then truncate the file, and mark the directory slot 714 * as empty. (This may not be necessary for the dos filesystem.) 715 */ 716 mprintf("msdosfs_inactive(): dep %p, refcnt %ld, mntflag %x, MNT_RDONLY %x\n", 717 dep, dep->de_refcnt, vp->v_mount->mnt_flag, MNT_RDONLY); 718 if (dep->de_refcnt <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 719 error = detrunc(dep, (u_long) 0, 0); 720 dep->de_flag |= DE_UPDATE; 721 dep->de_Name[0] = SLOT_DELETED; 722 } 723 deupdat(dep, 0); 724 725 out: 726 /* 727 * If we are done with the denode, reclaim it 728 * so that it can be reused immediately. 729 */ 730 mprintf("msdosfs_inactive(): v_refcnt 0x%08x, de_Name[0] %x\n", 731 vp->v_refcnt, (dep ? dep->de_Name[0] : 0)); 732 if (dep == NULL || dep->de_Name[0] == SLOT_DELETED) 733 vrecycle(vp); 734 return (error); 735 } 736