[BACK]Return to msdosfs_vfsops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / fs / msdosfs

Annotation of src/sys/fs/msdosfs/msdosfs_vfsops.c, Revision 1.68

1.68    ! rumble      1: /*     $NetBSD: msdosfs_vfsops.c,v 1.67 2008/05/16 09:21:59 hannken Exp $      */
1.1       jdolecek    2:
                      3: /*-
                      4:  * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
                      5:  * Copyright (C) 1994, 1995, 1997 TooLs GmbH.
                      6:  * All rights reserved.
                      7:  * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *     This product includes software developed by TooLs GmbH.
                     20:  * 4. The name of TooLs GmbH may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     25:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     26:  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
                     27:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     28:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                     29:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     30:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     31:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
                     32:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     33:  */
                     34: /*
                     35:  * Written by Paul Popelka (paulp@uts.amdahl.com)
                     36:  *
                     37:  * You can do anything you want with this software, just don't say you wrote
                     38:  * it, and don't remove this notice.
                     39:  *
                     40:  * This software is provided "as is".
                     41:  *
                     42:  * The author supplies this software to be publicly redistributed on the
                     43:  * understanding that the author is not responsible for the correct
                     44:  * functioning of this software in any circumstances and is not liable for
                     45:  * any damages caused by this software.
                     46:  *
                     47:  * October 1992
                     48:  */
                     49:
                     50: #include <sys/cdefs.h>
1.68    ! rumble     51: __KERNEL_RCSID(0, "$NetBSD: msdosfs_vfsops.c,v 1.67 2008/05/16 09:21:59 hannken Exp $");
1.1       jdolecek   52:
                     53: #if defined(_KERNEL_OPT)
                     54: #include "opt_quota.h"
                     55: #include "opt_compat_netbsd.h"
                     56: #endif
                     57:
                     58: #include <sys/param.h>
                     59: #include <sys/systm.h>
1.12      atatat     60: #include <sys/sysctl.h>
1.1       jdolecek   61: #include <sys/namei.h>
                     62: #include <sys/proc.h>
                     63: #include <sys/kernel.h>
                     64: #include <sys/vnode.h>
1.60      dholland   65: #include <miscfs/genfs/genfs.h>
1.1       jdolecek   66: #include <miscfs/specfs/specdev.h> /* XXX */   /* defines v_rdev */
                     67: #include <sys/mount.h>
                     68: #include <sys/buf.h>
                     69: #include <sys/file.h>
                     70: #include <sys/device.h>
                     71: #include <sys/disklabel.h>
1.42      christos   72: #include <sys/disk.h>
1.1       jdolecek   73: #include <sys/ioctl.h>
                     74: #include <sys/malloc.h>
                     75: #include <sys/dirent.h>
                     76: #include <sys/stat.h>
                     77: #include <sys/conf.h>
1.31      elad       78: #include <sys/kauth.h>
1.66      rumble     79: #include <sys/module.h>
1.1       jdolecek   80:
                     81: #include <fs/msdosfs/bpb.h>
                     82: #include <fs/msdosfs/bootsect.h>
                     83: #include <fs/msdosfs/direntry.h>
                     84: #include <fs/msdosfs/denode.h>
                     85: #include <fs/msdosfs/msdosfsmount.h>
                     86: #include <fs/msdosfs/fat.h>
                     87:
1.66      rumble     88: MODULE(MODULE_CLASS_VFS, msdosfs, NULL);
                     89:
1.42      christos   90: #ifdef MSDOSFS_DEBUG
                     91: #define DPRINTF(a) uprintf a
                     92: #else
                     93: #define DPRINTF(a)
                     94: #endif
                     95:
1.20      jdolecek   96: #define MSDOSFS_NAMEMAX(pmp) \
                     97:        (pmp)->pm_flags & MSDOSFSMNT_LONGNAME ? WIN_MAXLEN : 12
                     98:
1.50      pooka      99: VFS_PROTOS(msdosfs);
1.1       jdolecek  100:
1.29      christos  101: int msdosfs_mountfs(struct vnode *, struct mount *, struct lwp *,
1.26      xtraeme   102:     struct msdosfs_args *);
1.1       jdolecek  103:
1.26      xtraeme   104: static int update_mp(struct mount *, struct msdosfs_args *);
1.2       thorpej   105:
1.45      pooka     106: MALLOC_JUSTDEFINE(M_MSDOSFSMNT, "MSDOSFS mount", "MSDOS FS mount structure");
                    107: MALLOC_JUSTDEFINE(M_MSDOSFSFAT, "MSDOSFS fat", "MSDOS FS fat table");
1.51      rumble    108: MALLOC_JUSTDEFINE(M_MSDOSFSTMP, "MSDOSFS temp", "MSDOS FS temp. structures");
1.1       jdolecek  109:
                    110: #define ROOTNAME "root_device"
                    111:
1.68    ! rumble    112: static struct sysctllog *msdosfs_sysctl_log;
        !           113:
1.1       jdolecek  114: extern const struct vnodeopv_desc msdosfs_vnodeop_opv_desc;
                    115:
                    116: const struct vnodeopv_desc * const msdosfs_vnodeopv_descs[] = {
                    117:        &msdosfs_vnodeop_opv_desc,
                    118:        NULL,
                    119: };
                    120:
                    121: struct vfsops msdosfs_vfsops = {
                    122:        MOUNT_MSDOS,
1.46      dsl       123:        sizeof (struct msdosfs_args),
1.1       jdolecek  124:        msdosfs_mount,
                    125:        msdosfs_start,
                    126:        msdosfs_unmount,
                    127:        msdosfs_root,
1.54      pooka     128:        (void *)eopnotsupp,             /* vfs_quotactl */
1.14      christos  129:        msdosfs_statvfs,
1.1       jdolecek  130:        msdosfs_sync,
                    131:        msdosfs_vget,
                    132:        msdosfs_fhtovp,
                    133:        msdosfs_vptofh,
                    134:        msdosfs_init,
                    135:        msdosfs_reinit,
                    136:        msdosfs_done,
                    137:        msdosfs_mountroot,
1.18      hannken   138:        (int (*)(struct mount *, struct vnode *, struct timespec *)) eopnotsupp,
1.21      thorpej   139:        vfs_stdextattrctl,
1.49      pooka     140:        (void *)eopnotsupp,             /* vfs_suspendctl */
1.60      dholland  141:        genfs_renamelock_enter,
                    142:        genfs_renamelock_exit,
1.62      ad        143:        (void *)eopnotsupp,
1.1       jdolecek  144:        msdosfs_vnodeopv_descs,
1.35      christos  145:        0,
                    146:        { NULL, NULL },
1.1       jdolecek  147: };
1.66      rumble    148:
                    149: static int
                    150: msdosfs_modcmd(modcmd_t cmd, void *arg)
                    151: {
1.68    ! rumble    152:        int error;
1.66      rumble    153:
                    154:        switch (cmd) {
                    155:        case MODULE_CMD_INIT:
1.68    ! rumble    156:                error = vfs_attach(&msdosfs_vfsops);
        !           157:                if (error != 0)
        !           158:                        break;
        !           159:                sysctl_createv(&msdosfs_sysctl_log, 0, NULL, NULL,
        !           160:                               CTLFLAG_PERMANENT,
        !           161:                               CTLTYPE_NODE, "vfs", NULL,
        !           162:                               NULL, 0, NULL, 0,
        !           163:                               CTL_VFS, CTL_EOL);
        !           164:                sysctl_createv(&msdosfs_sysctl_log, 0, NULL, NULL,
        !           165:                               CTLFLAG_PERMANENT,
        !           166:                               CTLTYPE_NODE, "msdosfs",
        !           167:                               SYSCTL_DESCR("MS-DOS file system"),
        !           168:                               NULL, 0, NULL, 0,
        !           169:                               CTL_VFS, 4, CTL_EOL);
        !           170:                /*
        !           171:                 * XXX the "4" above could be dynamic, thereby eliminating one
        !           172:                 * more instance of the "number to vfs" mapping problem, but
        !           173:                 * "4" is the order as taken from sys/mount.h
        !           174:                 */
        !           175:                break;
1.66      rumble    176:        case MODULE_CMD_FINI:
1.68    ! rumble    177:                error = vfs_detach(&msdosfs_vfsops);
        !           178:                if (error != 0)
        !           179:                        break;
        !           180:                sysctl_teardown(&msdosfs_sysctl_log);
        !           181:                break;
1.66      rumble    182:        default:
1.68    ! rumble    183:                error = ENOTTY;
        !           184:                break;
1.66      rumble    185:        }
1.68    ! rumble    186:
        !           187:        return (error);
1.66      rumble    188: }
1.1       jdolecek  189:
                    190: static int
