[BACK]Return to msdosfs_vfsops.c CVS log [TXT][DIR] Up to [local] / sys / msdosfs

Annotation of sys/msdosfs/msdosfs_vfsops.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: msdosfs_vfsops.c,v 1.47 2007/03/21 17:29:32 thib Exp $        */
        !             2: /*     $NetBSD: msdosfs_vfsops.c,v 1.48 1997/10/18 02:54:57 briggs Exp $       */
        !             3:
        !             4: /*-
        !             5:  * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
        !             6:  * Copyright (C) 1994, 1995, 1997 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/disklabel.h>
        !            62: #include <sys/ioctl.h>
        !            63: #include <sys/malloc.h>
        !            64: #include <sys/dirent.h>
        !            65:
        !            66: #include <msdosfs/bpb.h>
        !            67: #include <msdosfs/bootsect.h>
        !            68: #include <msdosfs/direntry.h>
        !            69: #include <msdosfs/denode.h>
        !            70: #include <msdosfs/msdosfsmount.h>
        !            71: #include <msdosfs/fat.h>
        !            72:
        !            73: int msdosfs_mount(struct mount *, const char *, void *, struct nameidata *,
        !            74:                       struct proc *);
        !            75: int msdosfs_start(struct mount *, int, struct proc *);
        !            76: int msdosfs_unmount(struct mount *, int, struct proc *);
        !            77: int msdosfs_root(struct mount *, struct vnode **);
        !            78: int msdosfs_statfs(struct mount *, struct statfs *, struct proc *);
        !            79: int msdosfs_sync(struct mount *, int, struct ucred *, struct proc *);
        !            80: int msdosfs_fhtovp(struct mount *, struct fid *, struct vnode **);
        !            81: int msdosfs_vptofh(struct vnode *, struct fid *);
        !            82: int msdosfs_check_export(struct mount *mp, struct mbuf *nam,
        !            83:                              int *extflagsp, struct ucred **credanonp);
        !            84:
        !            85: int msdosfs_mountfs(struct vnode *, struct mount *, struct proc *,
        !            86:                         struct msdosfs_args *);
        !            87:
        !            88: int msdosfs_sync_vnode(struct vnode *, void *);
        !            89:
        !            90: /*
        !            91:  * mp - path - addr in user space of mount point (ie /usr or whatever)
        !            92:  * data - addr in user space of mount params including the name of the block
        !            93:  * special file to treat as a filesystem.
        !            94:  */
        !            95: int
        !            96: msdosfs_mount(mp, path, data, ndp, p)
        !            97:        struct mount *mp;
        !            98:        const char *path;
        !            99:        void *data;
        !           100:        struct nameidata *ndp;
        !           101:        struct proc *p;
        !           102: {
        !           103:        struct vnode *devvp;      /* vnode for blk device to mount */
        !           104:        struct msdosfs_args args; /* will hold data from mount request */
        !           105:        /* msdosfs specific mount control block */
        !           106:        struct msdosfsmount *pmp = NULL;
        !           107:        size_t size;
        !           108:        int error, flags;
        !           109:        mode_t accessmode;
        !           110:
        !           111:        error = copyin(data, &args, sizeof(struct msdosfs_args));
        !           112:        if (error)
        !           113:                return (error);
        !           114:        /*
        !           115:         * If updating, check whether changing from read-only to
        !           116:         * read/write; if there is no device name, that's all we do.
        !           117:         */
        !           118:        if (mp->mnt_flag & MNT_UPDATE) {
        !           119:                pmp = VFSTOMSDOSFS(mp);
        !           120:                error = 0;
        !           121:                if (!(pmp->pm_flags & MSDOSFSMNT_RONLY) && (mp->mnt_flag & MNT_RDONLY)) {
        !           122:                        flags = WRITECLOSE;
        !           123:                        if (mp->mnt_flag & MNT_FORCE)
        !           124:                                flags |= FORCECLOSE;
        !           125:                        error = vflush(mp, NULLVP, flags);
        !           126:                }
        !           127:                if (!error && (mp->mnt_flag & MNT_RELOAD))
        !           128:                        /* not yet implemented */
        !           129:                        error = EOPNOTSUPP;
        !           130:                if (error)
        !           131:                        return (error);
        !           132:                if ((pmp->pm_flags & MSDOSFSMNT_RONLY) && (mp->mnt_flag & MNT_WANTRDWR)) {
        !           133:                        /*
        !           134:                         * If upgrade to read-write by non-root, then verify
        !           135:                         * that user has necessary permissions on the device.
        !           136:                         */
        !           137:                        if (p->p_ucred->cr_uid != 0) {
        !           138:                                devvp = pmp->pm_devvp;
        !           139:                                vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
        !           140:                                error = VOP_ACCESS(devvp, VREAD | VWRITE,
        !           141:                                                   p->p_ucred, p);
        !           142:                                if (error) {
        !           143:                                        VOP_UNLOCK(devvp, 0, p);
        !           144:                                        return (error);
        !           145:                                }
        !           146:                                VOP_UNLOCK(devvp, 0, p);
        !           147:                        }
        !           148:                        pmp->pm_flags &= ~MSDOSFSMNT_RONLY;
        !           149:                }
        !           150:                if (args.fspec == 0) {
        !           151: #ifdef __notyet__              /* doesn't work correctly with current mountd   XXX */
        !           152:                        if (args.flags & MSDOSFSMNT_MNTOPT) {
        !           153:                                pmp->pm_flags &= ~MSDOSFSMNT_MNTOPT;
        !           154:                                pmp->pm_flags |= args.flags & MSDOSFSMNT_MNTOPT;
        !           155:                                if (pmp->pm_flags & MSDOSFSMNT_NOWIN95)
        !           156:                                        pmp->pm_flags |= MSDOSFSMNT_SHORTNAME;
        !           157:                        }
        !           158: #endif
        !           159:                        /*
        !           160:                         * Process export requests.
        !           161:                         */
        !           162:                        return (vfs_export(mp, &pmp->pm_export,
        !           163:                            &args.export_info));
        !           164:                }
        !           165:        }
        !           166:        /*
        !           167:         * Not an update, or updating the name: look up the name
        !           168:         * and verify that it refers to a sensible block device.
        !           169:         */
        !           170:        NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
        !           171:        if ((error = namei(ndp)) != 0)
        !           172:                return (error);
        !           173:        devvp = ndp->ni_vp;
        !           174:
        !           175:        if (devvp->v_type != VBLK) {
        !           176:                vrele(devvp);
        !           177:                return (ENOTBLK);
        !           178:        }
        !           179:        if (major(devvp->v_rdev) >= nblkdev) {
        !           180:                vrele(devvp);
        !           181:                return (ENXIO);
        !           182:        }
        !           183:        /*
        !           184:         * If mount by non-root, then verify that user has necessary
        !           185:         * permissions on the device.
        !           186:         */
        !           187:        if (p->p_ucred->cr_uid != 0) {
        !           188:                accessmode = VREAD;
        !           189:                if ((mp->mnt_flag & MNT_RDONLY) == 0)
        !           190:                        accessmode |= VWRITE;
        !           191:                vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
        !           192:                error = VOP_ACCESS(devvp, accessmode, p->p_ucred, p);
        !           193:                if (error) {
        !           194:                        vput(devvp);
        !           195:                        return (error);
        !           196:                }
        !           197:                VOP_UNLOCK(devvp, 0, p);
        !           198:        }
        !           199:        if ((mp->mnt_flag & MNT_UPDATE) == 0)
        !           200:                error = msdosfs_mountfs(devvp, mp, p, &args);
        !           201:        else {
        !           202:                if (devvp != pmp->pm_devvp)
        !           203:                        error = EINVAL; /* XXX needs translation */
        !           204:                else
        !           205:                        vrele(devvp);
        !           206:        }
        !           207:        if (error) {
        !           208:                vrele(devvp);
        !           209:                return (error);
        !           210:        }
        !           211:        pmp = VFSTOMSDOSFS(mp);
        !           212:        pmp->pm_gid = args.gid;
        !           213:        pmp->pm_uid = args.uid;
        !           214:        pmp->pm_mask = args.mask;
        !           215:        pmp->pm_flags |= args.flags & MSDOSFSMNT_MNTOPT;
        !           216:
        !           217:        if (pmp->pm_flags & MSDOSFSMNT_NOWIN95)
        !           218:                pmp->pm_flags |= MSDOSFSMNT_SHORTNAME;
        !           219:        else if (!(pmp->pm_flags & (MSDOSFSMNT_SHORTNAME | MSDOSFSMNT_LONGNAME))) {
        !           220:                struct vnode *rvp;
        !           221:
        !           222:                /*
        !           223:                 * Try to divine whether to support Win'95 long filenames
        !           224:                 */
        !           225:                if (FAT32(pmp))
        !           226:                        pmp->pm_flags |= MSDOSFSMNT_LONGNAME;
        !           227:                else {
        !           228:                        if ((error = msdosfs_root(mp, &rvp)) != 0) {
        !           229:                                msdosfs_unmount(mp, MNT_FORCE, p);
        !           230:                                return (error);
        !           231:                        }
        !           232:                        pmp->pm_flags |= findwin95(VTODE(rvp))
        !           233:                             ? MSDOSFSMNT_LONGNAME
        !           234:                             : MSDOSFSMNT_SHORTNAME;
        !           235:                        vput(rvp);
        !           236:                }
        !           237:        }
        !           238:        (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
        !           239:        bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
        !           240:        (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
        !           241:            &size);
        !           242:        bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
        !           243:        bcopy(&args, &mp->mnt_stat.mount_info.msdosfs_args, sizeof(args));
        !           244: #ifdef MSDOSFS_DEBUG
        !           245:        printf("msdosfs_mount(): mp %x, pmp %x, inusemap %x\n", mp, pmp, pmp->pm_inusemap);
        !           246: #endif
        !           247:        return (0);
        !           248: }
        !           249:
        !           250: int
        !           251: msdosfs_mountfs(devvp, mp, p, argp)
        !           252:        struct vnode *devvp;
        !           253:        struct mount *mp;
        !           254:        struct proc *p;
        !           255:        struct msdosfs_args *argp;
        !           256: {
        !           257:        struct msdosfsmount *pmp;
        !           258:        struct buf *bp;
        !           259:        dev_t dev = devvp->v_rdev;
        !           260:        union bootsector *bsp;
        !           261:        struct byte_bpb33 *b33;
        !           262:        struct byte_bpb50 *b50;
        !           263:        struct byte_bpb710 *b710;
        !           264:        extern struct vnode *rootvp;
        !           265:        u_int8_t SecPerClust;
        !           266:        int     ronly, error, bmapsiz;
        !           267:        uint32_t fat_max_clusters;
        !           268:
        !           269:        /*
        !           270:         * Disallow multiple mounts of the same device.
        !           271:         * Disallow mounting of a device that is currently in use
        !           272:         * (except for root, which might share swap device for miniroot).
        !           273:         * Flush out any old buffers remaining from a previous use.
        !           274:         */
        !           275:        if ((error = vfs_mountedon(devvp)) != 0)
        !           276:                return (error);
        !           277:        if (vcount(devvp) > 1 && devvp != rootvp)
        !           278:                return (EBUSY);
        !           279:        vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
        !           280:        error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
        !           281:        VOP_UNLOCK(devvp, 0, p);
        !           282:        if (error)
        !           283:                return (error);
        !           284:
        !           285:        ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
        !           286:        error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
        !           287:        if (error)
        !           288:                return (error);
        !           289:
        !           290:        bp  = NULL; /* both used in error_exit */
        !           291:        pmp = NULL;
        !           292:
        !           293:        /*
        !           294:         * Read the boot sector of the filesystem, and then check the
        !           295:         * boot signature.  If not a dos boot sector then error out.
        !           296:         */
        !           297:        if ((error = bread(devvp, 0, 2048, NOCRED, &bp)) != 0)
        !           298:                goto error_exit;
        !           299:        bp->b_flags |= B_AGE;
        !           300:        bsp = (union bootsector *)bp->b_data;
        !           301:        b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB;
        !           302:        b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB;
        !           303:        b710 = (struct byte_bpb710 *)bsp->bs710.bsPBP;
        !           304:
        !           305:        pmp = malloc(sizeof *pmp, M_MSDOSFSMNT, M_WAITOK);
        !           306:        bzero((caddr_t)pmp, sizeof *pmp);
        !           307:        pmp->pm_mountp = mp;
        !           308:
        !           309:        /*
        !           310:         * Compute several useful quantities from the bpb in the
        !           311:         * bootsector.  Copy in the dos 5 variant of the bpb then fix up
        !           312:         * the fields that are different between dos 5 and dos 3.3.
        !           313:         */
        !           314:        SecPerClust = b50->bpbSecPerClust;
        !           315:        pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec);
        !           316:        pmp->pm_ResSectors = getushort(b50->bpbResSectors);
        !           317:        pmp->pm_FATs = b50->bpbFATs;
        !           318:        pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts);
        !           319:        pmp->pm_Sectors = getushort(b50->bpbSectors);
        !           320:        pmp->pm_FATsecs = getushort(b50->bpbFATsecs);
        !           321:        pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack);
        !           322:        pmp->pm_Heads = getushort(b50->bpbHeads);
        !           323:        pmp->pm_Media = b50->bpbMedia;
        !           324:
        !           325:        /* Determine the number of DEV_BSIZE blocks in a MSDOSFS sector */
        !           326:        pmp->pm_BlkPerSec = pmp->pm_BytesPerSec / DEV_BSIZE;
        !           327:
        !           328:        if (!pmp->pm_BytesPerSec || !SecPerClust || pmp->pm_SecPerTrack > 63) {
        !           329:                error = EFTYPE;
        !           330:                goto error_exit;
        !           331:        }
        !           332:
        !           333:        if (pmp->pm_Sectors == 0) {
        !           334:                pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs);
        !           335:                pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors);
        !           336:        } else {
        !           337:                pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs);
        !           338:                pmp->pm_HugeSectors = pmp->pm_Sectors;
        !           339:        }
        !           340:
        !           341:        if (pmp->pm_RootDirEnts == 0) {
        !           342:                if (pmp->pm_Sectors || pmp->pm_FATsecs ||
        !           343:                    getushort(b710->bpbFSVers)) {
        !           344:                        error = EINVAL;
        !           345:                        goto error_exit;
        !           346:                }
        !           347:                pmp->pm_fatmask = FAT32_MASK;
        !           348:                pmp->pm_fatmult = 4;
        !           349:                pmp->pm_fatdiv = 1;
        !           350:                pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs);
        !           351:                if (getushort(b710->bpbExtFlags) & FATMIRROR)
        !           352:                        pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM;
        !           353:                else
        !           354:                        pmp->pm_flags |= MSDOSFS_FATMIRROR;
        !           355:        } else
        !           356:                pmp->pm_flags |= MSDOSFS_FATMIRROR;
        !           357:
        !           358:        /*
        !           359:         * More sanity checks:
        !           360:         *      MSDOSFS sectors per cluster: >0 && power of 2
        !           361:         *      MSDOSFS sector size: >= DEV_BSIZE && power of 2
        !           362:         *      HUGE sector count: >0
        !           363:         *      FAT sectors: >0
        !           364:         */
        !           365:        if ((SecPerClust == 0) || (SecPerClust & (SecPerClust - 1)) ||
        !           366:            (pmp->pm_BytesPerSec < DEV_BSIZE) ||
        !           367:            (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1)) ||
        !           368:            (pmp->pm_HugeSectors == 0) || (pmp->pm_FATsecs == 0)) {
        !           369:                error = EINVAL;
        !           370:                goto error_exit;
        !           371:        }
        !           372:
        !           373:        pmp->pm_HugeSectors *= pmp->pm_BlkPerSec;
        !           374:        pmp->pm_HiddenSects *= pmp->pm_BlkPerSec;
        !           375:        pmp->pm_FATsecs *= pmp->pm_BlkPerSec;
        !           376:        pmp->pm_fatblk = pmp->pm_ResSectors * pmp->pm_BlkPerSec;
        !           377:        SecPerClust *= pmp->pm_BlkPerSec;
        !           378:
        !           379:        if (FAT32(pmp)) {
        !           380:                pmp->pm_rootdirblk = getulong(b710->bpbRootClust);
        !           381:                pmp->pm_firstcluster = pmp->pm_fatblk
        !           382:                        + (pmp->pm_FATs * pmp->pm_FATsecs);
        !           383:                pmp->pm_fsinfo = getushort(b710->bpbFSInfo) * pmp->pm_BlkPerSec;
        !           384:        } else {
        !           385:                pmp->pm_rootdirblk = pmp->pm_fatblk +
        !           386:                        (pmp->pm_FATs * pmp->pm_FATsecs);
        !           387:                pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry)
        !           388:                                       + DEV_BSIZE - 1) / DEV_BSIZE;
        !           389:                pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize;
        !           390:        }
        !           391:
        !           392:        pmp->pm_nmbrofclusters = (pmp->pm_HugeSectors - pmp->pm_firstcluster) /
        !           393:            SecPerClust;
        !           394:        pmp->pm_maxcluster = pmp->pm_nmbrofclusters + 1;
        !           395:        pmp->pm_fatsize = pmp->pm_FATsecs * DEV_BSIZE;
        !           396:
        !           397:        if (pmp->pm_fatmask == 0) {
        !           398:                if (pmp->pm_maxcluster
        !           399:                    <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) {
        !           400:                        /*
        !           401:                         * This will usually be a floppy disk. This size makes
        !           402:                         * sure that one fat entry will not be split across
        !           403:                         * multiple blocks.
        !           404:                         */
        !           405:                        pmp->pm_fatmask = FAT12_MASK;
        !           406:                        pmp->pm_fatmult = 3;
        !           407:                        pmp->pm_fatdiv = 2;
        !           408:                } else {
        !           409:                        pmp->pm_fatmask = FAT16_MASK;
        !           410:                        pmp->pm_fatmult = 2;
        !           411:                        pmp->pm_fatdiv = 1;
        !           412:                }
        !           413:        }
        !           414:        if (FAT12(pmp))
        !           415:                pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec;
        !           416:        else
        !           417:                pmp->pm_fatblocksize = MAXBSIZE;
        !           418:
        !           419:        /*
        !           420:         * We now have the number of sectors in each FAT, so can work
        !           421:         * out how many clusters can be represented in a FAT.  Let's
        !           422:         * make sure the file system doesn't claim to have more clusters
        !           423:         * than this.
        !           424:         *
        !           425:         * We perform the calculation like we do to avoid integer overflow.
        !           426:         *
        !           427:         * This will give us a count of clusters.  They are numbered
        !           428:         * from 0, so the max cluster value is one less than the value
        !           429:         * we end up with.
        !           430:         */
        !           431:        fat_max_clusters = pmp->pm_fatsize / pmp->pm_fatmult;
        !           432:        fat_max_clusters *= pmp->pm_fatdiv;
        !           433:        if (pmp->pm_maxcluster >= fat_max_clusters) {
        !           434: #ifndef SMALL_KERNEL
        !           435:                printf("msdosfs: reducing max cluster to %d from %d "
        !           436:                    "due to FAT size\n", fat_max_clusters - 1,
        !           437:                    pmp->pm_maxcluster);
        !           438: #endif
        !           439:                pmp->pm_maxcluster = fat_max_clusters - 1;
        !           440:        }
        !           441:
        !           442:        pmp->pm_fatblocksec = pmp->pm_fatblocksize / DEV_BSIZE;
        !           443:        pmp->pm_bnshift = ffs(DEV_BSIZE) - 1;
        !           444:
        !           445:        /*
        !           446:         * Compute mask and shift value for isolating cluster relative byte
        !           447:         * offsets and cluster numbers from a file offset.
        !           448:         */
        !           449:        pmp->pm_bpcluster = SecPerClust * DEV_BSIZE;
        !           450:        pmp->pm_crbomask = pmp->pm_bpcluster - 1;
        !           451:        pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1;
        !           452:
        !           453:        /*
        !           454:         * Check for valid cluster size
        !           455:         * must be a power of 2
        !           456:         */
        !           457:        if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) {
        !           458:                error = EFTYPE;
        !           459:                goto error_exit;
        !           460:        }
        !           461:
        !           462:        /*
        !           463:         * Release the bootsector buffer.
        !           464:         */
        !           465:        brelse(bp);
        !           466:        bp = NULL;
        !           467:
        !           468:        /*
        !           469:         * Check FSInfo
        !           470:         */
        !           471:        if (pmp->pm_fsinfo) {
        !           472:                struct fsinfo *fp;
        !           473:
        !           474:                if ((error = bread(devvp, pmp->pm_fsinfo, fsi_size(pmp),
        !           475:                    NOCRED, &bp)) != 0)
        !           476:                        goto error_exit;
        !           477:                fp = (struct fsinfo *)bp->b_data;
        !           478:                if (!bcmp(fp->fsisig1, "RRaA", 4)
        !           479:                    && !bcmp(fp->fsisig2, "rrAa", 4)
        !           480:                    && !bcmp(fp->fsisig3, "\0\0\125\252", 4)
        !           481:                    && !bcmp(fp->fsisig4, "\0\0\125\252", 4))
        !           482:                        pmp->pm_nxtfree = getulong(fp->fsinxtfree);
        !           483:                else
        !           484:                        pmp->pm_fsinfo = 0;
        !           485:                brelse(bp);
        !           486:                bp = NULL;
        !           487:        }
        !           488:
        !           489:        /*
        !           490:         * Check and validate (or perhaps invalidate?) the fsinfo structure? XXX
        !           491:         */
        !           492:
        !           493:        /*
        !           494:         * Allocate memory for the bitmap of allocated clusters, and then
        !           495:         * fill it in.
        !           496:         */
        !           497:        bmapsiz = (pmp->pm_maxcluster + N_INUSEBITS - 1) / N_INUSEBITS;
        !           498:        if (bmapsiz == 0 || SIZE_MAX / bmapsiz < sizeof(*pmp->pm_inusemap)) {
        !           499:                /* detect multiplicative integer overflow */
        !           500:                error = EINVAL;
        !           501:                goto error_exit;
        !           502:        }
        !           503:        pmp->pm_inusemap = malloc(bmapsiz * sizeof(*pmp->pm_inusemap),
        !           504:            M_MSDOSFSFAT, M_WAITOK | M_CANFAIL);
        !           505:        if (pmp->pm_inusemap == NULL) {
        !           506:                error = EINVAL;
        !           507:                goto error_exit;
        !           508:        }
        !           509:
        !           510:        /*
        !           511:         * fillinusemap() needs pm_devvp.
        !           512:         */
        !           513:        pmp->pm_dev = dev;
        !           514:        pmp->pm_devvp = devvp;
        !           515:
        !           516:        /*
        !           517:         * Have the inuse map filled in.
        !           518:         */
        !           519:        if ((error = fillinusemap(pmp)) != 0)
        !           520:                goto error_exit;
        !           521:
        !           522:        /*
        !           523:         * If they want fat updates to be synchronous then let them suffer
        !           524:         * the performance degradation in exchange for the on disk copy of
        !           525:         * the fat being correct just about all the time.  I suppose this
        !           526:         * would be a good thing to turn on if the kernel is still flakey.
        !           527:         */
        !           528:        if (mp->mnt_flag & MNT_SYNCHRONOUS)
        !           529:                pmp->pm_flags |= MSDOSFSMNT_WAITONFAT;
        !           530:
        !           531:        /*
        !           532:         * Finish up.
        !           533:         */
        !           534:        if (ronly)
        !           535:                pmp->pm_flags |= MSDOSFSMNT_RONLY;
        !           536:        else
        !           537:                pmp->pm_fmod = 1;
        !           538:        mp->mnt_data = (qaddr_t)pmp;
        !           539:         mp->mnt_stat.f_fsid.val[0] = (long)dev;
        !           540:         mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
        !           541: #ifdef QUOTA
        !           542:        /*
        !           543:         * If we ever do quotas for DOS filesystems this would be a place
        !           544:         * to fill in the info in the msdosfsmount structure. You dolt,
        !           545:         * quotas on dos filesystems make no sense because files have no
        !           546:         * owners on dos filesystems. of course there is some empty space
        !           547:         * in the directory entry where we could put uid's and gid's.
        !           548:         */
        !           549: #endif
        !           550:        devvp->v_specmountpoint = mp;
        !           551:
        !           552:        return (0);
        !           553:
        !           554: error_exit:
        !           555:        devvp->v_specmountpoint = NULL;
        !           556:        if (bp)
        !           557:                brelse(bp);
        !           558:        (void) VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
        !           559:        if (pmp) {
        !           560:                if (pmp->pm_inusemap)
        !           561:                        free(pmp->pm_inusemap, M_MSDOSFSFAT);
        !           562:                free(pmp, M_MSDOSFSMNT);
        !           563:                mp->mnt_data = (qaddr_t)0;
        !           564:        }
        !           565:        return (error);
        !           566: }
        !           567:
        !           568: int
        !           569: msdosfs_start(mp, flags, p)
        !           570:        struct mount *mp;
        !           571:        int flags;
        !           572:        struct proc *p;
        !           573: {
        !           574:
        !           575:        return (0);
        !           576: }
        !           577:
        !           578: /*
        !           579:  * Unmount the filesystem described by mp.
        !           580:  */
        !           581: int
        !           582: msdosfs_unmount(mp, mntflags, p)
        !           583:        struct mount *mp;
        !           584:        int mntflags;
        !           585:        struct proc *p;
        !           586: {
        !           587:        struct msdosfsmount *pmp;
        !           588:        int error, flags;
        !           589:        struct vnode *vp;
        !           590:
        !           591:        flags = 0;
        !           592:        if (mntflags & MNT_FORCE)
        !           593:                flags |= FORCECLOSE;
        !           594: #ifdef QUOTA
        !           595: #endif
        !           596:        if ((error = vflush(mp, NULLVP, flags)) != 0)
        !           597:                return (error);
        !           598:        pmp = VFSTOMSDOSFS(mp);
        !           599:        pmp->pm_devvp->v_specmountpoint = NULL;
        !           600:        vp = pmp->pm_devvp;
        !           601: #ifdef MSDOSFS_DEBUG
        !           602:        vprint("msdosfs_umount(): just before calling VOP_CLOSE()\n", vp);
        !           603: #endif
        !           604:        error = VOP_CLOSE(vp,
        !           605:           pmp->pm_flags & MSDOSFSMNT_RONLY ? FREAD : FREAD|FWRITE, NOCRED, p);
        !           606:        vrele(vp);
        !           607:        free(pmp->pm_inusemap, M_MSDOSFSFAT);
        !           608:        free(pmp, M_MSDOSFSMNT);
        !           609:        mp->mnt_data = (qaddr_t)0;
        !           610:        mp->mnt_flag &= ~MNT_LOCAL;
        !           611:        return (error);
        !           612: }
        !           613:
        !           614: int
        !           615: msdosfs_root(mp, vpp)
        !           616:        struct mount *mp;
        !           617:        struct vnode **vpp;
        !           618: {
        !           619:        struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
        !           620:        struct denode *ndep;
        !           621:        int error;
        !           622:
        !           623:        if ((error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, &ndep)) != 0)
        !           624:                return (error);
        !           625:
        !           626: #ifdef MSDOSFS_DEBUG
        !           627:        printf("msdosfs_root(); mp %08x, pmp %08x, ndep %08x, vp %08x\n",
        !           628:            mp, pmp, ndep, DETOV(ndep));
        !           629: #endif
        !           630:
        !           631:        *vpp = DETOV(ndep);
        !           632:        return (0);
        !           633: }
        !           634:
        !           635: int
        !           636: msdosfs_statfs(mp, sbp, p)
        !           637:        struct mount *mp;
        !           638:        struct statfs *sbp;
        !           639:        struct proc *p;
        !           640: {
        !           641:        struct msdosfsmount *pmp;
        !           642:
        !           643:        pmp = VFSTOMSDOSFS(mp);
        !           644:        sbp->f_bsize = pmp->pm_bpcluster;
        !           645:        sbp->f_iosize = pmp->pm_bpcluster;
        !           646:        sbp->f_blocks = pmp->pm_nmbrofclusters;
        !           647:        sbp->f_bfree = pmp->pm_freeclustercount;
        !           648:        sbp->f_bavail = pmp->pm_freeclustercount;
        !           649:        sbp->f_files = pmp->pm_RootDirEnts;                     /* XXX */
        !           650:        sbp->f_ffree = 0;       /* what to put in here? */
        !           651:        if (sbp != &mp->mnt_stat) {
        !           652:                bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
        !           653:                bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
        !           654:                bcopy(&mp->mnt_stat.mount_info.msdosfs_args,
        !           655:                    &sbp->mount_info.msdosfs_args, sizeof(struct msdosfs_args));
        !           656:        }
        !           657:        strncpy(sbp->f_fstypename, mp->mnt_vfc->vfc_name, MFSNAMELEN);
        !           658:        return (0);
        !           659: }
        !           660:
        !           661:
        !           662: struct msdosfs_sync_arg {
        !           663:        struct proc *p;
        !           664:        struct ucred *cred;
        !           665:        int allerror;
        !           666:        int waitfor;
        !           667: };
        !           668:
        !           669: int
        !           670: msdosfs_sync_vnode(struct vnode *vp, void *arg)
        !           671: {
        !           672:        struct msdosfs_sync_arg *msa = arg;
        !           673:        int error;
        !           674:        struct denode *dep;
        !           675:
        !           676:        dep = VTODE(vp);
        !           677:        if (vp->v_type == VNON ||
        !           678:            ((dep->de_flag & (DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0
        !           679:              && LIST_EMPTY(&vp->v_dirtyblkhd)) ||
        !           680:            msa->waitfor == MNT_LAZY) {
        !           681:                return (0);
        !           682:        }
        !           683:
        !           684:        if (vget(vp, LK_EXCLUSIVE | LK_NOWAIT, msa->p))
        !           685:                return (0);
        !           686:
        !           687:        if ((error = VOP_FSYNC(vp, msa->cred, msa->waitfor, msa->p)) != 0)
        !           688:                msa->allerror = error;
        !           689:        VOP_UNLOCK(vp, 0, msa->p);
        !           690:        vrele(vp);
        !           691:
        !           692:        return (0);
        !           693: }
        !           694:
        !           695:
        !           696: int
        !           697: msdosfs_sync(mp, waitfor, cred, p)
        !           698:        struct mount *mp;
        !           699:        int waitfor;
        !           700:        struct ucred *cred;
        !           701:        struct proc *p;
        !           702: {
        !           703:        struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
        !           704:        struct msdosfs_sync_arg msa;
        !           705:        int error;
        !           706:
        !           707:        msa.allerror = 0;
        !           708:        msa.p = p;
        !           709:        msa.cred = cred;
        !           710:        msa.waitfor = waitfor;
        !           711:
        !           712:        /*
        !           713:         * If we ever switch to not updating all of the fats all the time,
        !           714:         * this would be the place to update them from the first one.
        !           715:         */
        !           716:        if (pmp->pm_fmod != 0) {
        !           717:                if (pmp->pm_flags & MSDOSFSMNT_RONLY)
        !           718:                        panic("msdosfs_sync: rofs mod");
        !           719:                else {
        !           720:                        /* update fats here */
        !           721:                }
        !           722:        }
        !           723:        /*
        !           724:         * Write back each (modified) denode.
        !           725:         */
        !           726:        vfs_mount_foreach_vnode(mp, msdosfs_sync_vnode, &msa);
        !           727:
        !           728:        /*
        !           729:         * Force stale file system control information to be flushed.
        !           730:         */
        !           731:        if (waitfor != MNT_LAZY) {
        !           732:                vn_lock(pmp->pm_devvp, LK_EXCLUSIVE | LK_RETRY, p);
        !           733:                if ((error = VOP_FSYNC(pmp->pm_devvp, cred, waitfor, p)) != 0)
        !           734:                        msa.allerror = error;
        !           735:                VOP_UNLOCK(pmp->pm_devvp, 0, p);
        !           736:        }
        !           737:
        !           738:        return (msa.allerror);
        !           739: }
        !           740:
        !           741: int
        !           742: msdosfs_fhtovp(mp, fhp, vpp)
        !           743:        struct mount *mp;
        !           744:        struct fid *fhp;
        !           745:        struct vnode **vpp;
        !           746: {
        !           747:        struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
        !           748:        struct defid *defhp = (struct defid *) fhp;
        !           749:        struct denode *dep;
        !           750:        int error;
        !           751:
        !           752:        error = deget(pmp, defhp->defid_dirclust, defhp->defid_dirofs, &dep);
        !           753:        if (error) {
        !           754:                *vpp = NULLVP;
        !           755:                return (error);
        !           756:        }
        !           757:        *vpp = DETOV(dep);
        !           758:        return (0);
        !           759: }
        !           760:
        !           761: int
        !           762: msdosfs_vptofh(vp, fhp)
        !           763:        struct vnode *vp;
        !           764:        struct fid *fhp;
        !           765: {
        !           766:        struct denode *dep;
        !           767:        struct defid *defhp;
        !           768:
        !           769:        dep = VTODE(vp);
        !           770:        defhp = (struct defid *)fhp;
        !           771:        defhp->defid_len = sizeof(struct defid);
        !           772:        defhp->defid_dirclust = dep->de_dirclust;
        !           773:        defhp->defid_dirofs = dep->de_diroffset;
        !           774:        /* defhp->defid_gen = dep->de_gen; */
        !           775:        return (0);
        !           776: }
        !           777:
        !           778: int
        !           779: msdosfs_check_export(mp, nam, exflagsp, credanonp)
        !           780:        register struct mount *mp;
        !           781:        struct mbuf *nam;
        !           782:        int *exflagsp;
        !           783:        struct ucred **credanonp;
        !           784: {
        !           785:        register struct netcred *np;
        !           786:        register struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
        !           787:
        !           788:        /*
        !           789:         * Get the export permission structure for this <mp, client> tuple.
        !           790:         */
        !           791:        np = vfs_export_lookup(mp, &pmp->pm_export, nam);
        !           792:        if (np == NULL)
        !           793:                return (EACCES);
        !           794:
        !           795:        *exflagsp = np->netc_exflags;
        !           796:        *credanonp = &np->netc_anon;
        !           797:        return (0);
        !           798: }
        !           799:
        !           800: #define msdosfs_vget ((int (*)(struct mount *, ino_t, struct vnode **)) \
        !           801:                      eopnotsupp)
        !           802:
        !           803: #define msdosfs_quotactl ((int (*)(struct mount *, int, uid_t, caddr_t, \
        !           804:                                        struct proc *))eopnotsupp)
        !           805:
        !           806: #define msdosfs_sysctl ((int (*)(int *, u_int, void *, size_t *, void *, \
        !           807:                                     size_t, struct proc *))eopnotsupp)
        !           808:
        !           809: const struct vfsops msdosfs_vfsops = {
        !           810:        msdosfs_mount,
        !           811:        msdosfs_start,
        !           812:        msdosfs_unmount,
        !           813:        msdosfs_root,
        !           814:        msdosfs_quotactl,
        !           815:        msdosfs_statfs,
        !           816:        msdosfs_sync,
        !           817:        msdosfs_vget,
        !           818:        msdosfs_fhtovp,
        !           819:        msdosfs_vptofh,
        !           820:        msdosfs_init,
        !           821:        msdosfs_sysctl,
        !           822:        msdosfs_check_export
        !           823: };

CVSweb