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