1.6       thorpej   191: update_mp(mp, argp)
1.1       jdolecek  192:        struct mount *mp;
                    193:        struct msdosfs_args *argp;
                    194: {
                    195:        struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
                    196:        int error;
                    197:
                    198:        pmp->pm_gid = argp->gid;
                    199:        pmp->pm_uid = argp->uid;
                    200:        pmp->pm_mask = argp->mask & ALLPERMS;
1.8       jdolecek  201:        pmp->pm_dirmask = argp->dirmask & ALLPERMS;
1.9       itojun    202:        pmp->pm_gmtoff = argp->gmtoff;
1.1       jdolecek  203:        pmp->pm_flags |= argp->flags & MSDOSFSMNT_MNTOPT;
                    204:
                    205:        /*
                    206:         * GEMDOS knows nothing (yet) about win95
                    207:         */
                    208:        if (pmp->pm_flags & MSDOSFSMNT_GEMDOSFS)
                    209:                pmp->pm_flags |= MSDOSFSMNT_NOWIN95;
                    210:
                    211:        if (pmp->pm_flags & MSDOSFSMNT_NOWIN95)
                    212:                pmp->pm_flags |= MSDOSFSMNT_SHORTNAME;
                    213:        else if (!(pmp->pm_flags &
                    214:            (MSDOSFSMNT_SHORTNAME | MSDOSFSMNT_LONGNAME))) {
1.24      christos  215:                struct vnode *rtvp;
1.1       jdolecek  216:
                    217:                /*
                    218:                 * Try to divine whether to support Win'95 long filenames
                    219:                 */
                    220:                if (FAT32(pmp))
                    221:                        pmp->pm_flags |= MSDOSFSMNT_LONGNAME;
                    222:                else {
1.24      christos  223:                        if ((error = msdosfs_root(mp, &rtvp)) != 0)
1.1       jdolecek  224:                                return error;
1.24      christos  225:                        pmp->pm_flags |= findwin95(VTODE(rtvp))
1.1       jdolecek  226:                                ? MSDOSFSMNT_LONGNAME
                    227:                                        : MSDOSFSMNT_SHORTNAME;
1.24      christos  228:                        vput(rtvp);
1.1       jdolecek  229:                }
                    230:        }
1.20      jdolecek  231:
                    232:        mp->mnt_stat.f_namemax = MSDOSFS_NAMEMAX(pmp);
                    233:
1.1       jdolecek  234:        return 0;
                    235: }
                    236:
                    237: int
                    238: msdosfs_mountroot()
                    239: {
                    240:        struct mount *mp;
1.29      christos  241:        struct lwp *l = curlwp; /* XXX */
1.1       jdolecek  242:        int error;
                    243:        struct msdosfs_args args;
                    244:
1.30      thorpej   245:        if (device_class(root_device) != DV_DISK)
1.1       jdolecek  246:                return (ENODEV);
                    247:
                    248:        if ((error = vfs_rootmountalloc(MOUNT_MSDOS, "root_device", &mp))) {
                    249:                vrele(rootvp);
                    250:                return (error);
                    251:        }
                    252:
1.8       jdolecek  253:        args.flags = MSDOSFSMNT_VERSIONED;
1.1       jdolecek  254:        args.uid = 0;
                    255:        args.gid = 0;
                    256:        args.mask = 0777;
1.8       jdolecek  257:        args.version = MSDOSFSMNT_VERSION;
                    258:        args.dirmask = 0777;
1.1       jdolecek  259:
1.29      christos  260:        if ((error = msdosfs_mountfs(rootvp, mp, l, &args)) != 0) {
1.63      ad        261:                vfs_unbusy(mp, false, NULL);
1.65      ad        262:                vfs_destroy(mp);
1.1       jdolecek  263:                return (error);
                    264:        }
                    265:
1.6       thorpej   266:        if ((error = update_mp(mp, &args)) != 0) {
1.54      pooka     267:                (void)msdosfs_unmount(mp, 0);
1.63      ad        268:                vfs_unbusy(mp, false, NULL);
1.65      ad        269:                vfs_destroy(mp);
1.1       jdolecek  270:                vrele(rootvp);
                    271:                return (error);
                    272:        }
                    273:
1.53      ad        274:        mutex_enter(&mountlist_lock);
1.1       jdolecek  275:        CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
1.53      ad        276:        mutex_exit(&mountlist_lock);
1.54      pooka     277:        (void)msdosfs_statvfs(mp, &mp->mnt_stat);
1.63      ad        278:        vfs_unbusy(mp, false, NULL);
1.1       jdolecek  279:        return (0);
                    280: }
                    281:
                    282: /*
                    283:  * mp - path - addr in user space of mount point (ie /usr or whatever)
                    284:  * data - addr in user space of mount params including the name of the block
                    285:  * special file to treat as a filesystem.
                    286:  */
                    287: int
1.54      pooka     288: msdosfs_mount(mp, path, data, data_len)
1.1       jdolecek  289:        struct mount *mp;
                    290:        const char *path;
                    291:        void *data;
