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