msdosfs_denode.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. /* $OpenBSD: msdosfs_denode.c,v 1.53 2015/01/09 05:01:57 tedu Exp $ */
  2. /* $NetBSD: msdosfs_denode.c,v 1.23 1997/10/17 11:23:58 ws Exp $ */
  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. #include <sys/param.h>
  50. #include <sys/systm.h>
  51. #include <sys/mount.h>
  52. #include <sys/malloc.h>
  53. #include <sys/buf.h>
  54. #include <sys/vnode.h>
  55. #include <sys/lock.h>
  56. #include <sys/kernel.h> /* defines "time" */
  57. #include <sys/dirent.h>
  58. #include <sys/namei.h>
  59. #include <crypto/siphash.h>
  60. #include <msdosfs/bpb.h>
  61. #include <msdosfs/msdosfsmount.h>
  62. #include <msdosfs/direntry.h>
  63. #include <msdosfs/denode.h>
  64. #include <msdosfs/fat.h>
  65. u_int msdosfs_dehash(dev_t, uint32_t, uint32_t);
  66. struct denode **dehashtbl;
  67. SIPHASH_KEY dehashkey;
  68. u_long dehash; /* size of hash table - 1 */
  69. #define DEHASH(dev, dcl, doff) msdosfs_dehash((dev), (dcl), (doff))
  70. static struct denode *msdosfs_hashget(dev_t, uint32_t, uint32_t);
  71. static int msdosfs_hashins(struct denode *);
  72. static void msdosfs_hashrem(struct denode *);
  73. /*ARGSUSED*/
  74. int
  75. msdosfs_init(struct vfsconf *vfsp)
  76. {
  77. dehashtbl = hashinit(initialvnodes / 2, M_MSDOSFSMNT, M_WAITOK, &dehash);
  78. arc4random_buf(&dehashkey, sizeof(dehashkey));
  79. return (0);
  80. }
  81. u_int
  82. msdosfs_dehash(dev_t dev, uint32_t dirclust, uint32_t diroff)
  83. {
  84. SIPHASH_CTX ctx;
  85. SipHash24_Init(&ctx, &dehashkey);
  86. SipHash24_Update(&ctx, &dev, sizeof(dev));
  87. SipHash24_Update(&ctx, &dirclust, sizeof(dirclust));
  88. SipHash24_Update(&ctx, &diroff, sizeof(diroff));
  89. return (SipHash24_End(&ctx) & dehash);
  90. }
  91. static struct denode *
  92. msdosfs_hashget(dev_t dev, uint32_t dirclust, uint32_t diroff)
  93. {
  94. struct denode *dep;
  95. struct proc *p = curproc; /* XXX */
  96. for (;;)
  97. for (dep = dehashtbl[DEHASH(dev, dirclust, diroff)]; ;
  98. dep = dep->de_next) {
  99. if (dep == NULL)
  100. return (NULL);
  101. if (dirclust == dep->de_dirclust &&
  102. diroff == dep->de_diroffset &&
  103. dev == dep->de_dev &&
  104. dep->de_refcnt != 0) {
  105. struct vnode *vp = DETOV(dep);
  106. if (!vget(vp, LK_EXCLUSIVE, p))
  107. return (dep);
  108. break;
  109. }
  110. }
  111. /* NOTREACHED */
  112. }
  113. static int
  114. msdosfs_hashins(struct denode *dep)
  115. {
  116. struct denode **depp, *deq;
  117. depp = &dehashtbl[DEHASH(dep->de_dev, dep->de_dirclust,
  118. dep->de_diroffset)];
  119. for (deq = *depp; deq; deq = deq->de_next) {
  120. if (dep->de_dirclust == deq->de_dirclust &&
  121. dep->de_diroffset == deq->de_diroffset &&
  122. dep->de_dev == deq->de_dev &&
  123. deq->de_refcnt != 0) {
  124. return (EEXIST);
  125. }
  126. }
  127. if ((deq = *depp) != NULL)
  128. deq->de_prev = &dep->de_next;
  129. dep->de_next = deq;
  130. dep->de_prev = depp;
  131. *depp = dep;
  132. return (0);
  133. }
  134. static void
  135. msdosfs_hashrem(struct denode *dep)
  136. {
  137. struct denode *deq;
  138. if (dep->de_prev == NULL)
  139. return;
  140. if ((deq = dep->de_next) != NULL)
  141. deq->de_prev = dep->de_prev;
  142. *dep->de_prev = deq;
  143. #ifdef DIAGNOSTIC
  144. dep->de_next = NULL;
  145. dep->de_prev = NULL;
  146. #endif
  147. }
  148. /*
  149. * If deget() succeeds it returns with the gotten denode locked().
  150. *
  151. * pmp - address of msdosfsmount structure of the filesystem containing
  152. * the denode of interest. The pm_dev field and the address of
  153. * the msdosfsmount structure are used.
  154. * dirclust - which cluster bp contains, if dirclust is 0 (root directory)
  155. * diroffset is relative to the beginning of the root directory,
  156. * otherwise it is cluster relative.
  157. * diroffset - offset past begin of cluster of denode we want
  158. * depp - returns the address of the gotten denode.
  159. */
  160. int
  161. deget(struct msdosfsmount *pmp, uint32_t dirclust, uint32_t diroffset,
  162. struct denode **depp)
  163. {
  164. int error;
  165. extern struct vops msdosfs_vops;
  166. struct direntry *direntptr;
  167. struct denode *ldep;
  168. struct vnode *nvp;
  169. struct buf *bp;
  170. struct proc *p = curproc; /* XXX */
  171. #ifdef MSDOSFS_DEBUG
  172. printf("deget(pmp %08x, dirclust %d, diroffset %x, depp %08x)\n",
  173. pmp, dirclust, diroffset, depp);
  174. #endif
  175. /*
  176. * On FAT32 filesystems, root is a (more or less) normal
  177. * directory
  178. */
  179. if (FAT32(pmp) && dirclust == MSDOSFSROOT)
  180. dirclust = pmp->pm_rootdirblk;
  181. /*
  182. * See if the denode is in the denode cache. Use the location of
  183. * the directory entry to compute the hash value. For subdir use
  184. * address of "." entry. For root dir (if not FAT32) use cluster
  185. * MSDOSFSROOT, offset MSDOSFSROOT_OFS
  186. *
  187. * NOTE: The check for de_refcnt > 0 below insures the denode being
  188. * examined does not represent an unlinked but still open file.
  189. * These files are not to be accessible even when the directory
  190. * entry that represented the file happens to be reused while the
  191. * deleted file is still open.
  192. */
  193. retry:
  194. ldep = msdosfs_hashget(pmp->pm_dev, dirclust, diroffset);
  195. if (ldep) {
  196. *depp = ldep;
  197. return (0);
  198. }
  199. /*
  200. * Directory entry was not in cache, have to create a vnode and
  201. * copy it from the passed disk buffer.
  202. */
  203. /* getnewvnode() does a vref() on the vnode */
  204. error = getnewvnode(VT_MSDOSFS, pmp->pm_mountp, &msdosfs_vops, &nvp);
  205. if (error) {
  206. *depp = 0;
  207. return (error);
  208. }
  209. ldep = malloc(sizeof(*ldep), M_MSDOSFSNODE, M_WAITOK | M_ZERO);
  210. lockinit(&ldep->de_lock, PINOD, "denode", 0, 0);
  211. nvp->v_data = ldep;
  212. ldep->de_vnode = nvp;
  213. ldep->de_flag = 0;
  214. ldep->de_devvp = 0;
  215. ldep->de_lockf = 0;
  216. ldep->de_dev = pmp->pm_dev;
  217. ldep->de_dirclust = dirclust;
  218. ldep->de_diroffset = diroffset;
  219. fc_purge(ldep, 0); /* init the fat cache for this denode */
  220. /*
  221. * Insert the denode into the hash queue and lock the denode so it
  222. * can't be accessed until we've read it in and have done what we
  223. * need to it.
  224. */
  225. vn_lock(nvp, LK_EXCLUSIVE | LK_RETRY, p);
  226. error = msdosfs_hashins(ldep);
  227. if (error) {
  228. vput (nvp);
  229. if (error == EEXIST)
  230. goto retry;
  231. return (error);
  232. }
  233. ldep->de_pmp = pmp;
  234. ldep->de_devvp = pmp->pm_devvp;
  235. ldep->de_refcnt = 1;
  236. /*
  237. * Copy the directory entry into the denode area of the vnode.
  238. */
  239. if ((dirclust == MSDOSFSROOT
  240. || (FAT32(pmp) && dirclust == pmp->pm_rootdirblk))
  241. && diroffset == MSDOSFSROOT_OFS) {
  242. /*
  243. * Directory entry for the root directory. There isn't one,
  244. * so we manufacture one. We should probably rummage
  245. * through the root directory and find a label entry (if it
  246. * exists), and then use the time and date from that entry
  247. * as the time and date for the root denode.
  248. */
  249. nvp->v_flag |= VROOT; /* should be further down XXX */
  250. ldep->de_Attributes = ATTR_DIRECTORY;
  251. if (FAT32(pmp))
  252. ldep->de_StartCluster = pmp->pm_rootdirblk;
  253. /* de_FileSize will be filled in further down */
  254. else {
  255. ldep->de_StartCluster = MSDOSFSROOT;
  256. ldep->de_FileSize = pmp->pm_rootdirsize * pmp->pm_BytesPerSec;
  257. }
  258. /*
  259. * fill in time and date so that dos2unixtime() doesn't
  260. * spit up when called from msdosfs_getattr() with root
  261. * denode
  262. */
  263. ldep->de_CTime = 0x0000; /* 00:00:00 */
  264. ldep->de_CTimeHundredth = 0;
  265. ldep->de_CDate = (0 << DD_YEAR_SHIFT) | (1 << DD_MONTH_SHIFT)
  266. | (1 << DD_DAY_SHIFT);
  267. /* Jan 1, 1980 */
  268. ldep->de_ADate = ldep->de_CDate;
  269. ldep->de_MTime = ldep->de_CTime;
  270. ldep->de_MDate = ldep->de_CDate;
  271. /* leave the other fields as garbage */
  272. } else {
  273. error = readep(pmp, dirclust, diroffset, &bp, &direntptr);
  274. if (error)
  275. return (error);
  276. DE_INTERNALIZE(ldep, direntptr);
  277. brelse(bp);
  278. }
  279. /*
  280. * Fill in a few fields of the vnode and finish filling in the
  281. * denode. Then return the address of the found denode.
  282. */
  283. if (ldep->de_Attributes & ATTR_DIRECTORY) {
  284. /*
  285. * Since DOS directory entries that describe directories
  286. * have 0 in the filesize field, we take this opportunity
  287. * to find out the length of the directory and plug it into
  288. * the denode structure.
  289. */
  290. uint32_t size;
  291. nvp->v_type = VDIR;
  292. if (ldep->de_StartCluster != MSDOSFSROOT) {
  293. error = pcbmap(ldep, 0xffff, 0, &size, 0);
  294. if (error == E2BIG) {
  295. ldep->de_FileSize = de_cn2off(pmp, size);
  296. error = 0;
  297. } else if (error) {
  298. printf("deget(): pcbmap returned %d\n", error);
  299. return (error);
  300. }
  301. }
  302. } else
  303. nvp->v_type = VREG;
  304. vref(ldep->de_devvp);
  305. *depp = ldep;
  306. return (0);
  307. }
  308. int
  309. deupdat(struct denode *dep, int waitfor)
  310. {
  311. struct buf *bp;
  312. struct direntry *dirp;
  313. int error;
  314. struct timespec ts;
  315. if (DETOV(dep)->v_mount->mnt_flag & MNT_RDONLY)
  316. return (0);
  317. getnanotime(&ts);
  318. DETIMES(dep, &ts, &ts, &ts);
  319. if ((dep->de_flag & DE_MODIFIED) == 0)
  320. return (0);
  321. dep->de_flag &= ~DE_MODIFIED;
  322. if (dep->de_Attributes & ATTR_DIRECTORY)
  323. return (0);
  324. if (dep->de_refcnt <= 0)
  325. return (0);
  326. error = readde(dep, &bp, &dirp);
  327. if (error)
  328. return (error);
  329. DE_EXTERNALIZE(dirp, dep);
  330. if (waitfor)
  331. return (bwrite(bp));
  332. else {
  333. bdwrite(bp);
  334. return (0);
  335. }
  336. }
  337. /*
  338. * Truncate the file described by dep to the length specified by length.
  339. */
  340. int
  341. detrunc(struct denode *dep, uint32_t length, int flags, struct ucred *cred,
  342. struct proc *p)
  343. {
  344. int error;
  345. int allerror;
  346. int vflags;
  347. uint32_t eofentry;
  348. uint32_t chaintofree = 0;
  349. daddr_t bn;
  350. int boff;
  351. int isadir = dep->de_Attributes & ATTR_DIRECTORY;
  352. struct buf *bp;
  353. struct msdosfsmount *pmp = dep->de_pmp;
  354. #ifdef MSDOSFS_DEBUG
  355. printf("detrunc(): file %.11s, length %ld, flags %d\n",
  356. dep->de_Name, length, flags);
  357. #endif
  358. /*
  359. * Disallow attempts to truncate the root directory since it is of
  360. * fixed size. That's just the way dos filesystems are. We use
  361. * the VROOT bit in the vnode because checking for the directory
  362. * bit and a startcluster of 0 in the denode is not adequate to
  363. * recognize the root directory at this point in a file or
  364. * directory's life.
  365. */
  366. if ((DETOV(dep)->v_flag & VROOT) && !FAT32(pmp)) {
  367. printf("detrunc(): can't truncate root directory, clust %u, offset %u\n",
  368. dep->de_dirclust, dep->de_diroffset);
  369. return (EINVAL);
  370. }
  371. uvm_vnp_setsize(DETOV(dep), length);
  372. if (dep->de_FileSize < length)
  373. return (deextend(dep, length, cred));
  374. /*
  375. * If the desired length is 0 then remember the starting cluster of
  376. * the file and set the StartCluster field in the directory entry
  377. * to 0. If the desired length is not zero, then get the number of
  378. * the last cluster in the shortened file. Then get the number of
  379. * the first cluster in the part of the file that is to be freed.
  380. * Then set the next cluster pointer in the last cluster of the
  381. * file to CLUST_EOFE.
  382. */
  383. if (length == 0) {
  384. chaintofree = dep->de_StartCluster;
  385. dep->de_StartCluster = 0;
  386. eofentry = ~0;
  387. } else {
  388. error = pcbmap(dep, de_clcount(pmp, length) - 1, 0,
  389. &eofentry, 0);
  390. if (error) {
  391. #ifdef MSDOSFS_DEBUG
  392. printf("detrunc(): pcbmap fails %d\n", error);
  393. #endif
  394. return (error);
  395. }
  396. }
  397. fc_purge(dep, de_clcount(pmp, length));
  398. /*
  399. * If the new length is not a multiple of the cluster size then we
  400. * must zero the tail end of the new last cluster in case it
  401. * becomes part of the file again because of a seek.
  402. */
  403. if ((boff = length & pmp->pm_crbomask) != 0) {
  404. if (isadir) {
  405. bn = cntobn(pmp, eofentry);
  406. error = bread(pmp->pm_devvp, bn, pmp->pm_bpcluster, &bp);
  407. } else {
  408. bn = de_blk(pmp, length);
  409. error = bread(DETOV(dep), bn, pmp->pm_bpcluster, &bp);
  410. }
  411. if (error) {
  412. brelse(bp);
  413. #ifdef MSDOSFS_DEBUG
  414. printf("detrunc(): bread fails %d\n", error);
  415. #endif
  416. return (error);
  417. }
  418. uvm_vnp_uncache(DETOV(dep));
  419. /*
  420. * is this the right place for it?
  421. */
  422. bzero(bp->b_data + boff, pmp->pm_bpcluster - boff);
  423. if (flags & IO_SYNC)
  424. bwrite(bp);
  425. else
  426. bdwrite(bp);
  427. }
  428. /*
  429. * Write out the updated directory entry. Even if the update fails
  430. * we free the trailing clusters.
  431. */
  432. dep->de_FileSize = length;
  433. if (!isadir)
  434. dep->de_flag |= DE_UPDATE|DE_MODIFIED;
  435. vflags = (length > 0 ? V_SAVE : 0) | V_SAVEMETA;
  436. vinvalbuf(DETOV(dep), vflags, cred, p, 0, 0);
  437. allerror = deupdat(dep, 1);
  438. #ifdef MSDOSFS_DEBUG
  439. printf("detrunc(): allerror %d, eofentry %d\n",
  440. allerror, eofentry);
  441. #endif
  442. /*
  443. * If we need to break the cluster chain for the file then do it
  444. * now.
  445. */
  446. if (eofentry != ~0) {
  447. error = fatentry(FAT_GET_AND_SET, pmp, eofentry,
  448. &chaintofree, CLUST_EOFE);
  449. if (error) {
  450. #ifdef MSDOSFS_DEBUG
  451. printf("detrunc(): fatentry errors %d\n", error);
  452. #endif
  453. return (error);
  454. }
  455. fc_setcache(dep, FC_LASTFC, de_cluster(pmp, length - 1),
  456. eofentry);
  457. }
  458. /*
  459. * Now free the clusters removed from the file because of the
  460. * truncation.
  461. */
  462. if (chaintofree != 0 && !MSDOSFSEOF(pmp, chaintofree))
  463. freeclusterchain(pmp, chaintofree);
  464. return (allerror);
  465. }
  466. /*
  467. * Extend the file described by dep to length specified by length.
  468. */
  469. int
  470. deextend(struct denode *dep, uint32_t length, struct ucred *cred)
  471. {
  472. struct msdosfsmount *pmp = dep->de_pmp;
  473. uint32_t count;
  474. int error;
  475. /*
  476. * The root of a DOS filesystem cannot be extended.
  477. */
  478. if ((DETOV(dep)->v_flag & VROOT) && !FAT32(pmp))
  479. return (EINVAL);
  480. /*
  481. * Directories cannot be extended.
  482. */
  483. if (dep->de_Attributes & ATTR_DIRECTORY)
  484. return (EISDIR);
  485. if (length <= dep->de_FileSize)
  486. panic("deextend: file too large");
  487. /*
  488. * Compute the number of clusters to allocate.
  489. */
  490. count = de_clcount(pmp, length) - de_clcount(pmp, dep->de_FileSize);
  491. if (count > 0) {
  492. if (count > pmp->pm_freeclustercount)
  493. return (ENOSPC);
  494. error = extendfile(dep, count, NULL, NULL, DE_CLEAR);
  495. if (error) {
  496. /* truncate the added clusters away again */
  497. (void) detrunc(dep, dep->de_FileSize, 0, cred, NULL);
  498. return (error);
  499. }
  500. }
  501. dep->de_FileSize = length;
  502. dep->de_flag |= DE_UPDATE|DE_MODIFIED;
  503. return (deupdat(dep, 1));
  504. }
  505. /*
  506. * Move a denode to its correct hash queue after the file it represents has
  507. * been moved to a new directory.
  508. */
  509. void
  510. reinsert(struct denode *dep)
  511. {
  512. /*
  513. * Fix up the denode cache. If the denode is for a directory,
  514. * there is nothing to do since the hash is based on the starting
  515. * cluster of the directory file and that hasn't changed. If for a
  516. * file the hash is based on the location of the directory entry,
  517. * so we must remove it from the cache and re-enter it with the
  518. * hash based on the new location of the directory entry.
  519. */
  520. if (dep->de_Attributes & ATTR_DIRECTORY)
  521. return;
  522. msdosfs_hashrem(dep);
  523. msdosfs_hashins(dep);
  524. }
  525. int
  526. msdosfs_reclaim(void *v)
  527. {
  528. struct vop_reclaim_args *ap = v;
  529. struct vnode *vp = ap->a_vp;
  530. struct denode *dep = VTODE(vp);
  531. #ifdef DIAGNOSTIC
  532. extern int prtactive;
  533. if (prtactive && vp->v_usecount != 0)
  534. vprint("msdosfs_reclaim(): pushing active", vp);
  535. #endif
  536. #ifdef MSDOSFS_DEBUG
  537. printf("msdosfs_reclaim(): dep %08x, file %.11s, refcnt %d\n",
  538. dep, dep->de_Name, dep->de_refcnt);
  539. #endif
  540. /*
  541. * Remove the denode from its hash chain.
  542. */
  543. msdosfs_hashrem(dep);
  544. /*
  545. * Purge old data structures associated with the denode.
  546. */
  547. cache_purge(vp);
  548. if (dep->de_devvp) {
  549. vrele(dep->de_devvp);
  550. dep->de_devvp = 0;
  551. }
  552. #if 0 /* XXX */
  553. dep->de_flag = 0;
  554. #endif
  555. free(dep, M_MSDOSFSNODE, 0);
  556. vp->v_data = NULL;
  557. return (0);
  558. }
  559. int
  560. msdosfs_inactive(void *v)
  561. {
  562. struct vop_inactive_args *ap = v;
  563. struct vnode *vp = ap->a_vp;
  564. struct denode *dep = VTODE(vp);
  565. struct proc *p = ap->a_p;
  566. int error;
  567. #ifdef DIAGNOSTIC
  568. extern int prtactive;
  569. if (prtactive && vp->v_usecount != 0)
  570. vprint("msdosfs_inactive(): pushing active", vp);
  571. #endif
  572. #ifdef MSDOSFS_DEBUG
  573. printf("msdosfs_inactive(): dep %08x, de_Name[0] %x\n", dep,
  574. dep->de_Name[0]);
  575. #endif
  576. error = 0;
  577. /*
  578. * Get rid of denodes related to stale file handles.
  579. */
  580. if (dep->de_Name[0] == SLOT_DELETED)
  581. goto out;
  582. /*
  583. * If the file has been deleted and it is on a read/write
  584. * filesystem, then truncate the file, and mark the directory slot
  585. * as empty. (This may not be necessary for the dos filesystem.)
  586. */
  587. #ifdef MSDOSFS_DEBUG
  588. printf("msdosfs_inactive(): dep %08x, refcnt %d, mntflag %x, MNT_RDONLY %x\n",
  589. dep, dep->de_refcnt, vp->v_mount->mnt_flag, MNT_RDONLY);
  590. #endif
  591. if (dep->de_refcnt <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
  592. error = detrunc(dep, (uint32_t)0, 0, NOCRED, NULL);
  593. dep->de_Name[0] = SLOT_DELETED;
  594. }
  595. deupdat(dep, 0);
  596. out:
  597. VOP_UNLOCK(vp, 0, p);
  598. /*
  599. * If we are done with the denode, reclaim it
  600. * so that it can be reused immediately.
  601. */
  602. #ifdef MSDOSFS_DEBUG
  603. printf("msdosfs_inactive(): v_usecount %d, de_Name[0] %x\n",
  604. vp->v_usecount, dep->de_Name[0]);
  605. #endif
  606. if (dep->de_Name[0] == SLOT_DELETED)
  607. vrecycle(vp, p);
  608. return (error);
  609. }