1.46      dsl       292:        size_t *data_len;
1.1       jdolecek  293: {
1.54      pooka     294:        struct lwp *l = curlwp;
1.50      pooka     295:        struct nameidata nd;
1.1       jdolecek  296:        struct vnode *devvp;      /* vnode for blk device to mount */
1.46      dsl       297:        struct msdosfs_args *args = data; /* holds data from mount request */
1.1       jdolecek  298:        /* msdosfs specific mount control block */
                    299:        struct msdosfsmount *pmp = NULL;
                    300:        int error, flags;
                    301:        mode_t accessmode;
                    302:
1.46      dsl       303:        if (*data_len < sizeof *args)
                    304:                return EINVAL;
                    305:
1.1       jdolecek  306:        if (mp->mnt_flag & MNT_GETARGS) {
                    307:                pmp = VFSTOMSDOSFS(mp);
                    308:                if (pmp == NULL)
                    309:                        return EIO;
1.46      dsl       310:                args->fspec = NULL;
                    311:                args->uid = pmp->pm_uid;
                    312:                args->gid = pmp->pm_gid;
                    313:                args->mask = pmp->pm_mask;
                    314:                args->flags = pmp->pm_flags;
                    315:                args->version = MSDOSFSMNT_VERSION;
                    316:                args->dirmask = pmp->pm_dirmask;
                    317:                args->gmtoff = pmp->pm_gmtoff;
                    318:                *data_len = sizeof *args;
                    319:                return 0;
1.42      christos  320:        }
1.8       jdolecek  321:
                    322:        /*
                    323:         * If not versioned (i.e. using old mount_msdos(8)), fill in
                    324:         * the additional structure items with suitable defaults.
                    325:         */
1.46      dsl       326:        if ((args->flags & MSDOSFSMNT_VERSIONED) == 0) {
                    327:                args->version = 1;
                    328:                args->dirmask = args->mask;
1.8       jdolecek  329:        }
                    330:
1.1       jdolecek  331:        /*
1.15      jdolecek  332:         * Reset GMT offset for pre-v3 mount structure args.
                    333:         */
1.46      dsl       334:        if (args->version < 3)
                    335:                args->gmtoff = 0;
1.15      jdolecek  336:
                    337:        /*
1.1       jdolecek  338:         * If updating, check whether changing from read-only to
                    339:         * read/write; if there is no device name, that's all we do.
                    340:         */
                    341:        if (mp->mnt_flag & MNT_UPDATE) {
                    342:                pmp = VFSTOMSDOSFS(mp);
                    343:                error = 0;
                    344:                if (!(pmp->pm_flags & MSDOSFSMNT_RONLY) && (mp->mnt_flag & MNT_RDONLY)) {
                    345:                        flags = WRITECLOSE;
                    346:                        if (mp->mnt_flag & MNT_FORCE)
                    347:                                flags |= FORCECLOSE;
                    348:                        error = vflush(mp, NULLVP, flags);
                    349:                }
                    350:                if (!error && (mp->mnt_flag & MNT_RELOAD))
                    351:                        /* not yet implemented */
                    352:                        error = EOPNOTSUPP;
1.42      christos  353:                if (error) {
                    354:                        DPRINTF(("vflush %d\n", error));
1.1       jdolecek  355:                        return (error);
1.42      christos  356:                }
1.11      dbj       357:                if ((pmp->pm_flags & MSDOSFSMNT_RONLY) && (mp->mnt_iflag & IMNT_WANTRDWR)) {
1.1       jdolecek  358:                        /*
                    359:                         * If upgrade to read-write by non-root, then verify
                    360:                         * that user has necessary permissions on the device.
                    361:                         */
1.33      ad        362:                        if (kauth_authorize_generic(l->l_cred,
                    363:                            KAUTH_GENERIC_ISSUSER, NULL) != 0) {
1.1       jdolecek  364:                                devvp = pmp->pm_devvp;
                    365:                                vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
                    366:                                error = VOP_ACCESS(devvp, VREAD | VWRITE,
1.54      pooka     367:                                                   l->l_cred);
1.1       jdolecek  368:                                VOP_UNLOCK(devvp, 0);
1.42      christos  369:                                DPRINTF(("VOP_ACCESS %d\n", error));
1.1       jdolecek  370:                                if (error)
                    371:                                        return (error);
                    372:                        }
                    373:                        pmp->pm_flags &= ~MSDOSFSMNT_RONLY;
                    374:                }
1.46      dsl       375:                if (args->fspec == NULL) {
1.42      christos  376:                        DPRINTF(("missing fspec\n"));
1.28      jmmv      377:                        return EINVAL;
1.42      christos  378:                }
1.1       jdolecek  379:        }
                    380:        /*
                    381:         * Not an update, or updating the name: look up the name
                    382:         * and verify that it refers to a sensible block device.
                    383:         */
1.55      pooka     384:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, args->fspec);
1.50      pooka     385:        if ((error = namei(&nd)) != 0) {
1.42      christos  386:                DPRINTF(("namei %d\n", error));
1.1       jdolecek  387:                return (error);
1.42      christos  388:        }
1.50      pooka     389:        devvp = nd.ni_vp;
1.1       jdolecek  390:
                    391:        if (devvp->v_type != VBLK) {
1.42      christos  392:                DPRINTF(("not block\n"));
1.1       jdolecek  393:                vrele(devvp);
                    394:                return (ENOTBLK);
                    395:        }
                    396:        if (bdevsw_lookup(devvp->v_rdev) == NULL) {
1.42      christos  397:                DPRINTF(("no block switch\n"));
1.1       jdolecek  398:                vrele(devvp);
                    399:                return (ENXIO);
                    400:        }
                    401:        /*
                    402:         * If mount by non-root, then verify that user has necessary
                    403:         * permissions on the device.
                    404:         */
1.33      ad        405:        if (kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER, NULL) != 0) {
1.1       jdolecek  406:                accessmode = VREAD;
                    407:                if ((mp->mnt_flag & MNT_RDONLY) == 0)
                    408:                        accessmode |= VWRITE;
                    409:                vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.54      pooka     410:                error = VOP_ACCESS(devvp, accessmode, l->l_cred);
1.1       jdolecek  411:                VOP_UNLOCK(devvp, 0);
                    412:                if (error) {
1.42      christos  413:                        DPRINTF(("VOP_ACCESS2 %d\n", error));
1.1       jdolecek  414:                        vrele(devvp);
                    415:                        return (error);
                    416:                }
                    417:        }
                    418:        if ((mp->mnt_flag & MNT_UPDATE) == 0) {
1.24      christos  419:                int xflags;
1.22      mycroft   420:
                    421:                if (mp->mnt_flag & MNT_RDONLY)
1.24      christos  422:                        xflags = FREAD;
1.22      mycroft   423:                else
1.24      christos  424:                        xflags = FREAD|FWRITE;
1.54      pooka     425:                error = VOP_OPEN(devvp, xflags, FSCRED);
1.42      christos  426:                if (error) {
                    427:                        DPRINTF(("VOP_OPEN %d\n", error));
1.22      mycroft   428:                        goto fail;
1.42      christos  429:                }
1.46      dsl       430:                error = msdosfs_mountfs(devvp, mp, l, args);
1.22      mycroft   431:                if (error) {
1.42      christos  432:                        DPRINTF(("msdosfs_mountfs %d\n", error));
1.22      mycroft   433:                        vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
1.54      pooka     434:                        (void) VOP_CLOSE(devvp, xflags, NOCRED);
1.22      mycroft   435:                        VOP_UNLOCK(devvp, 0);
                    436:                        goto fail;
                    437:                }
1.1       jdolecek  438: #ifdef MSDOSFS_DEBUG           /* only needed for the printf below */
                    439:                pmp = VFSTOMSDOSFS(mp);
                    440: #endif
                    441:        } else {
1.22      mycroft   442:                vrele(devvp);
1.42      christos  443:                if (devvp != pmp->pm_devvp) {
                    444:                        DPRINTF(("devvp %p pmp %p\n",
                    445:                            devvp, pmp->pm_devvp));
1.22      mycroft   446:                        return (EINVAL);        /* needs translation */
1.42      christos  447:                }
1.1       jdolecek  448:        }
1.46      dsl       449:        if ((error = update_mp(mp, args)) != 0) {
1.54      pooka     450:                msdosfs_unmount(mp, MNT_FORCE);
1.42      christos  451:                DPRINTF(("update_mp %d\n", error));
1.1       jdolecek  452:                return error;
                    453:        }
                    454:
                    455: #ifdef MSDOSFS_DEBUG
                    456:        printf("msdosfs_mount(): mp %p, pmp %p, inusemap %p\n", mp, pmp, pmp->pm_inusemap);
                    457: #endif
