msdosfs_vfsops.c revision 2946
1/* $Id: msdosfs_vfsops.c,v 1.2 1994/09/19 19:24:44 dfr Exp $ */ 2/* $NetBSD: msdosfs_vfsops.c,v 1.19 1994/08/21 18:44:10 ws Exp $ */ 3 4/*- 5 * Copyright (C) 1994 Wolfgang Solfrank. 6 * Copyright (C) 1994 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/namei.h> 54#include <sys/proc.h> 55#include <sys/kernel.h> 56#include <sys/vnode.h> 57#include <miscfs/specfs/specdev.h> /* XXX */ /* defines v_rdev */ 58#include <sys/mount.h> 59#include <sys/buf.h> 60#include <sys/file.h> 61#include <sys/malloc.h> 62 63#include <msdosfs/bpb.h> 64#include <msdosfs/bootsect.h> 65#include <msdosfs/direntry.h> 66#include <msdosfs/denode.h> 67#include <msdosfs/msdosfsmount.h> 68#include <msdosfs/fat.h> 69 70int msdosfsdoforce = 1; /* 1 = force unmount */ 71 72/* 73 * mp - path - addr in user space of mount point (ie /usr or whatever) 74 * data - addr in user space of mount params including the name of the block 75 * special file to treat as a filesystem. 76 */ 77int 78msdosfs_mount(mp, path, data, ndp, p) 79 struct mount *mp; 80 char *path; 81 caddr_t data; 82 struct nameidata *ndp; 83 struct proc *p; 84{ 85 struct vnode *devvp; /* vnode for blk device to mount */ 86 struct msdosfs_args args; /* will hold data from mount request */ 87 struct msdosfsmount *pmp; /* msdosfs specific mount control block */ 88 int error, flags; 89 u_int size; 90 struct ucred *cred, *scred; 91 struct vattr va; 92 93 /* 94 * Copy in the args for the mount request. 95 */ 96 if (error = copyin(data, (caddr_t) & args, sizeof(struct msdosfs_args))) 97 return error; 98 99 /* 100 * If they just want to update then be sure we can do what is 101 * asked. Can't change a filesystem from read/write to read only. 102 * Why? And if they've supplied a new device file name then we 103 * continue, otherwise return. 104 */ 105 if (mp->mnt_flag & MNT_UPDATE) { 106 pmp = (struct msdosfsmount *) mp->mnt_data; 107 error = 0; 108 if (pmp->pm_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { 109 flags = WRITECLOSE; 110 if (mp->mnt_flag & MNT_FORCE) 111 flags |= FORCECLOSE; 112 if (vfs_busy(mp)) 113 return EBUSY; 114 error = vflush(mp, NULLVP, flags); 115 vfs_unbusy(mp); 116 } 117 if (!error && (mp->mnt_flag & MNT_RELOAD)) 118 /* not yet implemented */ 119 error = EINVAL; 120 if (error) 121 return error; 122 if (pmp->pm_ronly && (mp->mnt_flag & MNT_RDONLY) == 0) 123 pmp->pm_ronly = 0; 124 if (args.fspec == 0) { 125 /* 126 * Process export requests. 127 */ 128 return vfs_export(mp, &pmp->pm_export, &args.export); 129 } 130 } else 131 pmp = NULL; 132 133 /* 134 * check to see that the user in owns the target directory. 135 * Note the very XXX trick to make sure we're checking as the 136 * real user -- were mount() executable by anyone, this wouldn't 137 * be a problem. 138 * 139 * XXX there should be one consistent error out. 140 */ 141 cred = crdup(p->p_ucred); /* XXX */ 142 cred->cr_uid = p->p_cred->p_ruid; /* XXX */ 143 error = VOP_GETATTR(mp->mnt_vnodecovered, &va, cred, p); 144 if (error) { 145 crfree(cred); /* XXX */ 146 return error; 147 } 148 if (cred->cr_uid != 0) { 149 if (va.va_uid != cred->cr_uid) { 150 error = EACCES; 151 crfree(cred); /* XXX */ 152 return error; 153 } 154 155 /* a user mounted it; we'll verify permissions when unmounting */ 156 mp->mnt_flag |= MNT_USER; 157 } 158 159 /* 160 * Now, lookup the name of the block device this mount or name 161 * update request is to apply to. 162 */ 163 NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p); 164 scred = p->p_ucred; /* XXX */ 165 p->p_ucred = cred; /* XXX */ 166 error = namei(ndp); 167 p->p_ucred = scred; /* XXX */ 168 crfree(cred); /* XXX */ 169 if (error != 0) 170 return error; 171 172 /* 173 * Be sure they've given us a block device to treat as a 174 * filesystem. And, that its major number is within the bdevsw 175 * table. 176 */ 177 devvp = ndp->ni_vp; 178 if (devvp->v_type != VBLK) { 179 vrele(devvp); 180 return ENOTBLK; 181 } 182 if (major(devvp->v_rdev) >= nblkdev) { 183 vrele(devvp); 184 return ENXIO; 185 } 186 187 /* 188 * If this is an update, then make sure the vnode for the block 189 * special device is the same as the one our filesystem is in. 190 */ 191 if (mp->mnt_flag & MNT_UPDATE) { 192 if (devvp != pmp->pm_devvp) 193 error = EINVAL; 194 else 195 vrele(devvp); 196 } else { 197 198 /* 199 * Well, it's not an update, it's a real mount request. 200 * Time to get dirty. 201 */ 202 error = mountmsdosfs(devvp, mp, p); 203 } 204 if (error) { 205 vrele(devvp); 206 return error; 207 } 208 209 /* 210 * Copy in the name of the directory the filesystem is to be 211 * mounted on. Then copy in the name of the block special file 212 * representing the filesystem being mounted. And we clear the 213 * remainder of the character strings to be tidy. Set up the 214 * user id/group id/mask as specified by the user. Then, we try to 215 * fill in the filesystem stats structure as best we can with 216 * whatever applies from a dos file system. 217 */ 218 pmp = (struct msdosfsmount *) mp->mnt_data; 219 copyinstr(path, (caddr_t) mp->mnt_stat.f_mntonname, 220 sizeof(mp->mnt_stat.f_mntonname) - 1, &size); 221 bzero(mp->mnt_stat.f_mntonname + size, 222 sizeof(mp->mnt_stat.f_mntonname) - size); 223 copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size); 224 bzero(mp->mnt_stat.f_mntfromname + size, 225 MNAMELEN - size); 226 pmp->pm_mounter = p->p_cred->p_ruid; 227 pmp->pm_gid = args.gid; 228 pmp->pm_uid = args.uid; 229 pmp->pm_mask = args.mask; 230 (void) msdosfs_statfs(mp, &mp->mnt_stat, p); 231#ifdef MSDOSFS_DEBUG 232 printf("msdosfs_mount(): mp %x, pmp %x, inusemap %x\n", mp, pmp, pmp->pm_inusemap); 233#endif 234 return 0; 235} 236 237int 238mountmsdosfs(devvp, mp, p) 239 struct vnode *devvp; 240 struct mount *mp; 241 struct proc *p; 242{ 243 int i; 244 int bpc; 245 int bit; 246 int error; 247 int needclose; 248 int ronly = (mp->mnt_flag & MNT_RDONLY) != 0; 249 dev_t dev = devvp->v_rdev; 250 union bootsector *bsp; 251 struct msdosfsmount *pmp = NULL; 252 struct buf *bp0 = NULL; 253 struct byte_bpb33 *b33; 254 struct byte_bpb50 *b50; 255 256 /* 257 * Multiple mounts of the same block special file aren't allowed. 258 * Make sure no one else has the special file open. And flush any 259 * old buffers from this filesystem. Presumably this prevents us 260 * from running into buffers that are the wrong blocksize. 261 */ 262 if (error = vfs_mountedon(devvp)) 263 return error; 264 if (vcount(devvp) > 1) 265 return EBUSY; 266 if (error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) 267 return error; 268 269 /* 270 * Now open the block special file. 271 */ 272 if (error = VOP_OPEN(devvp, ronly ? FREAD : FREAD | FWRITE, FSCRED, p)) 273 return error; 274 needclose = 1; 275#ifdef HDSUPPORT 276 /* 277 * Put this in when we support reading dos filesystems from 278 * partitioned harddisks. 279 */ 280 if (VOP_IOCTL(devvp, DIOCGPART, &msdosfspart, FREAD, NOCRED, p) == 0) { 281 } 282#endif 283 284 /* 285 * Read the boot sector of the filesystem, and then check the boot 286 * signature. If not a dos boot sector then error out. We could 287 * also add some checking on the bsOemName field. So far I've seen 288 * the following values: "IBM 3.3" "MSDOS3.3" "MSDOS5.0" 289 */ 290 if (error = bread(devvp, 0, 512, NOCRED, &bp0)) 291 goto error_exit; 292 bp0->b_flags |= B_AGE; 293 bsp = (union bootsector *) bp0->b_data; 294 b33 = (struct byte_bpb33 *) bsp->bs33.bsBPB; 295 b50 = (struct byte_bpb50 *) bsp->bs50.bsBPB; 296#ifdef MSDOSFS_CHECKSIG 297 if (bsp->bs50.bsBootSectSig != BOOTSIG) { 298 error = EINVAL; 299 goto error_exit; 300 } 301#endif 302 if ( bsp->bs50.bsJump[0] != 0xe9 && 303 (bsp->bs50.bsJump[0] != 0xeb || bsp->bs50.bsJump[2] != 0x90)) { 304 error = EINVAL; 305 goto error_exit; 306 } 307 308 pmp = malloc(sizeof *pmp, M_MSDOSFSMNT, M_WAITOK); 309 bzero((caddr_t)pmp, sizeof *pmp); 310 pmp->pm_mountp = mp; 311 312 /* 313 * Compute several useful quantities from the bpb in the 314 * bootsector. Copy in the dos 5 variant of the bpb then fix up 315 * the fields that are different between dos 5 and dos 3.3. 316 */ 317 pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec); 318 pmp->pm_SectPerClust = b50->bpbSecPerClust; 319 pmp->pm_ResSectors = getushort(b50->bpbResSectors); 320 pmp->pm_FATs = b50->bpbFATs; 321 pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts); 322 pmp->pm_Sectors = getushort(b50->bpbSectors); 323 pmp->pm_Media = b50->bpbMedia; 324 pmp->pm_FATsecs = getushort(b50->bpbFATsecs); 325 pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack); 326 pmp->pm_Heads = getushort(b50->bpbHeads); 327 328 /* XXX - We should probably check more values here */ 329 if (!pmp->pm_BytesPerSec || !pmp->pm_SectPerClust || 330 !pmp->pm_Heads || pmp->pm_Heads > 255 || 331 !pmp->pm_SecPerTrack || pmp->pm_SecPerTrack > 63) { 332 error = EINVAL; 333 goto error_exit; 334 } 335 336 if (pmp->pm_Sectors == 0) { 337 pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs); 338 pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors); 339 } else { 340 pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs); 341 pmp->pm_HugeSectors = pmp->pm_Sectors; 342 } 343 pmp->pm_fatblk = pmp->pm_ResSectors; 344 pmp->pm_rootdirblk = pmp->pm_fatblk + 345 (pmp->pm_FATs * pmp->pm_FATsecs); 346 pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry)) 347 / 348 pmp->pm_BytesPerSec;/* in sectors */ 349 pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize; 350 pmp->pm_nmbrofclusters = (pmp->pm_HugeSectors - pmp->pm_firstcluster) / 351 pmp->pm_SectPerClust; 352 pmp->pm_maxcluster = pmp->pm_nmbrofclusters + 1; 353 pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec; 354 if (FAT12(pmp)) 355 /* 356 * This will usually be a floppy disk. This size makes sure 357 * that one fat entry will not be split across multiple 358 * blocks. 359 */ 360 pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec; 361 else 362 /* 363 * This will usually be a hard disk. Reading or writing one 364 * block should be quite fast. 365 */ 366 pmp->pm_fatblocksize = MAXBSIZE; 367 pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec; 368 369 370 if ((pmp->pm_rootdirsize % pmp->pm_SectPerClust) != 0) 371 printf("mountmsdosfs(): root directory is not a multiple of the clustersize in length\n"); 372 373 /* 374 * Compute mask and shift value for isolating cluster relative byte 375 * offsets and cluster numbers from a file offset. 376 */ 377 bpc = pmp->pm_SectPerClust * pmp->pm_BytesPerSec; 378 pmp->pm_bpcluster = bpc; 379 pmp->pm_depclust = bpc / sizeof(struct direntry); 380 pmp->pm_crbomask = bpc - 1; 381 if (bpc == 0) { 382 error = EINVAL; 383 goto error_exit; 384 } 385 bit = 1; 386 for (i = 0; i < 32; i++) { 387 if (bit & bpc) { 388 if (bit ^ bpc) { 389 error = EINVAL; 390 goto error_exit; 391 } 392 pmp->pm_cnshift = i; 393 break; 394 } 395 bit <<= 1; 396 } 397 398 pmp->pm_brbomask = 0x01ff; /* 512 byte blocks only (so far) */ 399 pmp->pm_bnshift = 9; /* shift right 9 bits to get bn */ 400 401 /* 402 * Release the bootsector buffer. 403 */ 404 brelse(bp0); 405 bp0 = NULL; 406 407 /* 408 * Allocate memory for the bitmap of allocated clusters, and then 409 * fill it in. 410 */ 411 pmp->pm_inusemap = malloc(((pmp->pm_maxcluster + N_INUSEBITS - 1) 412 / N_INUSEBITS) 413 * sizeof(*pmp->pm_inusemap), 414 M_MSDOSFSFAT, M_WAITOK); 415 416 /* 417 * fillinusemap() needs pm_devvp. 418 */ 419 pmp->pm_dev = dev; 420 pmp->pm_devvp = devvp; 421 422 /* 423 * Have the inuse map filled in. 424 */ 425 error = fillinusemap(pmp); 426 if (error) 427 goto error_exit; 428 429 /* 430 * If they want fat updates to be synchronous then let them suffer 431 * the performance degradation in exchange for the on disk copy of 432 * the fat being correct just about all the time. I suppose this 433 * would be a good thing to turn on if the kernel is still flakey. 434 */ 435 pmp->pm_waitonfat = mp->mnt_flag & MNT_SYNCHRONOUS; 436 437 /* 438 * Finish up. 439 */ 440 pmp->pm_ronly = ronly; 441 if (ronly == 0) 442 pmp->pm_fmod = 1; 443 mp->mnt_data = (qaddr_t) pmp; 444 mp->mnt_stat.f_fsid.val[0] = (long)dev; 445 mp->mnt_stat.f_fsid.val[1] = MOUNT_MSDOS; 446 mp->mnt_flag |= MNT_LOCAL; 447#ifdef QUOTA 448 /* 449 * If we ever do quotas for DOS filesystems this would be a place 450 * to fill in the info in the msdosfsmount structure. You dolt, 451 * quotas on dos filesystems make no sense because files have no 452 * owners on dos filesystems. of course there is some empty space 453 * in the directory entry where we could put uid's and gid's. 454 */ 455#endif 456 devvp->v_specflags |= SI_MOUNTEDON; 457 458 return 0; 459 460error_exit:; 461 if (bp0) 462 brelse(bp0); 463 if (needclose) 464 (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD | FWRITE, 465 NOCRED, p); 466 if (pmp) { 467 if (pmp->pm_inusemap) 468 free((caddr_t) pmp->pm_inusemap, M_MSDOSFSFAT); 469 free((caddr_t) pmp, M_MSDOSFSMNT); 470 mp->mnt_data = (qaddr_t) 0; 471 } 472 return error; 473} 474 475int 476msdosfs_start(mp, flags, p) 477 struct mount *mp; 478 int flags; 479 struct proc *p; 480{ 481 return 0; 482} 483 484/* 485 * Unmount the filesystem described by mp. 486 */ 487int 488msdosfs_unmount(mp, mntflags, p) 489 struct mount *mp; 490 int mntflags; 491 struct proc *p; 492{ 493 int flags = 0; 494 int error; 495 struct msdosfsmount *pmp = (struct msdosfsmount *) mp->mnt_data; 496 struct vnode *vp = pmp->pm_devvp; 497 498 /* only the mounter, or superuser can unmount */ 499 if ((p->p_cred->p_ruid != pmp->pm_mounter) && 500 (error = suser(p->p_ucred, &p->p_acflag))) 501 return error; 502 503 if (mntflags & MNT_FORCE) { 504 if (!msdosfsdoforce) 505 return EINVAL; 506 flags |= FORCECLOSE; 507 } 508#ifdef QUOTA 509#endif 510 if (error = vflush(mp, NULLVP, flags)) 511 return error; 512 pmp->pm_devvp->v_specflags &= ~SI_MOUNTEDON; 513#ifdef MSDOSFS_DEBUG 514 printf("msdosfs_umount(): just before calling VOP_CLOSE()\n"); 515 printf("flag %08x, usecount %d, writecount %d, holdcnt %d\n", 516 vp->v_flag, vp->v_usecount, vp->v_writecount, vp->v_holdcnt); 517 printf("lastr %d, id %d, mount %08x, op %08x\n", 518 vp->v_lastr, vp->v_id, vp->v_mount, vp->v_op); 519 printf("freef %08x, freeb %08x, mountf %08x, mountb %08x\n", 520 vp->v_freef, vp->v_freeb, vp->v_mountf, vp->v_mountb); 521 printf("cleanblkhd %08x, dirtyblkhd %08x, numoutput %d, type %d\n", 522 vp->v_cleanblkhd, vp->v_dirtyblkhd, vp->v_numoutput, vp->v_type); 523 printf("union %08x, tag %d, data[0] %08x, data[1] %08x\n", 524 vp->v_socket, vp->v_tag, vp->v_data[0], vp->v_data[1]); 525#endif 526 error = VOP_CLOSE(pmp->pm_devvp, pmp->pm_ronly ? FREAD : FREAD | FWRITE, 527 NOCRED, p); 528 vrele(pmp->pm_devvp); 529 free((caddr_t) pmp->pm_inusemap, M_MSDOSFSFAT); 530 free((caddr_t) pmp, M_MSDOSFSMNT); 531 mp->mnt_data = (qaddr_t) 0; 532 mp->mnt_flag &= ~MNT_LOCAL; 533 return error; 534} 535 536int 537msdosfs_root(mp, vpp) 538 struct mount *mp; 539 struct vnode **vpp; 540{ 541 struct denode *ndep; 542 struct msdosfsmount *pmp = (struct msdosfsmount *) (mp->mnt_data); 543 int error; 544 545 error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, NULL, &ndep); 546#ifdef MSDOSFS_DEBUG 547 printf("msdosfs_root(); mp %08x, pmp %08x, ndep %08x, vp %08x\n", 548 mp, pmp, ndep, DETOV(ndep)); 549#endif 550 if (error == 0) 551 *vpp = DETOV(ndep); 552 return error; 553} 554 555int 556msdosfs_quotactl(mp, cmds, uid, arg, p) 557 struct mount *mp; 558 int cmds; 559 uid_t uid; 560 caddr_t arg; 561 struct proc *p; 562{ 563#ifdef QUOTA 564#else 565 return EOPNOTSUPP; 566#endif 567} 568 569int 570msdosfs_statfs(mp, sbp, p) 571 struct mount *mp; 572 struct statfs *sbp; 573 struct proc *p; 574{ 575 struct msdosfsmount *pmp = (struct msdosfsmount *) mp->mnt_data; 576 577 /* 578 * Fill in the stat block. 579 */ 580 sbp->f_type = MOUNT_MSDOS; 581 sbp->f_bsize = pmp->pm_bpcluster; 582 sbp->f_iosize = pmp->pm_bpcluster; 583 sbp->f_blocks = pmp->pm_nmbrofclusters; 584 sbp->f_bfree = pmp->pm_freeclustercount; 585 sbp->f_bavail = pmp->pm_freeclustercount; 586 sbp->f_files = pmp->pm_RootDirEnts; /* XXX */ 587 sbp->f_ffree = 0; /* what to put in here? */ 588 589 /* 590 * Copy the mounted on and mounted from names into the passed in 591 * stat block, if it is not the one in the mount structure. 592 */ 593 if (sbp != &mp->mnt_stat) { 594 bcopy((caddr_t) mp->mnt_stat.f_mntonname, 595 (caddr_t) & sbp->f_mntonname[0], MNAMELEN); 596 bcopy((caddr_t) mp->mnt_stat.f_mntfromname, 597 (caddr_t) & sbp->f_mntfromname[0], MNAMELEN); 598 } 599#if 0 600 strncpy(&sbp->f_fstypename[0], mp->mnt_op->vfs_name, MFSNAMELEN); 601 sbp->f_fstypename[MFSNAMELEN] = '\0'; 602#endif 603 return 0; 604} 605 606int 607msdosfs_sync(mp, waitfor, cred, p) 608 struct mount *mp; 609 int waitfor; 610 struct ucred *cred; 611 struct proc *p; 612{ 613 struct vnode *vp; 614 struct denode *dep; 615 struct msdosfsmount *pmp; 616 int error; 617 int allerror = 0; 618 619 pmp = (struct msdosfsmount *) mp->mnt_data; 620 621 /* 622 * If we ever switch to not updating all of the fats all the time, 623 * this would be the place to update them from the first one. 624 */ 625 if (pmp->pm_fmod) 626 if (pmp->pm_ronly) 627 panic("msdosfs_sync: rofs mod"); 628 else { 629 /* update fats here */ 630 } 631 632 /* 633 * Go thru in memory denodes and write them out along with 634 * unwritten file blocks. 635 */ 636loop: 637 for (vp = mp->mnt_vnodelist.lh_first; vp; 638 vp = vp->v_mntvnodes.le_next) { 639 if (vp->v_mount != mp) /* not ours anymore */ 640 goto loop; 641 if (VOP_ISLOCKED(vp)) /* file is busy */ 642 continue; 643 dep = VTODE(vp); 644 if ((dep->de_flag & DE_UPDATE) == 0 && 645 vp->v_dirtyblkhd.lh_first == NULL) 646 continue; 647 if (vget(vp, 1)) /* not there anymore? */ 648 goto loop; 649 if (error = VOP_FSYNC(vp, cred, waitfor, p)) 650 allerror = error; 651 vput(vp); /* done with this one */ 652 } 653 654 /* 655 * Flush filesystem control info. 656 */ 657 if (error = VOP_FSYNC(pmp->pm_devvp, cred, waitfor, p)) 658 allerror = error; 659 return allerror; 660} 661 662int 663msdosfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) 664 struct mount *mp; 665 struct fid *fhp; 666 struct mbuf *nam; 667 struct vnode **vpp; 668 int *exflagsp; 669 struct ucred **credanonp; 670{ 671 struct msdosfsmount *pmp = (struct msdosfsmount *) mp->mnt_data; 672 struct defid *defhp = (struct defid *) fhp; 673 struct denode *dep; 674 struct netcred *np; 675 int error; 676 677 np = vfs_export_lookup(mp, &pmp->pm_export, nam); 678 if (np == NULL) 679 return EACCES; 680 error = deget(pmp, defhp->defid_dirclust, defhp->defid_dirofs, 681 NULL, &dep); 682 if (error) { 683 *vpp = NULLVP; 684 return error; 685 } 686 *vpp = DETOV(dep); 687 *exflagsp = np->netc_exflags; 688 *credanonp = &np->netc_anon; 689 return 0; 690} 691 692 693int 694msdosfs_vptofh(vp, fhp) 695 struct vnode *vp; 696 struct fid *fhp; 697{ 698 struct denode *dep = VTODE(vp); 699 struct defid *defhp = (struct defid *) fhp; 700 701 defhp->defid_len = sizeof(struct defid); 702 defhp->defid_dirclust = dep->de_dirclust; 703 defhp->defid_dirofs = dep->de_diroffset; 704 /* defhp->defid_gen = ip->i_gen; */ 705 return 0; 706} 707 708int 709msdosfs_vget(mp, ino, vpp) 710 struct mount *mp; 711 ino_t ino; 712 struct vnode **vpp; 713{ 714 return EOPNOTSUPP; 715} 716 717struct vfsops msdosfs_vfsops = { 718 msdosfs_mount, 719 msdosfs_start, 720 msdosfs_unmount, 721 msdosfs_root, 722 msdosfs_quotactl, 723 msdosfs_statfs, 724 msdosfs_sync, 725 msdosfs_vget, 726 msdosfs_fhtovp, 727 msdosfs_vptofh, 728 msdosfs_init 729}; 730 731VFS_SET(msdosfs_vfsops, msdos, MOUNT_MSDOS, 0); 732