1237d1b14SEd Maste /*- 22037e988SEd Maste * SPDX-License-Identifier: BSD-4-Clause 32037e988SEd Maste * 4237d1b14SEd Maste * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. 5237d1b14SEd Maste * Copyright (C) 1994, 1995, 1997 TooLs GmbH. 6237d1b14SEd Maste * All rights reserved. 7237d1b14SEd Maste * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below). 8237d1b14SEd Maste * 9237d1b14SEd Maste * Redistribution and use in source and binary forms, with or without 10237d1b14SEd Maste * modification, are permitted provided that the following conditions 11237d1b14SEd Maste * are met: 12237d1b14SEd Maste * 1. Redistributions of source code must retain the above copyright 13237d1b14SEd Maste * notice, this list of conditions and the following disclaimer. 14237d1b14SEd Maste * 2. Redistributions in binary form must reproduce the above copyright 15237d1b14SEd Maste * notice, this list of conditions and the following disclaimer in the 16237d1b14SEd Maste * documentation and/or other materials provided with the distribution. 17237d1b14SEd Maste * 3. All advertising materials mentioning features or use of this software 18237d1b14SEd Maste * must display the following acknowledgement: 19237d1b14SEd Maste * This product includes software developed by TooLs GmbH. 20237d1b14SEd Maste * 4. The name of TooLs GmbH may not be used to endorse or promote products 21237d1b14SEd Maste * derived from this software without specific prior written permission. 22237d1b14SEd Maste * 23237d1b14SEd Maste * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 24237d1b14SEd Maste * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25237d1b14SEd Maste * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26237d1b14SEd Maste * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27237d1b14SEd Maste * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28237d1b14SEd Maste * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 29237d1b14SEd Maste * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30237d1b14SEd Maste * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 31237d1b14SEd Maste * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 32237d1b14SEd Maste * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33237d1b14SEd Maste */ 342037e988SEd Maste /*- 35237d1b14SEd Maste * Written by Paul Popelka (paulp@uts.amdahl.com) 36237d1b14SEd Maste * 37237d1b14SEd Maste * You can do anything you want with this software, just don't say you wrote 38237d1b14SEd Maste * it, and don't remove this notice. 39237d1b14SEd Maste * 40237d1b14SEd Maste * This software is provided "as is". 41237d1b14SEd Maste * 42237d1b14SEd Maste * The author supplies this software to be publicly redistributed on the 43237d1b14SEd Maste * understanding that the author is not responsible for the correct 44237d1b14SEd Maste * functioning of this software in any circumstances and is not liable for 45237d1b14SEd Maste * any damages caused by this software. 46237d1b14SEd Maste * 47237d1b14SEd Maste * October 1992 48237d1b14SEd Maste */ 49237d1b14SEd Maste 50237d1b14SEd Maste #include <sys/cdefs.h> 51237d1b14SEd Maste /* $NetBSD: msdosfs_vfsops.c,v 1.10 2016/01/30 09:59:27 mlelstv Exp $ */ 52237d1b14SEd Maste __FBSDID("$FreeBSD$"); 53237d1b14SEd Maste 54237d1b14SEd Maste #include <sys/param.h> 5598dc8da5SEd Maste #include <sys/mount.h> 56237d1b14SEd Maste 57237d1b14SEd Maste #include <errno.h> 58aaa38524SConrad Meyer #include <stdbool.h> 5998dc8da5SEd Maste #include <stdio.h> 60237d1b14SEd Maste #include <string.h> 6198dc8da5SEd Maste #include <stdlib.h> 62237d1b14SEd Maste #include <util.h> 63237d1b14SEd Maste 6498dc8da5SEd Maste #include <fs/msdosfs/bootsect.h> 6598dc8da5SEd Maste #include <fs/msdosfs/bpb.h> 66ba2cfa80SAlex Richardson #include "msdos/denode.h" 6751e79affSEd Maste #include <fs/msdosfs/fat.h> 68840aca28SEd Maste #include <fs/msdosfs/msdosfsmount.h> 6998dc8da5SEd Maste 7098dc8da5SEd Maste #include <mkfs_msdos.h> 7198dc8da5SEd Maste 72237d1b14SEd Maste #include "makefs.h" 73237d1b14SEd Maste #include "msdos.h" 74237d1b14SEd Maste 75237d1b14SEd Maste struct msdosfsmount * 76d485c77fSKonstantin Belousov m_msdosfs_mount(struct m_vnode *devvp) 77237d1b14SEd Maste { 78237d1b14SEd Maste struct msdosfsmount *pmp = NULL; 79d485c77fSKonstantin Belousov struct m_buf *bp; 80237d1b14SEd Maste union bootsector *bsp; 81237d1b14SEd Maste struct byte_bpb33 *b33; 82237d1b14SEd Maste struct byte_bpb50 *b50; 83237d1b14SEd Maste struct byte_bpb710 *b710; 84237d1b14SEd Maste uint8_t SecPerClust; 8598dc8da5SEd Maste int ronly = 0, error; 86237d1b14SEd Maste int bsize; 87237d1b14SEd Maste unsigned secsize = 512; 88237d1b14SEd Maste 8998dc8da5SEd Maste MSDOSFS_DPRINTF(("%s(bread 0)\n", __func__)); 90d485c77fSKonstantin Belousov if ((error = bread((void *)devvp, 0, secsize, 0, &bp)) != 0) 91237d1b14SEd Maste goto error_exit; 92237d1b14SEd Maste 93237d1b14SEd Maste bsp = (union bootsector *)bp->b_data; 94237d1b14SEd Maste b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB; 95237d1b14SEd Maste b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB; 96237d1b14SEd Maste b710 = (struct byte_bpb710 *)bsp->bs710.bsBPB; 97237d1b14SEd Maste 9898dc8da5SEd Maste if (bsp->bs50.bsBootSectSig0 != BOOTSIG0 || 9998dc8da5SEd Maste bsp->bs50.bsBootSectSig1 != BOOTSIG1) { 10098dc8da5SEd Maste MSDOSFS_DPRINTF(("bootsig0 %d bootsig1 %d\n", 101237d1b14SEd Maste bsp->bs50.bsBootSectSig0, 102237d1b14SEd Maste bsp->bs50.bsBootSectSig1)); 103237d1b14SEd Maste error = EINVAL; 104237d1b14SEd Maste goto error_exit; 105237d1b14SEd Maste } 106237d1b14SEd Maste bsize = 0; 107237d1b14SEd Maste 10898dc8da5SEd Maste pmp = ecalloc(1, sizeof(*pmp)); 109237d1b14SEd Maste /* 110237d1b14SEd Maste * Compute several useful quantities from the bpb in the 111237d1b14SEd Maste * bootsector. Copy in the dos 5 variant of the bpb then fix up 112237d1b14SEd Maste * the fields that are different between dos 5 and dos 3.3. 113237d1b14SEd Maste */ 114237d1b14SEd Maste SecPerClust = b50->bpbSecPerClust; 115237d1b14SEd Maste pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec); 116237d1b14SEd Maste pmp->pm_ResSectors = getushort(b50->bpbResSectors); 117237d1b14SEd Maste pmp->pm_FATs = b50->bpbFATs; 118237d1b14SEd Maste pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts); 119237d1b14SEd Maste pmp->pm_Sectors = getushort(b50->bpbSectors); 120237d1b14SEd Maste pmp->pm_FATsecs = getushort(b50->bpbFATsecs); 121237d1b14SEd Maste pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack); 122237d1b14SEd Maste pmp->pm_Heads = getushort(b50->bpbHeads); 123237d1b14SEd Maste pmp->pm_Media = b50->bpbMedia; 124237d1b14SEd Maste 12598dc8da5SEd Maste MSDOSFS_DPRINTF(("%s(BytesPerSec=%u, ResSectors=%u, FATs=%d, " 12698dc8da5SEd Maste "RootDirEnts=%u, Sectors=%u, FATsecs=%lu, SecPerTrack=%u, " 12798dc8da5SEd Maste "Heads=%u, Media=%u)\n", 12898dc8da5SEd Maste __func__, pmp->pm_BytesPerSec, pmp->pm_ResSectors, 12998dc8da5SEd Maste pmp->pm_FATs, pmp->pm_RootDirEnts, pmp->pm_Sectors, 13098dc8da5SEd Maste pmp->pm_FATsecs, pmp->pm_SecPerTrack, pmp->pm_Heads, 13198dc8da5SEd Maste pmp->pm_Media)); 13298dc8da5SEd Maste 133237d1b14SEd Maste /* XXX - We should probably check more values here */ 134237d1b14SEd Maste if (!pmp->pm_BytesPerSec || !SecPerClust 135237d1b14SEd Maste || pmp->pm_SecPerTrack > 63) { 13698dc8da5SEd Maste MSDOSFS_DPRINTF(("bytespersec %d secperclust %d " 13798dc8da5SEd Maste "secpertrack %d\n", pmp->pm_BytesPerSec, 13898dc8da5SEd Maste SecPerClust, pmp->pm_SecPerTrack)); 139237d1b14SEd Maste error = EINVAL; 140237d1b14SEd Maste goto error_exit; 141237d1b14SEd Maste } 142237d1b14SEd Maste 143237d1b14SEd Maste if (pmp->pm_Sectors == 0) { 144237d1b14SEd Maste pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs); 145237d1b14SEd Maste pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors); 146237d1b14SEd Maste } else { 147237d1b14SEd Maste pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs); 148237d1b14SEd Maste pmp->pm_HugeSectors = pmp->pm_Sectors; 149237d1b14SEd Maste } 150237d1b14SEd Maste 15198dc8da5SEd Maste pmp->pm_flags = 0; 152237d1b14SEd Maste if (pmp->pm_RootDirEnts == 0) { 153237d1b14SEd Maste unsigned short vers = getushort(b710->bpbFSVers); 154237d1b14SEd Maste /* 155237d1b14SEd Maste * Some say that bsBootSectSig[23] must be zero, but 156237d1b14SEd Maste * Windows does not require this and some digital cameras 157237d1b14SEd Maste * do not set these to zero. Therefore, do not insist. 158237d1b14SEd Maste */ 159237d1b14SEd Maste if (pmp->pm_Sectors || pmp->pm_FATsecs || vers) { 16098dc8da5SEd Maste MSDOSFS_DPRINTF(("sectors %d fatsecs %lu vers %d\n", 161237d1b14SEd Maste pmp->pm_Sectors, pmp->pm_FATsecs, vers)); 162237d1b14SEd Maste error = EINVAL; 163237d1b14SEd Maste goto error_exit; 164237d1b14SEd Maste } 165237d1b14SEd Maste pmp->pm_fatmask = FAT32_MASK; 166237d1b14SEd Maste pmp->pm_fatmult = 4; 167237d1b14SEd Maste pmp->pm_fatdiv = 1; 168237d1b14SEd Maste pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs); 169237d1b14SEd Maste 170237d1b14SEd Maste /* mirrorring is enabled if the FATMIRROR bit is not set */ 171237d1b14SEd Maste if ((getushort(b710->bpbExtFlags) & FATMIRROR) == 0) 172237d1b14SEd Maste pmp->pm_flags |= MSDOSFS_FATMIRROR; 173237d1b14SEd Maste else 174237d1b14SEd Maste pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM; 175237d1b14SEd Maste } else 176237d1b14SEd Maste pmp->pm_flags |= MSDOSFS_FATMIRROR; 177237d1b14SEd Maste 178237d1b14SEd Maste /* Check that fs has nonzero FAT size */ 179237d1b14SEd Maste if (pmp->pm_FATsecs == 0) { 18098dc8da5SEd Maste MSDOSFS_DPRINTF(("FATsecs is 0\n")); 181237d1b14SEd Maste error = EINVAL; 182237d1b14SEd Maste goto error_exit; 183237d1b14SEd Maste } 184237d1b14SEd Maste 185237d1b14SEd Maste pmp->pm_fatblk = pmp->pm_ResSectors; 186237d1b14SEd Maste if (FAT32(pmp)) { 187237d1b14SEd Maste pmp->pm_rootdirblk = getulong(b710->bpbRootClust); 188237d1b14SEd Maste pmp->pm_firstcluster = pmp->pm_fatblk 189237d1b14SEd Maste + (pmp->pm_FATs * pmp->pm_FATsecs); 190237d1b14SEd Maste pmp->pm_fsinfo = getushort(b710->bpbFSInfo); 191237d1b14SEd Maste } else { 192237d1b14SEd Maste pmp->pm_rootdirblk = pmp->pm_fatblk + 193237d1b14SEd Maste (pmp->pm_FATs * pmp->pm_FATsecs); 194237d1b14SEd Maste pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry) 195237d1b14SEd Maste + pmp->pm_BytesPerSec - 1) 196237d1b14SEd Maste / pmp->pm_BytesPerSec;/* in sectors */ 197237d1b14SEd Maste pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize; 198237d1b14SEd Maste } 199237d1b14SEd Maste 20098dc8da5SEd Maste pmp->pm_maxcluster = ((pmp->pm_HugeSectors - pmp->pm_firstcluster) / 20198dc8da5SEd Maste SecPerClust) + 1; 202237d1b14SEd Maste pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec; 203237d1b14SEd Maste 20498dc8da5SEd Maste if (pmp->pm_fatmask == 0) { 205237d1b14SEd Maste if (pmp->pm_maxcluster 206237d1b14SEd Maste <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) { 207237d1b14SEd Maste /* 208237d1b14SEd Maste * This will usually be a floppy disk. This size makes 209237d1b14SEd Maste * sure that one FAT entry will not be split across 210237d1b14SEd Maste * multiple blocks. 211237d1b14SEd Maste */ 212237d1b14SEd Maste pmp->pm_fatmask = FAT12_MASK; 213237d1b14SEd Maste pmp->pm_fatmult = 3; 214237d1b14SEd Maste pmp->pm_fatdiv = 2; 215237d1b14SEd Maste } else { 216237d1b14SEd Maste pmp->pm_fatmask = FAT16_MASK; 217237d1b14SEd Maste pmp->pm_fatmult = 2; 218237d1b14SEd Maste pmp->pm_fatdiv = 1; 219237d1b14SEd Maste } 220237d1b14SEd Maste } 221237d1b14SEd Maste if (FAT12(pmp)) 222237d1b14SEd Maste pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec; 223237d1b14SEd Maste else 224237d1b14SEd Maste pmp->pm_fatblocksize = MAXBSIZE; 225237d1b14SEd Maste 226237d1b14SEd Maste pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec; 227237d1b14SEd Maste pmp->pm_bnshift = ffs(pmp->pm_BytesPerSec) - 1; 228237d1b14SEd Maste 229237d1b14SEd Maste /* 230237d1b14SEd Maste * Compute mask and shift value for isolating cluster relative byte 231237d1b14SEd Maste * offsets and cluster numbers from a file offset. 232237d1b14SEd Maste */ 233237d1b14SEd Maste pmp->pm_bpcluster = SecPerClust * pmp->pm_BytesPerSec; 234237d1b14SEd Maste pmp->pm_crbomask = pmp->pm_bpcluster - 1; 235237d1b14SEd Maste pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1; 236237d1b14SEd Maste 23798dc8da5SEd Maste MSDOSFS_DPRINTF(("%s(fatmask=%lu, fatmult=%u, fatdiv=%u, " 23898dc8da5SEd Maste "fatblocksize=%lu, fatblocksec=%lu, bnshift=%lu, pbcluster=%lu, " 23998dc8da5SEd Maste "crbomask=%lu, cnshift=%lu)\n", 24098dc8da5SEd Maste __func__, (unsigned long)pmp->pm_fatmask, pmp->pm_fatmult, 24198dc8da5SEd Maste pmp->pm_fatdiv, pmp->pm_fatblocksize, pmp->pm_fatblocksec, 24298dc8da5SEd Maste pmp->pm_bnshift, pmp->pm_bpcluster, pmp->pm_crbomask, 24398dc8da5SEd Maste pmp->pm_cnshift)); 244237d1b14SEd Maste /* 245237d1b14SEd Maste * Check for valid cluster size 246237d1b14SEd Maste * must be a power of 2 247237d1b14SEd Maste */ 248237d1b14SEd Maste if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) { 24998dc8da5SEd Maste MSDOSFS_DPRINTF(("bpcluster %lu cnshift %lu\n", 250237d1b14SEd Maste pmp->pm_bpcluster, pmp->pm_cnshift)); 251237d1b14SEd Maste error = EINVAL; 252237d1b14SEd Maste goto error_exit; 253237d1b14SEd Maste } 254237d1b14SEd Maste 255237d1b14SEd Maste /* 256237d1b14SEd Maste * Release the bootsector buffer. 257237d1b14SEd Maste */ 2585b292f9aSEd Maste brelse(bp); 259237d1b14SEd Maste bp = NULL; 260237d1b14SEd Maste 261237d1b14SEd Maste /* 262237d1b14SEd Maste * Check FSInfo. 263237d1b14SEd Maste */ 264237d1b14SEd Maste if (pmp->pm_fsinfo) { 265237d1b14SEd Maste struct fsinfo *fp; 266237d1b14SEd Maste 267237d1b14SEd Maste /* 268237d1b14SEd Maste * XXX If the fsinfo block is stored on media with 269237d1b14SEd Maste * 2KB or larger sectors, is the fsinfo structure 270237d1b14SEd Maste * padded at the end or in the middle? 271237d1b14SEd Maste */ 272d485c77fSKonstantin Belousov if ((error = bread((void *)devvp, pmp->pm_fsinfo, 273d485c77fSKonstantin Belousov pmp->pm_BytesPerSec, 0, &bp)) != 0) 274237d1b14SEd Maste goto error_exit; 275237d1b14SEd Maste fp = (struct fsinfo *)bp->b_data; 276237d1b14SEd Maste if (!memcmp(fp->fsisig1, "RRaA", 4) 277237d1b14SEd Maste && !memcmp(fp->fsisig2, "rrAa", 4) 27898dc8da5SEd Maste && !memcmp(fp->fsisig3, "\0\0\125\252", 4)) 279237d1b14SEd Maste pmp->pm_nxtfree = getulong(fp->fsinxtfree); 280237d1b14SEd Maste else 281237d1b14SEd Maste pmp->pm_fsinfo = 0; 2825b292f9aSEd Maste brelse(bp); 283237d1b14SEd Maste bp = NULL; 284237d1b14SEd Maste } 285237d1b14SEd Maste 286237d1b14SEd Maste /* 287237d1b14SEd Maste * Check and validate (or perhaps invalidate?) the fsinfo structure? 288237d1b14SEd Maste * XXX 289237d1b14SEd Maste */ 290237d1b14SEd Maste if (pmp->pm_fsinfo) { 291237d1b14SEd Maste if ((pmp->pm_nxtfree == 0xffffffffUL) || 292237d1b14SEd Maste (pmp->pm_nxtfree > pmp->pm_maxcluster)) 293237d1b14SEd Maste pmp->pm_fsinfo = 0; 294237d1b14SEd Maste } 295237d1b14SEd Maste 296237d1b14SEd Maste /* 297237d1b14SEd Maste * Allocate memory for the bitmap of allocated clusters, and then 298237d1b14SEd Maste * fill it in. 299237d1b14SEd Maste */ 300237d1b14SEd Maste pmp->pm_inusemap = ecalloc(sizeof(*pmp->pm_inusemap), 301237d1b14SEd Maste ((pmp->pm_maxcluster + N_INUSEBITS) / N_INUSEBITS)); 302237d1b14SEd Maste /* 303237d1b14SEd Maste * fillinusemap() needs pm_devvp. 304237d1b14SEd Maste */ 305237d1b14SEd Maste pmp->pm_dev = 0; 306d485c77fSKonstantin Belousov pmp->pm_devvp = (void *)devvp; 307237d1b14SEd Maste 308237d1b14SEd Maste /* 309237d1b14SEd Maste * Have the inuse map filled in. 310237d1b14SEd Maste */ 311237d1b14SEd Maste if ((error = fillinusemap(pmp)) != 0) { 31298dc8da5SEd Maste MSDOSFS_DPRINTF(("fillinusemap %d\n", error)); 313237d1b14SEd Maste goto error_exit; 314237d1b14SEd Maste } 315237d1b14SEd Maste 316237d1b14SEd Maste /* 317237d1b14SEd Maste * Finish up. 318237d1b14SEd Maste */ 319237d1b14SEd Maste if (ronly) 320237d1b14SEd Maste pmp->pm_flags |= MSDOSFSMNT_RONLY; 321237d1b14SEd Maste else 322237d1b14SEd Maste pmp->pm_fmod = 1; 323237d1b14SEd Maste 324237d1b14SEd Maste /* 325237d1b14SEd Maste * If we ever do quotas for DOS filesystems this would be a place 326237d1b14SEd Maste * to fill in the info in the msdosfsmount structure. You dolt, 327237d1b14SEd Maste * quotas on dos filesystems make no sense because files have no 328237d1b14SEd Maste * owners on dos filesystems. of course there is some empty space 329237d1b14SEd Maste * in the directory entry where we could put uid's and gid's. 330237d1b14SEd Maste */ 331237d1b14SEd Maste 332237d1b14SEd Maste return pmp; 333237d1b14SEd Maste 334237d1b14SEd Maste error_exit: 335237d1b14SEd Maste if (bp) 33698dc8da5SEd Maste brelse(bp); 337237d1b14SEd Maste if (pmp) { 338237d1b14SEd Maste if (pmp->pm_inusemap) 339237d1b14SEd Maste free(pmp->pm_inusemap); 340237d1b14SEd Maste free(pmp); 341237d1b14SEd Maste } 342237d1b14SEd Maste errno = error; 343237d1b14SEd Maste return NULL; 344237d1b14SEd Maste } 345237d1b14SEd Maste 346237d1b14SEd Maste int 347d485c77fSKonstantin Belousov msdosfs_root(struct msdosfsmount *pmp, struct m_vnode *vp) { 348237d1b14SEd Maste struct denode *ndep; 349237d1b14SEd Maste int error; 350237d1b14SEd Maste 351d485c77fSKonstantin Belousov *vp = *(struct m_vnode *)pmp->pm_devvp; 352*ae7e8a02SKonstantin Belousov if ((error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, 0, &ndep)) != 0) { 353237d1b14SEd Maste errno = error; 354237d1b14SEd Maste return -1; 355237d1b14SEd Maste } 356237d1b14SEd Maste vp->v_data = ndep; 357237d1b14SEd Maste return 0; 358237d1b14SEd Maste } 3598651679aSXin LI 3608651679aSXin LI /* 3618651679aSXin LI * If we have an FSInfo block, update it. 3628651679aSXin LI */ 3638651679aSXin LI int 3648651679aSXin LI msdosfs_fsiflush(struct msdosfsmount *pmp) 3658651679aSXin LI { 3668651679aSXin LI struct fsinfo *fp; 367d485c77fSKonstantin Belousov struct m_buf *bp; 3688651679aSXin LI int error; 3698651679aSXin LI 3708651679aSXin LI if (pmp->pm_fsinfo == 0 || (pmp->pm_flags & MSDOSFS_FSIMOD) == 0) { 3718651679aSXin LI error = 0; 3728651679aSXin LI goto out; 3738651679aSXin LI } 374d485c77fSKonstantin Belousov error = bread((void *)pmp->pm_devvp, pmp->pm_fsinfo, 375d485c77fSKonstantin Belousov pmp->pm_BytesPerSec, NOCRED, &bp); 3768651679aSXin LI if (error != 0) { 3778651679aSXin LI brelse(bp); 3788651679aSXin LI goto out; 3798651679aSXin LI } 3808651679aSXin LI fp = (struct fsinfo *)bp->b_data; 3818651679aSXin LI putulong(fp->fsinfree, pmp->pm_freeclustercount); 3828651679aSXin LI putulong(fp->fsinxtfree, pmp->pm_nxtfree); 3838651679aSXin LI pmp->pm_flags &= ~MSDOSFS_FSIMOD; 3848651679aSXin LI error = bwrite(bp); 3858651679aSXin LI 3868651679aSXin LI out: 3878651679aSXin LI return (error); 3888651679aSXin LI } 389