1.46      dsl       458:        return set_statvfs_info(path, UIO_USERSPACE, args->fspec, UIO_USERSPACE,
1.47      pooka     459:            mp->mnt_op->vfs_name, mp, l);
1.22      mycroft   460:
                    461: fail:
                    462:        vrele(devvp);
                    463:        return (error);
1.1       jdolecek  464: }
                    465:
                    466: int
1.29      christos  467: msdosfs_mountfs(devvp, mp, l, argp)
1.1       jdolecek  468:        struct vnode *devvp;
                    469:        struct mount *mp;
1.29      christos  470:        struct lwp *l;
1.1       jdolecek  471:        struct msdosfs_args *argp;
                    472: {
                    473:        struct msdosfsmount *pmp;
                    474:        struct buf *bp;
                    475:        dev_t dev = devvp->v_rdev;
                    476:        struct partinfo dpart;
                    477:        union bootsector *bsp;
                    478:        struct byte_bpb33 *b33;
                    479:        struct byte_bpb50 *b50;
                    480:        struct byte_bpb710 *b710;
                    481:        u_int8_t SecPerClust;
1.42      christos  482:        int     ronly, error, tmp;
                    483:        int     bsize, dtype, fstype, secsize;
                    484:        u_int64_t psize;
1.1       jdolecek  485:
1.22      mycroft   486:        /* Flush out any old buffers remaining from a previous use. */
1.33      ad        487:        if ((error = vinvalbuf(devvp, V_SAVE, l->l_cred, l, 0, 0)) != 0)
1.1       jdolecek  488:                return (error);
                    489:
                    490:        ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
                    491:
                    492:        bp  = NULL; /* both used in error_exit */
                    493:        pmp = NULL;
                    494:
1.40      scw       495:        /*
                    496:         * We need the disklabel to calculate the size of a FAT entry
                    497:         * later on. Also make sure the partition contains a filesystem
                    498:         * of type FS_MSDOS. This doesn't work for floppies, so we have
                    499:         * to check for them too.
                    500:         *
                    501:         * There might still be parts of the msdos fs driver which assume
                    502:         * that the size of a disk block will always be 512 bytes.
                    503:         * Let's root them out...
                    504:         */
1.54      pooka     505:        error = VOP_IOCTL(devvp, DIOCGPART, &dpart, FREAD, NOCRED);
1.42      christos  506:        if (error == 0) {
                    507:                secsize = dpart.disklab->d_secsize;
                    508:                dtype = dpart.disklab->d_type;
                    509:                fstype = dpart.part->p_fstype;
                    510:                psize = dpart.part->p_size;
                    511:        } else {
                    512:                struct dkwedge_info dkw;
1.54      pooka     513:                error = VOP_IOCTL(devvp, DIOCGWEDGEINFO, &dkw, FREAD, NOCRED);
1.44      kochi     514:                secsize = 512;  /* XXX */
                    515:                dtype = DTYPE_FLOPPY; /* XXX */
                    516:                fstype = FS_MSDOS;
                    517:                psize = -1;
1.42      christos  518:                if (error) {
1.44      kochi     519:                        if (error != ENOTTY) {
                    520:                                DPRINTF(("Error getting partition info %d\n",
                    521:                                    error));
                    522:                                goto error_exit;
                    523:                        }
                    524:                } else {
                    525:                        fstype = strcmp(dkw.dkw_ptype, DKW_PTYPE_FAT) == 0 ?
                    526:                            FS_MSDOS : -1;
                    527:                        psize = dkw.dkw_size;
1.42      christos  528:                }
                    529:        }
1.1       jdolecek  530:        if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
1.42      christos  531:                bsize = secsize;
                    532:                if (bsize != 512 ||
                    533:                    (dtype != DTYPE_FLOPPY && fstype != FS_MSDOS)) {
                    534:                        DPRINTF(("bsize %d dtype %d fstype %d\n", bsize, dtype,
                    535:                            fstype));
1.1       jdolecek  536:                        error = EINVAL;
                    537:                        goto error_exit;
                    538:                }
1.42      christos  539:        } else
                    540:                bsize = 0;
1.1       jdolecek  541:
                    542:        /*
                    543:         * Read the boot sector of the filesystem, and then check the
                    544:         * boot signature.  If not a dos boot sector then error out.
                    545:         */
1.67      hannken   546:        if ((error = bread(devvp, 0, secsize, NOCRED, 0, &bp)) != 0)
1.1       jdolecek  547:                goto error_exit;
                    548:        bsp = (union bootsector *)bp->b_data;
                    549:        b33 = (struct byte_bpb33 *)bsp->bs33.bsBPB;
                    550:        b50 = (struct byte_bpb50 *)bsp->bs50.bsBPB;
1.10      lukem     551:        b710 = (struct byte_bpb710 *)bsp->bs710.bsBPB;
1.1       jdolecek  552:
                    553:        if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) {
                    554:                if (bsp->bs50.bsBootSectSig0 != BOOTSIG0
                    555:                    || bsp->bs50.bsBootSectSig1 != BOOTSIG1) {
1.42      christos  556:                        DPRINTF(("bootsig0 %d bootsig1 %d\n",
                    557:                            bsp->bs50.bsBootSectSig0,
                    558:                            bsp->bs50.bsBootSectSig1));
1.1       jdolecek  559:                        error = EINVAL;
                    560:                        goto error_exit;
                    561:                }
                    562:        }
                    563:
                    564:        pmp = malloc(sizeof *pmp, M_MSDOSFSMNT, M_WAITOK);
