1 /* $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/msdosfs/Attic/msdosfs_vfsops.c,v 1.60.2.8 2004/03/02 09:43:04 tjr Exp $ */
2 /* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vfsops.c,v 1.52 2008/09/17 21:44:24 dillon Exp $ */
3 /* $NetBSD: msdosfs_vfsops.c,v 1.51 1997/11/17 15:36:58 ws Exp $ */
6 * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
7 * Copyright (C) 1994, 1995, 1997 TooLs GmbH.
9 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
37 * Written by Paul Popelka (paulp@uts.amdahl.com)
39 * You can do anything you want with this software, just don't say you wrote
40 * it, and don't remove this notice.
42 * This software is provided "as is".
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.
52 #include <sys/param.h>
53 #include <sys/systm.h>
56 #include <sys/nlookup.h>
57 #include <sys/kernel.h>
58 #include <sys/vnode.h>
59 #include <sys/mount.h>
61 #include <sys/fcntl.h>
62 #include <sys/malloc.h>
63 #include <sys/stat.h> /* defines ALLPERMS */
64 #include <vm/vm_zone.h>
70 #include "msdosfsmount.h"
73 extern struct vop_ops msdosfs_vnode_vops
;
75 #define MSDOSFS_DFLTBSIZE 4096
79 * XXX - The boot signature formatted by NEC PC-98 DOS looks like a
80 * garbage or a random value :-{
81 * If you want to use that broken-signatured media, define the
82 * following symbol even though PC/AT.
83 * (ex. mount PC-98 DOS formatted FD on PC/AT)
85 #define MSDOSFS_NOCHECKSIG
88 MALLOC_DEFINE(M_MSDOSFSMNT
, "MSDOSFS mount", "MSDOSFS mount structure");
89 static MALLOC_DEFINE(M_MSDOSFSFAT
, "MSDOSFS FAT", "MSDOSFS file allocation table");
91 static int update_mp (struct mount
*mp
, struct msdosfs_args
*argp
);
92 static int mountmsdosfs (struct vnode
*devvp
, struct mount
*mp
,
93 struct msdosfs_args
*argp
);
94 static int msdosfs_fhtovp (struct mount
*, struct vnode
*,
95 struct fid
*, struct vnode
**);
96 static int msdosfs_checkexp (struct mount
*, struct sockaddr
*,
97 int *, struct ucred
**);
98 static int msdosfs_mount (struct mount
*, char *, caddr_t
,
100 static int msdosfs_root (struct mount
*, struct vnode
**);
101 static int msdosfs_statfs (struct mount
*, struct statfs
*,
103 static int msdosfs_sync (struct mount
*, int);
104 static int msdosfs_unmount (struct mount
*, int);
105 static int msdosfs_vptofh (struct vnode
*, struct fid
*);
108 update_mp(struct mount
*mp
, struct msdosfs_args
*argp
)
110 struct msdosfsmount
*pmp
= VFSTOMSDOSFS(mp
);
113 pmp
->pm_gid
= argp
->gid
;
114 pmp
->pm_uid
= argp
->uid
;
115 pmp
->pm_mask
= argp
->mask
& ALLPERMS
;
116 pmp
->pm_flags
|= argp
->flags
& MSDOSFSMNT_MNTOPT
;
117 if (pmp
->pm_flags
& MSDOSFSMNT_U2WTABLE
) {
118 bcopy(argp
->u2w
, pmp
->pm_u2w
, sizeof(pmp
->pm_u2w
));
119 bcopy(argp
->d2u
, pmp
->pm_d2u
, sizeof(pmp
->pm_d2u
));
120 bcopy(argp
->u2d
, pmp
->pm_u2d
, sizeof(pmp
->pm_u2d
));
122 if (pmp
->pm_flags
& MSDOSFSMNT_ULTABLE
) {
123 bcopy(argp
->ul
, pmp
->pm_ul
, sizeof(pmp
->pm_ul
));
124 bcopy(argp
->lu
, pmp
->pm_lu
, sizeof(pmp
->pm_lu
));
127 if (pmp
->pm_flags
& MSDOSFSMNT_NOWIN95
)
128 pmp
->pm_flags
|= MSDOSFSMNT_SHORTNAME
;
129 else if (!(pmp
->pm_flags
&
130 (MSDOSFSMNT_SHORTNAME
| MSDOSFSMNT_LONGNAME
))) {
131 struct vnode
*rootvp
;
134 * Try to divine whether to support Win'95 long filenames
137 pmp
->pm_flags
|= MSDOSFSMNT_LONGNAME
;
139 if ((error
= msdosfs_root(mp
, &rootvp
)) != 0)
141 pmp
->pm_flags
|= findwin95(VTODE(rootvp
))
142 ? MSDOSFSMNT_LONGNAME
143 : MSDOSFSMNT_SHORTNAME
;
151 * mp - path - addr in user space of mount point (ie /usr or whatever)
152 * data - addr in user space of mount params including the name of the block
153 * special file to treat as a filesystem.
156 msdosfs_mount(struct mount
*mp
, char *path
, caddr_t data
, struct ucred
*cred
)
158 struct vnode
*devvp
; /* vnode for blk device to mount */
159 struct msdosfs_args args
; /* will hold data from mount request */
160 /* msdosfs specific mount control block */
161 struct msdosfsmount
*pmp
= NULL
;
165 struct nlookupdata nd
;
167 error
= copyin(data
, (caddr_t
)&args
, sizeof(struct msdosfs_args
));
170 if (args
.magic
!= MSDOSFS_ARGSMAGIC
)
173 * If updating, check whether changing from read-only to
174 * read/write; if there is no device name, that's all we do.
176 if (mp
->mnt_flag
& MNT_UPDATE
) {
177 pmp
= VFSTOMSDOSFS(mp
);
179 if (!(pmp
->pm_flags
& MSDOSFSMNT_RONLY
) && (mp
->mnt_flag
& MNT_RDONLY
)) {
181 if (mp
->mnt_flag
& MNT_FORCE
)
183 error
= vflush(mp
, 0, flags
);
185 devvp
= pmp
->pm_devvp
;
186 VOP_OPEN(devvp
, FREAD
, FSCRED
, NULL
);
187 VOP_CLOSE(devvp
, FREAD
|FWRITE
);
188 pmp
->pm_flags
|= MSDOSFSMNT_RONLY
;
191 if (!error
&& (mp
->mnt_flag
& MNT_RELOAD
))
192 /* not yet implemented */
196 if ((pmp
->pm_flags
& MSDOSFSMNT_RONLY
) && (mp
->mnt_kern_flag
& MNTK_WANTRDWR
)) {
198 * If upgrade to read-write by non-root, then verify
199 * that user has necessary permissions on the device.
201 devvp
= pmp
->pm_devvp
;
202 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
203 if (cred
->cr_uid
!= 0) {
204 error
= VOP_EACCESS(devvp
, VREAD
| VWRITE
, cred
);
210 VOP_OPEN(devvp
, FREAD
|FWRITE
, FSCRED
, NULL
);
211 VOP_CLOSE(devvp
, FREAD
);
213 pmp
->pm_flags
&= ~MSDOSFSMNT_RONLY
;
215 if (args
.fspec
== 0) {
216 #ifdef __notyet__ /* doesn't work correctly with current mountd XXX */
217 if (args
.flags
& MSDOSFSMNT_MNTOPT
) {
218 pmp
->pm_flags
&= ~MSDOSFSMNT_MNTOPT
;
219 pmp
->pm_flags
|= args
.flags
& MSDOSFSMNT_MNTOPT
;
220 if (pmp
->pm_flags
& MSDOSFSMNT_NOWIN95
)
221 pmp
->pm_flags
|= MSDOSFSMNT_SHORTNAME
;
225 * Process export requests.
227 return (vfs_export(mp
, &pmp
->pm_export
, &args
.export
));
231 * Not an update, or updating the name: look up the name
232 * and verify that it refers to a sensible block device.
235 error
= nlookup_init(&nd
, args
.fspec
, UIO_USERSPACE
, NLC_FOLLOW
);
237 error
= nlookup(&nd
);
239 error
= cache_vref(&nd
.nl_nch
, nd
.nl_cred
, &devvp
);
244 if (!vn_isdisk(devvp
, &error
)) {
249 * If mount by non-root, then verify that user has necessary
250 * permissions on the device.
252 if (cred
->cr_uid
!= 0) {
254 if ((mp
->mnt_flag
& MNT_RDONLY
) == 0)
255 accessmode
|= VWRITE
;
256 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
257 error
= VOP_EACCESS(devvp
, accessmode
, cred
);
264 if ((mp
->mnt_flag
& MNT_UPDATE
) == 0) {
265 error
= mountmsdosfs(devvp
, mp
, &args
);
266 #ifdef MSDOSFS_DEBUG /* only needed for the kprintf below */
267 pmp
= VFSTOMSDOSFS(mp
);
270 if (devvp
!= pmp
->pm_devvp
)
271 error
= EINVAL
; /* XXX needs translation */
280 error
= update_mp(mp
, &args
);
282 msdosfs_unmount(mp
, MNT_FORCE
);
286 copyinstr(args
.fspec
, mp
->mnt_stat
.f_mntfromname
, MNAMELEN
- 1, &size
);
287 bzero(mp
->mnt_stat
.f_mntfromname
+ size
, MNAMELEN
- size
);
288 msdosfs_statfs(mp
, &mp
->mnt_stat
, cred
);
290 kprintf("msdosfs_mount(): mp %p, pmp %p, inusemap %p\n", mp
, pmp
, pmp
->pm_inusemap
);
296 mountmsdosfs(struct vnode
*devvp
, struct mount
*mp
, struct msdosfs_args
*argp
)
298 struct msdosfsmount
*pmp
;
301 union bootsector
*bsp
;
302 struct byte_bpb33
*b33
;
303 struct byte_bpb50
*b50
;
304 struct byte_bpb710
*b710
;
305 u_int8_t SecPerClust
;
310 * Disallow multiple mounts of the same device.
311 * Disallow mounting of a device that is currently in use
312 * Flush out any old buffers remaining from a previous use.
314 error
= vfs_mountedon(devvp
);
317 if (vcount(devvp
) > 0)
319 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
320 error
= vinvalbuf(devvp
, V_SAVE
, 0, 0);
325 ronly
= (mp
->mnt_flag
& MNT_RDONLY
) != 0;
326 vn_lock(devvp
, LK_EXCLUSIVE
| LK_RETRY
);
327 error
= VOP_OPEN(devvp
, ronly
? FREAD
: FREAD
|FWRITE
, FSCRED
, NULL
);
332 bp
= NULL
; /* both used in error_exit */
336 * Read the boot sector of the filesystem, and then check the
337 * boot signature. If not a dos boot sector then error out.
339 * NOTE: 2048 is a maximum sector size in current...
341 error
= bread(devvp
, 0, 2048, &bp
);
344 bp
->b_flags
|= B_AGE
;
345 bsp
= (union bootsector
*)bp
->b_data
;
346 b33
= (struct byte_bpb33
*)bsp
->bs33
.bsBPB
;
347 b50
= (struct byte_bpb50
*)bsp
->bs50
.bsBPB
;
348 b710
= (struct byte_bpb710
*)bsp
->bs710
.bsPBP
;
350 #ifndef MSDOSFS_NOCHECKSIG
351 if (bsp
->bs50
.bsBootSectSig0
!= BOOTSIG0
352 || bsp
->bs50
.bsBootSectSig1
!= BOOTSIG1
) {
358 pmp
= kmalloc(sizeof *pmp
, M_MSDOSFSMNT
, M_WAITOK
| M_ZERO
);
362 * Compute several useful quantities from the bpb in the
363 * bootsector. Copy in the dos 5 variant of the bpb then fix up
364 * the fields that are different between dos 5 and dos 3.3.
366 SecPerClust
= b50
->bpbSecPerClust
;
367 pmp
->pm_BytesPerSec
= getushort(b50
->bpbBytesPerSec
);
368 pmp
->pm_ResSectors
= getushort(b50
->bpbResSectors
);
369 pmp
->pm_FATs
= b50
->bpbFATs
;
370 pmp
->pm_RootDirEnts
= getushort(b50
->bpbRootDirEnts
);
371 pmp
->pm_Sectors
= getushort(b50
->bpbSectors
);
372 pmp
->pm_FATsecs
= getushort(b50
->bpbFATsecs
);
373 pmp
->pm_SecPerTrack
= getushort(b50
->bpbSecPerTrack
);
374 pmp
->pm_Heads
= getushort(b50
->bpbHeads
);
375 pmp
->pm_Media
= b50
->bpbMedia
;
377 /* calculate the ratio of sector size to DEV_BSIZE */
378 pmp
->pm_BlkPerSec
= pmp
->pm_BytesPerSec
/ DEV_BSIZE
;
381 * We don't check pm_Heads nor pm_SecPerTrack, because
382 * these may not be set for EFI file systems. We don't
383 * use these anyway, so we're unaffected if they are
386 if (!pmp
->pm_BytesPerSec
|| !SecPerClust
) {
391 if (pmp
->pm_Sectors
== 0) {
392 pmp
->pm_HiddenSects
= getulong(b50
->bpbHiddenSecs
);
393 pmp
->pm_HugeSectors
= getulong(b50
->bpbHugeSectors
);
395 pmp
->pm_HiddenSects
= getushort(b33
->bpbHiddenSecs
);
396 pmp
->pm_HugeSectors
= pmp
->pm_Sectors
;
399 if (pmp
->pm_RootDirEnts
== 0) {
402 || getushort(b710
->bpbFSVers
)) {
404 kprintf("mountmsdosfs(): bad FAT32 filesystem\n");
407 pmp
->pm_fatmask
= FAT32_MASK
;
410 pmp
->pm_FATsecs
= getulong(b710
->bpbBigFATsecs
);
411 if (getushort(b710
->bpbExtFlags
) & FATMIRROR
)
412 pmp
->pm_curfat
= getushort(b710
->bpbExtFlags
) & FATNUM
;
414 pmp
->pm_flags
|= MSDOSFS_FATMIRROR
;
416 pmp
->pm_flags
|= MSDOSFS_FATMIRROR
;
419 * Check a few values (could do some more):
420 * - logical sector size: power of 2, >= block size
421 * - sectors per cluster: power of 2, >= 1
422 * - number of sectors: >= 1, <= size of partition
424 if ( (SecPerClust
== 0)
425 || (SecPerClust
& (SecPerClust
- 1))
426 || (pmp
->pm_BytesPerSec
< DEV_BSIZE
)
427 || (pmp
->pm_BytesPerSec
& (pmp
->pm_BytesPerSec
- 1))
428 || (pmp
->pm_HugeSectors
== 0)
434 pmp
->pm_HugeSectors
*= pmp
->pm_BlkPerSec
;
435 pmp
->pm_HiddenSects
*= pmp
->pm_BlkPerSec
; /* XXX not used? */
436 pmp
->pm_FATsecs
*= pmp
->pm_BlkPerSec
;
437 SecPerClust
*= pmp
->pm_BlkPerSec
;
439 pmp
->pm_fatblk
= pmp
->pm_ResSectors
* pmp
->pm_BlkPerSec
;
442 pmp
->pm_rootdirblk
= getulong(b710
->bpbRootClust
);
443 pmp
->pm_firstcluster
= pmp
->pm_fatblk
444 + (pmp
->pm_FATs
* pmp
->pm_FATsecs
);
445 pmp
->pm_fsinfo
= getushort(b710
->bpbFSInfo
) * pmp
->pm_BlkPerSec
;
447 pmp
->pm_rootdirblk
= pmp
->pm_fatblk
+
448 (pmp
->pm_FATs
* pmp
->pm_FATsecs
);
449 pmp
->pm_rootdirsize
= (pmp
->pm_RootDirEnts
* sizeof(struct direntry
)
451 / DEV_BSIZE
; /* in blocks */
452 pmp
->pm_firstcluster
= pmp
->pm_rootdirblk
+ pmp
->pm_rootdirsize
;
455 pmp
->pm_maxcluster
= (pmp
->pm_HugeSectors
- pmp
->pm_firstcluster
) /
457 pmp
->pm_fatsize
= pmp
->pm_FATsecs
* DEV_BSIZE
; /* XXX not used? */
459 if (pmp
->pm_fatmask
== 0) {
460 if (pmp
->pm_maxcluster
461 <= ((CLUST_RSRVD
- CLUST_FIRST
) & FAT12_MASK
)) {
463 * This will usually be a floppy disk. This size makes
464 * sure that one fat entry will not be split across
467 pmp
->pm_fatmask
= FAT12_MASK
;
471 pmp
->pm_fatmask
= FAT16_MASK
;
477 clusters
= (pmp
->pm_fatsize
/ pmp
->pm_fatmult
) * pmp
->pm_fatdiv
;
478 if (pmp
->pm_maxcluster
>= clusters
) {
479 kprintf("Warning: number of clusters (%ld) exceeds FAT "
480 "capacity (%ld)\n", pmp
->pm_maxcluster
+ 1, clusters
);
481 pmp
->pm_maxcluster
= clusters
- 1;
486 pmp
->pm_fatblocksize
= 3 * pmp
->pm_BytesPerSec
;
488 pmp
->pm_fatblocksize
= MSDOSFS_DFLTBSIZE
;
490 pmp
->pm_fatblocksec
= pmp
->pm_fatblocksize
/ DEV_BSIZE
;
491 pmp
->pm_bnshift
= DEV_BSHIFT
;
494 * Compute mask and shift value for isolating cluster relative byte
495 * offsets and cluster numbers from a file offset.
497 pmp
->pm_bpcluster
= SecPerClust
* DEV_BSIZE
;
498 pmp
->pm_crbomask
= pmp
->pm_bpcluster
- 1;
499 pmp
->pm_cnshift
= ffs(pmp
->pm_bpcluster
) - 1;
502 * Check for valid cluster size
503 * must be a power of 2
505 if (pmp
->pm_bpcluster
^ (1 << pmp
->pm_cnshift
)) {
511 * Release the bootsector buffer.
519 if (pmp
->pm_fsinfo
) {
522 if ((error
= bread(devvp
, de_bntodoff(pmp
, pmp
->pm_fsinfo
), fsi_size(pmp
), &bp
)) != 0)
524 fp
= (struct fsinfo
*)bp
->b_data
;
525 if (!bcmp(fp
->fsisig1
, "RRaA", 4)
526 && !bcmp(fp
->fsisig2
, "rrAa", 4)
527 && !bcmp(fp
->fsisig3
, "\0\0\125\252", 4)
528 && !bcmp(fp
->fsisig4
, "\0\0\125\252", 4)) {
529 pmp
->pm_nxtfree
= getulong(fp
->fsinxtfree
);
530 if (pmp
->pm_nxtfree
== 0xffffffff)
531 pmp
->pm_nxtfree
= CLUST_FIRST
;
539 * Check and validate (or perhaps invalidate?) the fsinfo structure?
541 if (pmp
->pm_fsinfo
&& pmp
->pm_nxtfree
> pmp
->pm_maxcluster
) {
543 "Next free cluster in FSInfo (%lu) exceeds maxcluster (%lu)\n",
544 pmp
->pm_nxtfree
, pmp
->pm_maxcluster
);
550 * Allocate memory for the bitmap of allocated clusters, and then
553 pmp
->pm_inusemap
= kmalloc(((pmp
->pm_maxcluster
+ N_INUSEBITS
- 1)
555 * sizeof(*pmp
->pm_inusemap
),
556 M_MSDOSFSFAT
, M_WAITOK
);
559 * fillinusemap() needs pm_devvp.
562 pmp
->pm_devvp
= devvp
;
565 * Have the inuse map filled in.
567 if ((error
= fillinusemap(pmp
)) != 0)
571 * If they want fat updates to be synchronous then let them suffer
572 * the performance degradation in exchange for the on disk copy of
573 * the fat being correct just about all the time. I suppose this
574 * would be a good thing to turn on if the kernel is still flakey.
576 if (mp
->mnt_flag
& MNT_SYNCHRONOUS
)
577 pmp
->pm_flags
|= MSDOSFSMNT_WAITONFAT
;
583 pmp
->pm_flags
|= MSDOSFSMNT_RONLY
;
586 mp
->mnt_data
= (qaddr_t
) pmp
;
587 mp
->mnt_stat
.f_fsid
.val
[0] = dev2udev(dev
);
588 mp
->mnt_stat
.f_fsid
.val
[1] = mp
->mnt_vfc
->vfc_typenum
;
589 mp
->mnt_flag
|= MNT_LOCAL
;
590 vfs_add_vnodeops(mp
, &msdosfs_vnode_vops
, &mp
->mnt_vn_norm_ops
);
591 dev
->si_mountpoint
= mp
;
598 VOP_CLOSE(devvp
, ronly
? FREAD
: FREAD
| FWRITE
);
600 if (pmp
->pm_inusemap
)
601 kfree(pmp
->pm_inusemap
, M_MSDOSFSFAT
);
602 kfree(pmp
, M_MSDOSFSMNT
);
603 mp
->mnt_data
= (qaddr_t
)0;
609 * Unmount the filesystem described by mp.
612 msdosfs_unmount(struct mount
*mp
, int mntflags
)
614 struct msdosfsmount
*pmp
;
618 if (mntflags
& MNT_FORCE
)
620 error
= vflush(mp
, 0, flags
);
623 pmp
= VFSTOMSDOSFS(mp
);
624 pmp
->pm_devvp
->v_rdev
->si_mountpoint
= NULL
;
627 struct vnode
*vp
= pmp
->pm_devvp
;
629 kprintf("msdosfs_umount(): just before calling VOP_CLOSE()\n");
630 kprintf("flag %08x, sysrefs %d, writecount %d, auxrefs %d\n",
631 vp
->v_flag
, vp
->v_sysref
.refcnt
,
632 vp
->v_writecount
, vp
->v_auxrefs
);
633 kprintf("mount %p, op %p\n", vp
->v_mount
, vp
->v_ops
);
634 kprintf("mount %p\n", vp
->v_mount
);
635 kprintf("cleanblkhd %p, dirtyblkhd %p, numoutput %d, type %d\n",
636 RB_ROOT(&vp
->v_rbclean_tree
),
637 RB_ROOT(&vp
->v_rbdirty_tree
),
638 bio_track_active(&vp
->v_track_write
),
640 kprintf("union %p, tag %d, data[0] %08x, data[1] %08x\n",
641 vp
->v_socket
, vp
->v_tag
,
642 ((u_int
*)vp
->v_data
)[0],
643 ((u_int
*)vp
->v_data
)[1]);
646 error
= VOP_CLOSE(pmp
->pm_devvp
,
647 (pmp
->pm_flags
&MSDOSFSMNT_RONLY
) ? FREAD
: FREAD
| FWRITE
);
648 vrele(pmp
->pm_devvp
);
649 kfree(pmp
->pm_inusemap
, M_MSDOSFSFAT
);
650 kfree(pmp
, M_MSDOSFSMNT
);
651 mp
->mnt_data
= (qaddr_t
)0;
652 mp
->mnt_flag
&= ~MNT_LOCAL
;
657 msdosfs_root(struct mount
*mp
, struct vnode
**vpp
)
659 struct msdosfsmount
*pmp
= VFSTOMSDOSFS(mp
);
664 kprintf("msdosfs_root(); mp %p, pmp %p\n", mp
, pmp
);
666 error
= deget(pmp
, MSDOSFSROOT
, MSDOSFSROOT_OFS
, &ndep
);
674 msdosfs_statfs(struct mount
*mp
, struct statfs
*sbp
, struct ucred
*cred
)
676 struct msdosfsmount
*pmp
;
678 pmp
= VFSTOMSDOSFS(mp
);
679 sbp
->f_bsize
= pmp
->pm_bpcluster
;
680 sbp
->f_iosize
= pmp
->pm_bpcluster
;
681 sbp
->f_blocks
= pmp
->pm_maxcluster
+ 1;
682 sbp
->f_bfree
= pmp
->pm_freeclustercount
;
683 sbp
->f_bavail
= pmp
->pm_freeclustercount
;
684 sbp
->f_files
= pmp
->pm_RootDirEnts
; /* XXX */
685 sbp
->f_ffree
= 0; /* what to put in here? */
686 if (sbp
!= &mp
->mnt_stat
) {
687 sbp
->f_type
= mp
->mnt_vfc
->vfc_typenum
;
688 bcopy(mp
->mnt_stat
.f_mntfromname
, sbp
->f_mntfromname
, MNAMELEN
);
690 strncpy(sbp
->f_fstypename
, mp
->mnt_vfc
->vfc_name
, MFSNAMELEN
);
700 static int msdosfs_sync_scan(struct mount
*mp
, struct vnode
*vp
, void *data
);
703 msdosfs_sync(struct mount
*mp
, int waitfor
)
705 struct msdosfsmount
*pmp
= VFSTOMSDOSFS(mp
);
706 struct scaninfo scaninfo
;
710 * If we ever switch to not updating all of the fats all the time,
711 * this would be the place to update them from the first one.
713 if (pmp
->pm_fmod
!= 0) {
714 if (pmp
->pm_flags
& MSDOSFSMNT_RONLY
)
715 panic("msdosfs_sync: rofs mod");
717 /* update fats here */
721 * Write back each (modified) denode.
723 scaninfo
.allerror
= 0;
725 while (scaninfo
.rescan
) {
727 vmntvnodescan(mp
, VMSC_GETVP
|VMSC_NOWAIT
, NULL
, msdosfs_sync_scan
, &scaninfo
);
731 * Flush filesystem control info.
733 if (waitfor
!= MNT_LAZY
) {
734 vn_lock(pmp
->pm_devvp
, LK_EXCLUSIVE
| LK_RETRY
);
735 if ((error
= VOP_FSYNC(pmp
->pm_devvp
, waitfor
, 0)) != 0)
736 scaninfo
.allerror
= error
;
737 vn_unlock(pmp
->pm_devvp
);
739 return (scaninfo
.allerror
);
743 msdosfs_sync_scan(struct mount
*mp
, struct vnode
*vp
, void *data
)
745 struct scaninfo
*info
= data
;
750 if (vp
->v_type
== VNON
|| vp
->v_type
== VBAD
||
752 (DE_ACCESS
| DE_CREATE
| DE_UPDATE
| DE_MODIFIED
)) == 0 &&
753 (RB_EMPTY(&vp
->v_rbdirty_tree
) || info
->waitfor
== MNT_LAZY
))) {
756 if ((error
= VOP_FSYNC(vp
, info
->waitfor
, 0)) != 0)
757 info
->allerror
= error
;
762 msdosfs_fhtovp(struct mount
*mp
, struct vnode
*rootvp
,
763 struct fid
*fhp
, struct vnode
**vpp
)
765 struct msdosfsmount
*pmp
= VFSTOMSDOSFS(mp
);
766 struct defid
*defhp
= (struct defid
*) fhp
;
770 error
= deget(pmp
, defhp
->defid_dirclust
, defhp
->defid_dirofs
, &dep
);
780 msdosfs_checkexp(struct mount
*mp
, struct sockaddr
*nam
, int *exflagsp
,
781 struct ucred
**credanonp
)
783 struct msdosfsmount
*pmp
= VFSTOMSDOSFS(mp
);
786 np
= vfs_export_lookup(mp
, &pmp
->pm_export
, nam
);
789 *exflagsp
= np
->netc_exflags
;
790 *credanonp
= &np
->netc_anon
;
795 msdosfs_vptofh(struct vnode
*vp
, struct fid
*fhp
)
801 defhp
= (struct defid
*)fhp
;
802 defhp
->defid_len
= sizeof(struct defid
);
803 defhp
->defid_dirclust
= dep
->de_dirclust
;
804 defhp
->defid_dirofs
= dep
->de_diroffset
;
805 /* defhp->defid_gen = dep->de_gen; */
809 static struct vfsops msdosfs_vfsops
= {
810 .vfs_mount
= msdosfs_mount
,
811 .vfs_unmount
= msdosfs_unmount
,
812 .vfs_root
= msdosfs_root
,
813 .vfs_statfs
= msdosfs_statfs
,
814 .vfs_sync
= msdosfs_sync
,
815 .vfs_fhtovp
= msdosfs_fhtovp
,
816 .vfs_checkexp
= msdosfs_checkexp
,
817 .vfs_vptofh
= msdosfs_vptofh
,
818 .vfs_init
= msdosfs_init
,
819 .vfs_uninit
= msdosfs_uninit
822 VFS_SET(msdosfs_vfsops
, msdos
, 0);