1.3       dsl       565:        memset(pmp, 0, sizeof *pmp);
1.1       jdolecek  566:        pmp->pm_mountp = mp;
                    567:
                    568:        /*
                    569:         * Compute several useful quantities from the bpb in the
                    570:         * bootsector.  Copy in the dos 5 variant of the bpb then fix up
                    571:         * the fields that are different between dos 5 and dos 3.3.
                    572:         */
                    573:        SecPerClust = b50->bpbSecPerClust;
                    574:        pmp->pm_BytesPerSec = getushort(b50->bpbBytesPerSec);
                    575:        pmp->pm_ResSectors = getushort(b50->bpbResSectors);
                    576:        pmp->pm_FATs = b50->bpbFATs;
                    577:        pmp->pm_RootDirEnts = getushort(b50->bpbRootDirEnts);
                    578:        pmp->pm_Sectors = getushort(b50->bpbSectors);
                    579:        pmp->pm_FATsecs = getushort(b50->bpbFATsecs);
                    580:        pmp->pm_SecPerTrack = getushort(b50->bpbSecPerTrack);
                    581:        pmp->pm_Heads = getushort(b50->bpbHeads);
                    582:        pmp->pm_Media = b50->bpbMedia;
                    583:
                    584:        if (!(argp->flags & MSDOSFSMNT_GEMDOSFS)) {
                    585:                /* XXX - We should probably check more values here */
                    586:                if (!pmp->pm_BytesPerSec || !SecPerClust
                    587:                        || pmp->pm_Heads > 255 || pmp->pm_SecPerTrack > 63) {
1.42      christos  588:                        DPRINTF(("bytespersec %d secperclust %d "
                    589:                            "heads %d secpertrack %d\n",
                    590:                            pmp->pm_BytesPerSec, SecPerClust,
                    591:                            pmp->pm_Heads, pmp->pm_SecPerTrack));
1.1       jdolecek  592:                        error = EINVAL;
                    593:                        goto error_exit;
                    594:                }
                    595:        }
                    596:
                    597:        if (pmp->pm_Sectors == 0) {
                    598:                pmp->pm_HiddenSects = getulong(b50->bpbHiddenSecs);
                    599:                pmp->pm_HugeSectors = getulong(b50->bpbHugeSectors);
                    600:        } else {
                    601:                pmp->pm_HiddenSects = getushort(b33->bpbHiddenSecs);
                    602:                pmp->pm_HugeSectors = pmp->pm_Sectors;
                    603:        }
                    604:
                    605:        if (pmp->pm_RootDirEnts == 0) {
1.42      christos  606:                unsigned short vers = getushort(b710->bpbFSVers);
1.34      gdt       607:                /*
                    608:                 * Some say that bsBootSectSig[23] must be zero, but
                    609:                 * Windows does not require this and some digital cameras
                    610:                 * do not set these to zero.  Therefore, do not insist.
                    611:                 */
1.42      christos  612:                if (pmp->pm_Sectors || pmp->pm_FATsecs || vers) {
                    613:                        DPRINTF(("sectors %d fatsecs %lu vers %d\n",
                    614:                            pmp->pm_Sectors, pmp->pm_FATsecs, vers));
1.1       jdolecek  615:                        error = EINVAL;
                    616:                        goto error_exit;
                    617:                }
                    618:                pmp->pm_fatmask = FAT32_MASK;
                    619:                pmp->pm_fatmult = 4;
                    620:                pmp->pm_fatdiv = 1;
                    621:                pmp->pm_FATsecs = getulong(b710->bpbBigFATsecs);
                    622:
                    623:                /* mirrorring is enabled if the FATMIRROR bit is not set */
                    624:                if ((getushort(b710->bpbExtFlags) & FATMIRROR) == 0)
                    625:                        pmp->pm_flags |= MSDOSFS_FATMIRROR;
                    626:                else
                    627:                        pmp->pm_curfat = getushort(b710->bpbExtFlags) & FATNUM;
                    628:        } else
                    629:                pmp->pm_flags |= MSDOSFS_FATMIRROR;
                    630:
                    631:        if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
                    632:                if (FAT32(pmp)) {
1.42      christos  633:                        DPRINTF(("fat32 for gemdos\n"));
1.1       jdolecek  634:                        /*
                    635:                         * GEMDOS doesn't know fat32.
                    636:                         */
                    637:                        error = EINVAL;
                    638:                        goto error_exit;
                    639:                }
                    640:
                    641:                /*
                    642:                 * Check a few values (could do some more):
                    643:                 * - logical sector size: power of 2, >= block size
                    644:                 * - sectors per cluster: power of 2, >= 1
                    645:                 * - number of sectors:   >= 1, <= size of partition
                    646:                 */
                    647:                if ( (SecPerClust == 0)
                    648:                  || (SecPerClust & (SecPerClust - 1))
                    649:                  || (pmp->pm_BytesPerSec < bsize)
                    650:                  || (pmp->pm_BytesPerSec & (pmp->pm_BytesPerSec - 1))
                    651:                  || (pmp->pm_HugeSectors == 0)
                    652:                  || (pmp->pm_HugeSectors * (pmp->pm_BytesPerSec / bsize)
1.42      christos  653:                      > psize)) {
                    654:                        DPRINTF(("consistency checks for gemdos\n"));
1.1       jdolecek  655:                        error = EINVAL;
                    656:                        goto error_exit;
                    657:                }
                    658:                /*
                    659:                 * XXX - Many parts of the msdos fs driver seem to assume that
                    660:                 * the number of bytes per logical sector (BytesPerSec) will
                    661:                 * always be the same as the number of bytes per disk block
                    662:                 * Let's pretend it is.
                    663:                 */
                    664:                tmp = pmp->pm_BytesPerSec / bsize;
                    665:                pmp->pm_BytesPerSec  = bsize;
                    666:                pmp->pm_HugeSectors *= tmp;
                    667:                pmp->pm_HiddenSects *= tmp;
                    668:                pmp->pm_ResSectors  *= tmp;
                    669:                pmp->pm_Sectors     *= tmp;
                    670:                pmp->pm_FATsecs     *= tmp;
                    671:                SecPerClust         *= tmp;
                    672:        }
1.58      pooka     673:
                    674:        /* Check that fs has nonzero FAT size */
                    675:        if (pmp->pm_FATsecs == 0) {
                    676:                DPRINTF(("FATsecs is 0\n"));
                    677:                error = EINVAL;
                    678:                goto error_exit;
                    679:        }
                    680:
1.1       jdolecek  681:        pmp->pm_fatblk = pmp->pm_ResSectors;
                    682:        if (FAT32(pmp)) {
                    683:                pmp->pm_rootdirblk = getulong(b710->bpbRootClust);
                    684:                pmp->pm_firstcluster = pmp->pm_fatblk
                    685:                        + (pmp->pm_FATs * pmp->pm_FATsecs);
                    686:                pmp->pm_fsinfo = getushort(b710->bpbFSInfo);
                    687:        } else {
                    688:                pmp->pm_rootdirblk = pmp->pm_fatblk +
                    689:                        (pmp->pm_FATs * pmp->pm_FATsecs);
                    690:                pmp->pm_rootdirsize = (pmp->pm_RootDirEnts * sizeof(struct direntry)
                    691:                                       + pmp->pm_BytesPerSec - 1)
                    692:                        / pmp->pm_BytesPerSec;/* in sectors */
                    693:                pmp->pm_firstcluster = pmp->pm_rootdirblk + pmp->pm_rootdirsize;
                    694:        }
                    695:
                    696:        pmp->pm_nmbrofclusters = (pmp->pm_HugeSectors - pmp->pm_firstcluster) /
                    697:            SecPerClust;
                    698:        pmp->pm_maxcluster = pmp->pm_nmbrofclusters + 1;
                    699:        pmp->pm_fatsize = pmp->pm_FATsecs * pmp->pm_BytesPerSec;
                    700:
                    701:        if (argp->flags & MSDOSFSMNT_GEMDOSFS) {
                    702:                if (pmp->pm_nmbrofclusters <= (0xff0 - 2)
                    703:                      && (dtype == DTYPE_FLOPPY
                    704:                          || (dtype == DTYPE_VND
                    705:                                && (pmp->pm_Heads == 1 || pmp->pm_Heads == 2)))
                    706:                    ) {
                    707:                        pmp->pm_fatmask = FAT12_MASK;
                    708:                        pmp->pm_fatmult = 3;
                    709:                        pmp->pm_fatdiv = 2;
                    710:                } else {
                    711:                        pmp->pm_fatmask = FAT16_MASK;
                    712:                        pmp->pm_fatmult = 2;
                    713:                        pmp->pm_fatdiv = 1;
                    714:                }
                    715:        } else if (pmp->pm_fatmask == 0) {
                    716:                if (pmp->pm_maxcluster
                    717:                    <= ((CLUST_RSRVD - CLUST_FIRST) & FAT12_MASK)) {
                    718:                        /*
                    719:                         * This will usually be a floppy disk. This size makes
                    720:                         * sure that one fat entry will not be split across
                    721:                         * multiple blocks.
                    722:                         */
                    723:                        pmp->pm_fatmask = FAT12_MASK;
                    724:                        pmp->pm_fatmult = 3;
                    725:                        pmp->pm_fatdiv = 2;
                    726:                } else {
                    727:                        pmp->pm_fatmask = FAT16_MASK;
                    728:                        pmp->pm_fatmult = 2;
                    729:                        pmp->pm_fatdiv = 1;
                    730:                }
                    731:        }
                    732:        if (FAT12(pmp))
                    733:                pmp->pm_fatblocksize = 3 * pmp->pm_BytesPerSec;
                    734:        else
                    735:                pmp->pm_fatblocksize = MAXBSIZE;
                    736:
                    737:        pmp->pm_fatblocksec = pmp->pm_fatblocksize / pmp->pm_BytesPerSec;
                    738:        pmp->pm_bnshift = ffs(pmp->pm_BytesPerSec) - 1;
                    739:
                    740:        /*
                    741:         * Compute mask and shift value for isolating cluster relative byte
                    742:         * offsets and cluster numbers from a file offset.
                    743:         */
                    744:        pmp->pm_bpcluster = SecPerClust * pmp->pm_BytesPerSec;
                    745:        pmp->pm_crbomask = pmp->pm_bpcluster - 1;
                    746:        pmp->pm_cnshift = ffs(pmp->pm_bpcluster) - 1;
                    747:
                    748:        /*
                    749:         * Check for valid cluster size
                    750:         * must be a power of 2
                    751:         */
                    752:        if (pmp->pm_bpcluster ^ (1 << pmp->pm_cnshift)) {
1.42      christos  753:                DPRINTF(("bpcluster %lu cnshift %lu\n",
                    754:                    pmp->pm_bpcluster, pmp->pm_cnshift));
1.1       jdolecek  755:                error = EINVAL;
                    756:                goto error_exit;
                    757:        }
                    758:
                    759:        /*
                    760:         * Release the bootsector buffer.
                    761:         */
1.52      ad        762:        brelse(bp, BC_AGE);
1.1       jdolecek  763:        bp = NULL;
                    764:
                    765:        /*
                    766:         * Check FSInfo.
                    767:         */
                    768:        if (pmp->pm_fsinfo) {
                    769:                struct fsinfo *fp;
                    770:
1.40      scw       771:                /*
                    772:                 * XXX  If the fsinfo block is stored on media with
                    773:                 *      2KB or larger sectors, is the fsinfo structure
                    774:                 *      padded at the end or in the middle?
                    775:                 */
                    776:                if ((error = bread(devvp, de_bn2kb(pmp, pmp->pm_fsinfo),
1.67      hannken   777:                    pmp->pm_BytesPerSec, NOCRED, 0, &bp)) != 0)
1.1       jdolecek  778:                        goto error_exit;
                    779:                fp = (struct fsinfo *)bp->b_data;
                    780:                if (!memcmp(fp->fsisig1, "RRaA", 4)
                    781:                    && !memcmp(fp->fsisig2, "rrAa", 4)
                    782:                    && !memcmp(fp->fsisig3, "\0\0\125\252", 4)
                    783:                    && !memcmp(fp->fsisig4, "\0\0\125\252", 4))
                    784:                        pmp->pm_nxtfree = getulong(fp->fsinxtfree);
                    785:                else
                    786:                        pmp->pm_fsinfo = 0;
1.52      ad        787:                brelse(bp, 0);
1.1       jdolecek  788:                bp = NULL;
                    789:        }
                    790:
                    791:        /*
                    792:         * Check and validate (or perhaps invalidate?) the fsinfo structure?
                    793:         * XXX
                    794:         */
                    795:        if (pmp->pm_fsinfo) {
                    796:                if (pmp->pm_nxtfree == (u_long)-1)
                    797:                        pmp->pm_fsinfo = 0;
                    798:        }
                    799:
                    800:        /*
                    801:         * Allocate memory for the bitmap of allocated clusters, and then
                    802:         * fill it in.
                    803:         */
                    804:        pmp->pm_inusemap = malloc(((pmp->pm_maxcluster + N_INUSEBITS - 1)
                    805:                                   / N_INUSEBITS)
                    806:                                  * sizeof(*pmp->pm_inusemap),
                    807:                                  M_MSDOSFSFAT, M_WAITOK);
                    808:
                    809:        /*
                    810:         * fillinusemap() needs pm_devvp.
                    811:         */
                    812:        pmp->pm_dev = dev;
                    813:        pmp->pm_devvp = devvp;
                    814:
                    815:        /*
                    816:         * Have the inuse map filled in.
                    817:         */
1.42      christos  818:        if ((error = fillinusemap(pmp)) != 0) {
                    819:                DPRINTF(("fillinusemap %d\n", error));
1.1       jdolecek  820:                goto error_exit;
1.42      christos  821:        }
1.1       jdolecek  822:
                    823:        /*
                    824:         * If they want fat updates to be synchronous then let them suffer
                    825:         * the performance degradation in exchange for the on disk copy of
                    826:         * the fat being correct just about all the time.  I suppose this
                    827:         * would be a good thing to turn on if the kernel is still flakey.
                    828:         */
                    829:        if (mp->mnt_flag & MNT_SYNCHRONOUS)
                    830:                pmp->pm_flags |= MSDOSFSMNT_WAITONFAT;
                    831:
                    832:        /*
                    833:         * Finish up.
                    834:         */
                    835:        if (ronly)
                    836:                pmp->pm_flags |= MSDOSFSMNT_RONLY;
                    837:        else
                    838:                pmp->pm_fmod = 1;
                    839:        mp->mnt_data = pmp;
1.20      jdolecek  840:        mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)dev;
                    841:        mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_MSDOS);
                    842:        mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
                    843:        mp->mnt_stat.f_namemax = MSDOSFS_NAMEMAX(pmp);
1.1       jdolecek  844:        mp->mnt_flag |= MNT_LOCAL;
                    845:        mp->mnt_dev_bshift = pmp->pm_bnshift;
                    846:        mp->mnt_fs_bshift = pmp->pm_cnshift;
                    847:
                    848: #ifdef QUOTA
                    849:        /*
                    850:         * If we ever do quotas for DOS filesystems this would be a place
                    851:         * to fill in the info in the msdosfsmount structure. You dolt,
                    852:         * quotas on dos filesystems make no sense because files have no
                    853:         * owners on dos filesystems. of course there is some empty space
                    854:         * in the directory entry where we could put uid's and gid's.
                    855:         */
                    856: #endif
                    857:        devvp->v_specmountpoint = mp;
                    858:
                    859:        return (0);
                    860:
                    861: error_exit:;
                    862:        if (bp)
1.52      ad        863:                brelse(bp, BC_AGE);
1.1       jdolecek  864:        if (pmp) {
                    865:                if (pmp->pm_inusemap)
                    866:                        free(pmp->pm_inusemap, M_MSDOSFSFAT);
                    867:                free(pmp, M_MSDOSFSMNT);
                    868:                mp->mnt_data = NULL;
                    869:        }
                    870:        return (error);
                    871: }
                    872:
                    873: int
1.54      pooka     874: msdosfs_start(struct mount *mp, int flags)
1.1       jdolecek  875: {
                    876:
                    877:        return (0);
                    878: }
                    879:
                    880: /*
                    881:  * Unmount the filesystem described by mp.
                    882:  */
                    883: int
1.54      pooka     884: msdosfs_unmount(mp, mntflags)
1.1       jdolecek  885:        struct mount *mp;
                    886:        int mntflags;
                    887: {
                    888:        struct msdosfsmount *pmp;
                    889:        int error, flags;
                    890:
                    891:        flags = 0;
                    892:        if (mntflags & MNT_FORCE)
                    893:                flags |= FORCECLOSE;
                    894: #ifdef QUOTA
                    895: #endif
                    896:        if ((error = vflush(mp, NULLVP, flags)) != 0)
                    897:                return (error);
                    898:        pmp = VFSTOMSDOSFS(mp);
                    899:        if (pmp->pm_devvp->v_type != VBAD)
                    900:                pmp->pm_devvp->v_specmountpoint = NULL;
                    901: #ifdef MSDOSFS_DEBUG
                    902:        {
                    903:                struct vnode *vp = pmp->pm_devvp;
                    904:
                    905:                printf("msdosfs_umount(): just before calling VOP_CLOSE()\n");
1.64      ad        906:                printf("flag %08x, usecount %d, writecount %d, holdcnt %d\n",
1.53      ad        907:                    vp->v_vflag | vp->v_iflag | vp->v_uflag, vp->v_usecount,
                    908:                    vp->v_writecount, vp->v_holdcnt);
1.25      jmmv      909:                printf("mount %p, op %p\n",
                    910:                    vp->v_mount, vp->v_op);
1.1       jdolecek  911:                printf("freef %p, freeb %p, mount %p\n",
                    912:                    vp->v_freelist.tqe_next, vp->v_freelist.tqe_prev,
                    913:                    vp->v_mount);
                    914:                printf("cleanblkhd %p, dirtyblkhd %p, numoutput %d, type %d\n",
                    915:                    vp->v_cleanblkhd.lh_first,
                    916:                    vp->v_dirtyblkhd.lh_first,
                    917:                    vp->v_numoutput, vp->v_type);
                    918:                printf("union %p, tag %d, data[0] %08x, data[1] %08x\n",
                    919:                    vp->v_socket, vp->v_tag,
                    920:                    ((u_int *)vp->v_data)[0],
                    921:                    ((u_int *)vp->v_data)[1]);
                    922:        }
                    923: #endif
                    924:        vn_lock(pmp->pm_devvp, LK_EXCLUSIVE | LK_RETRY);
                    925:        error = VOP_CLOSE(pmp->pm_devvp,
1.54      pooka     926:            pmp->pm_flags & MSDOSFSMNT_RONLY ? FREAD : FREAD|FWRITE, NOCRED);
1.1       jdolecek  927:        vput(pmp->pm_devvp);
                    928:        free(pmp->pm_inusemap, M_MSDOSFSFAT);
                    929:        free(pmp, M_MSDOSFSMNT);
                    930:        mp->mnt_data = NULL;
                    931:        mp->mnt_flag &= ~MNT_LOCAL;
                    932:        return (error);
                    933: }
                    934:
                    935: int
1.6       thorpej   936: msdosfs_root(mp, vpp)
1.1       jdolecek  937:        struct mount *mp;
                    938:        struct vnode **vpp;
                    939: {
                    940:        struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
                    941:        struct denode *ndep;
                    942:        int error;
                    943:
                    944: #ifdef MSDOSFS_DEBUG
                    945:        printf("msdosfs_root(); mp %p, pmp %p\n", mp, pmp);
                    946: #endif
                    947:        if ((error = deget(pmp, MSDOSFSROOT, MSDOSFSROOT_OFS, &ndep)) != 0)
                    948:                return (error);
                    949:        *vpp = DETOV(ndep);
                    950:        return (0);
                    951: }
                    952:
                    953: int
1.54      pooka     954: msdosfs_statvfs(struct mount *mp, struct statvfs *sbp)
1.1       jdolecek  955: {
                    956:        struct msdosfsmount *pmp;
                    957:
                    958:        pmp = VFSTOMSDOSFS(mp);
                    959:        sbp->f_bsize = pmp->pm_bpcluster;
1.14      christos  960:        sbp->f_frsize = sbp->f_bsize;
1.1       jdolecek  961:        sbp->f_iosize = pmp->pm_bpcluster;
                    962:        sbp->f_blocks = pmp->pm_nmbrofclusters;
                    963:        sbp->f_bfree = pmp->pm_freeclustercount;
                    964:        sbp->f_bavail = pmp->pm_freeclustercount;
1.14      christos  965:        sbp->f_bresvd = 0;
1.1       jdolecek  966:        sbp->f_files = pmp->pm_RootDirEnts;                     /* XXX */
                    967:        sbp->f_ffree = 0;       /* what to put in here? */
1.14      christos  968:        sbp->f_favail = 0;      /* what to put in here? */
                    969:        sbp->f_fresvd = 0;
                    970:        copy_statvfs_info(sbp, mp);
1.1       jdolecek  971:        return (0);
                    972: }
                    973:
                    974: int
1.54      pooka     975: msdosfs_sync(mp, waitfor, cred)
1.1       jdolecek  976:        struct mount *mp;
                    977:        int waitfor;
1.31      elad      978:        kauth_cred_t cred;
1.1       jdolecek  979: {
1.56      ad        980:        struct vnode *vp, *mvp;
1.1       jdolecek  981:        struct denode *dep;
                    982:        struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
                    983:        int error, allerror = 0;
                    984:
                    985:        /*
                    986:         * If we ever switch to not updating all of the fats all the time,
                    987:         * this would be the place to update them from the first one.
                    988:         */
                    989:        if (pmp->pm_fmod != 0) {
                    990:                if (pmp->pm_flags & MSDOSFSMNT_RONLY)
                    991:                        panic("msdosfs_sync: rofs mod");
                    992:                else {
                    993:                        /* update fats here */
                    994:                }
                    995:        }
1.56      ad        996:        /* Allocate a marker vnode. */
1.57      pooka     997:        if ((mvp = vnalloc(mp)) == NULL)
1.56      ad        998:                return ENOMEM;
1.1       jdolecek  999:        /*
                   1000:         * Write back each (modified) denode.
                   1001:         */
1.56      ad       1002:        mutex_enter(&mntvnode_lock);
1.1       jdolecek 1003: loop:
1.56      ad       1004:        for (vp = TAILQ_FIRST(&mp->mnt_vnodelist); vp; vp = vunmark(mvp)) {
                   1005:                vmark(mvp, vp);
                   1006:                if (vp->v_mount != mp || vismarker(vp))
                   1007:                        continue;
                   1008:                mutex_enter(&vp->v_interlock);
1.1       jdolecek 1009:                dep = VTODE(vp);
                   1010:                if (waitfor == MNT_LAZY || vp->v_type == VNON ||
                   1011:                    (((dep->de_flag &
                   1012:                    (DE_ACCESS | DE_CREATE | DE_UPDATE | DE_MODIFIED)) == 0) &&
                   1013:                     (LIST_EMPTY(&vp->v_dirtyblkhd) &&
1.48      pooka    1014:                      UVM_OBJ_IS_CLEAN(&vp->v_uobj)))) {
1.56      ad       1015:                        mutex_exit(&vp->v_interlock);
1.1       jdolecek 1016:                        continue;
                   1017:                }
1.56      ad       1018:                mutex_exit(&mntvnode_lock);
1.6       thorpej  1019:                error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK);
1.1       jdolecek 1020:                if (error) {
1.56      ad       1021:                        mutex_enter(&mntvnode_lock);
                   1022:                        if (error == ENOENT) {
                   1023:                                (void)vunmark(mvp);
1.1       jdolecek 1024:                                goto loop;
1.56      ad       1025:                        }
1.1       jdolecek 1026:                        continue;
                   1027:                }
                   1028:                if ((error = VOP_FSYNC(vp, cred,
1.54      pooka    1029:                    waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0)) != 0)
1.1       jdolecek 1030:                        allerror = error;
                   1031:                vput(vp);
1.56      ad       1032:                mutex_enter(&mntvnode_lock);
1.1       jdolecek 1033:        }
1.56      ad       1034:        mutex_exit(&mntvnode_lock);
1.57      pooka    1035:        vnfree(mvp);
1.56      ad       1036:
1.1       jdolecek 1037:        /*
                   1038:         * Force stale file system control information to be flushed.
                   1039:         */
                   1040:        if ((error = VOP_FSYNC(pmp->pm_devvp, cred,
1.54      pooka    1041:            waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0)) != 0)
1.1       jdolecek 1042:                allerror = error;
                   1043: #ifdef QUOTA
                   1044:        /* qsync(mp); */
                   1045: #endif
                   1046:        return (allerror);
                   1047: }
                   1048:
                   1049: int
1.6       thorpej  1050: msdosfs_fhtovp(mp, fhp, vpp)
1.1       jdolecek 1051:        struct mount *mp;
                   1052:        struct fid *fhp;
                   1053:        struct vnode **vpp;
                   1054: {
                   1055:        struct msdosfsmount *pmp = VFSTOMSDOSFS(mp);
1.32      martin   1056:        struct defid defh;
1.1       jdolecek 1057:        struct denode *dep;
                   1058:        int error;
                   1059:
1.42      christos 1060:        if (fhp->fid_len != sizeof(struct defid)) {
                   1061:                DPRINTF(("fid_len %d %zd\n", fhp->fid_len,
                   1062:                    sizeof(struct defid)));
1.32      martin   1063:                return EINVAL;
1.42      christos 1064:        }
1.32      martin   1065:
                   1066:        memcpy(&defh, fhp, sizeof(defh));
                   1067:        error = deget(pmp, defh.defid_dirclust, defh.defid_dirofs, &dep);
1.1       jdolecek 1068:        if (error) {
1.42      christos 1069:                DPRINTF(("deget %d\n", error));
1.1       jdolecek 1070:                *vpp = NULLVP;
                   1071:                return (error);
                   1072:        }
                   1073:        *vpp = DETOV(dep);
                   1074:        return (0);
                   1075: }
                   1076:
                   1077: int
1.32      martin   1078: msdosfs_vptofh(vp, fhp, fh_size)
1.1       jdolecek 1079:        struct vnode *vp;
                   1080:        struct fid *fhp;
1.32      martin   1081:        size_t *fh_size;
1.1       jdolecek 1082: {
                   1083:        struct denode *dep;
1.32      martin   1084:        struct defid defh;
1.1       jdolecek 1085:
1.32      martin   1086:        if (*fh_size < sizeof(struct defid)) {
                   1087:                *fh_size = sizeof(struct defid);
                   1088:                return E2BIG;
                   1089:        }
                   1090:        *fh_size = sizeof(struct defid);
1.1       jdolecek 1091:        dep = VTODE(vp);
1.32      martin   1092:        memset(&defh, 0, sizeof(defh));
                   1093:        defh.defid_len = sizeof(struct defid);
                   1094:        defh.defid_dirclust = dep->de_dirclust;
                   1095:        defh.defid_dirofs = dep->de_diroffset;
                   1096:        /* defh.defid_gen = dep->de_gen; */
                   1097:        memcpy(fhp, &defh, sizeof(defh));
1.1       jdolecek 1098:        return (0);
                   1099: }
                   1100:
                   1101: int
1.39      christos 1102: msdosfs_vget(struct mount *mp, ino_t ino,
                   1103:     struct vnode **vpp)
1.1       jdolecek 1104: {
                   1105:
                   1106:        return (EOPNOTSUPP);
                   1107: }

CVSweb <webmaster@jp.NetBSD.org>