The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ufs/mfs/mfs_vfsops.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: mfs_vfsops.c,v 1.55.2.1 2004/05/29 09:04:53 tron Exp $ */
    2 
    3 /*
    4  * Copyright (c) 1989, 1990, 1993, 1994
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  *      @(#)mfs_vfsops.c        8.11 (Berkeley) 6/19/95
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __KERNEL_RCSID(0, "$NetBSD: mfs_vfsops.c,v 1.55.2.1 2004/05/29 09:04:53 tron Exp $");
   36 
   37 #if defined(_KERNEL_OPT)
   38 #include "opt_compat_netbsd.h"
   39 #endif
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/sysctl.h>
   44 #include <sys/time.h>
   45 #include <sys/kernel.h>
   46 #include <sys/proc.h>
   47 #include <sys/buf.h>
   48 #include <sys/mount.h>
   49 #include <sys/signalvar.h>
   50 #include <sys/vnode.h>
   51 #include <sys/malloc.h>
   52 
   53 #include <miscfs/syncfs/syncfs.h>
   54 
   55 #include <ufs/ufs/quota.h>
   56 #include <ufs/ufs/inode.h>
   57 #include <ufs/ufs/ufsmount.h>
   58 #include <ufs/ufs/ufs_extern.h>
   59 
   60 #include <ufs/ffs/fs.h>
   61 #include <ufs/ffs/ffs_extern.h>
   62 
   63 #include <ufs/mfs/mfsnode.h>
   64 #include <ufs/mfs/mfs_extern.h>
   65 
   66 caddr_t mfs_rootbase;   /* address of mini-root in kernel virtual memory */
   67 u_long  mfs_rootsize;   /* size of mini-root in bytes */
   68 
   69 static  int mfs_minor;  /* used for building internal dev_t */
   70 
   71 extern int (**mfs_vnodeop_p) __P((void *));
   72 
   73 MALLOC_DEFINE(M_MFSNODE, "MFS node", "MFS vnode private part");
   74 
   75 /*
   76  * mfs vfs operations.
   77  */
   78 
   79 extern const struct vnodeopv_desc mfs_vnodeop_opv_desc;  
   80 
   81 const struct vnodeopv_desc * const mfs_vnodeopv_descs[] = {
   82         &mfs_vnodeop_opv_desc,
   83         NULL,
   84 };
   85 
   86 struct vfsops mfs_vfsops = {
   87         MOUNT_MFS,
   88         mfs_mount,
   89         mfs_start,
   90         ffs_unmount,
   91         ufs_root,
   92         ufs_quotactl,
   93         mfs_statfs,
   94         ffs_sync,
   95         ffs_vget,
   96         ffs_fhtovp,
   97         ffs_vptofh,
   98         mfs_init,
   99         mfs_reinit,
  100         mfs_done,
  101         NULL,
  102         NULL,
  103         ufs_check_export,
  104         mfs_vnodeopv_descs,
  105 };
  106 
  107 SYSCTL_SETUP(sysctl_vfs_mfs_setup, "sysctl vfs.mfs subtree setup")
  108 {
  109 
  110         sysctl_createv(clog, 0, NULL, NULL,
  111                        CTLFLAG_PERMANENT,
  112                        CTLTYPE_NODE, "vfs", NULL,
  113                        NULL, 0, NULL, 0,
  114                        CTL_VFS, CTL_EOL);
  115         sysctl_createv(clog, 0, NULL, NULL,
  116                        CTLFLAG_PERMANENT|CTLFLAG_ALIAS,
  117                        CTLTYPE_NODE, "mfs",
  118                        SYSCTL_DESCR("Memory based file system"),
  119                        NULL, 1, NULL, 0,
  120                        CTL_VFS, 3, CTL_EOL);
  121         /*
  122          * XXX the "1" and the "3" above could be dynamic, thereby
  123          * eliminating one more instance of the "number to vfs"
  124          * mapping problem, but they are in order as taken from
  125          * sys/mount.h
  126          */
  127 }
  128 
  129 /* 
  130  * Memory based filesystem initialization.
  131  */ 
  132 void
  133 mfs_init()
  134 {
  135 #ifdef _LKM
  136         malloc_type_attach(M_MFSNODE);
  137 #endif
  138         /*
  139          * ffs_init() ensures to initialize necessary resources
  140          * only once.
  141          */
  142         ffs_init();
  143 }
  144 
  145 void
  146 mfs_reinit()
  147 {
  148         ffs_reinit();
  149 }
  150 
  151 void
  152 mfs_done()
  153 {
  154         /*
  155          * ffs_done() ensures to free necessary resources
  156          * only once, when it's no more needed.
  157          */
  158         ffs_done();
  159 #ifdef _LKM
  160         malloc_type_detach(M_MFSNODE);
  161 #endif
  162 }
  163 
  164 /*
  165  * Called by main() when mfs is going to be mounted as root.
  166  */
  167 
  168 int
  169 mfs_mountroot()
  170 {
  171         struct fs *fs;
  172         struct mount *mp;
  173         struct proc *p = curproc;       /* XXX */
  174         struct ufsmount *ump;
  175         struct mfsnode *mfsp;
  176         int error = 0;
  177 
  178         /*
  179          * Get vnodes for rootdev.
  180          */
  181         if (bdevvp(rootdev, &rootvp)) {
  182                 printf("mfs_mountroot: can't setup bdevvp's");
  183                 return (error);
  184         }
  185 
  186         if ((error = vfs_rootmountalloc(MOUNT_MFS, "mfs_root", &mp))) {
  187                 vrele(rootvp);
  188                 return (error);
  189         }
  190 
  191         mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK);
  192         rootvp->v_data = mfsp;
  193         rootvp->v_op = mfs_vnodeop_p;
  194         rootvp->v_tag = VT_MFS;
  195         mfsp->mfs_baseoff = mfs_rootbase;
  196         mfsp->mfs_size = mfs_rootsize;
  197         mfsp->mfs_vnode = rootvp;
  198         mfsp->mfs_proc = NULL;          /* indicate kernel space */
  199         mfsp->mfs_shutdown = 0;
  200         bufq_alloc(&mfsp->mfs_buflist, BUFQ_FCFS);
  201         if ((error = ffs_mountfs(rootvp, mp, p)) != 0) {
  202                 mp->mnt_op->vfs_refcount--;
  203                 vfs_unbusy(mp);
  204                 bufq_free(&mfsp->mfs_buflist);
  205                 free(mp, M_MOUNT);
  206                 free(mfsp, M_MFSNODE);
  207                 vrele(rootvp);
  208                 return (error);
  209         }       
  210         simple_lock(&mountlist_slock);
  211         CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
  212         simple_unlock(&mountlist_slock);
  213         mp->mnt_vnodecovered = NULLVP;
  214         ump = VFSTOUFS(mp);
  215         fs = ump->um_fs;
  216         (void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
  217         (void)ffs_statfs(mp, &mp->mnt_stat, p);
  218         vfs_unbusy(mp);
  219         inittodr((time_t)0);
  220         return (0);
  221 }
  222 
  223 /*
  224  * This is called early in boot to set the base address and size
  225  * of the mini-root.
  226  */
  227 int
  228 mfs_initminiroot(base)
  229         caddr_t base;
  230 {
  231         struct fs *fs = (struct fs *)(base + SBLOCK_UFS1);
  232 
  233         /* check for valid super block */
  234         if (fs->fs_magic != FS_UFS1_MAGIC || fs->fs_bsize > MAXBSIZE ||
  235             fs->fs_bsize < sizeof(struct fs))
  236                 return (0);
  237         mountroot = mfs_mountroot;
  238         mfs_rootbase = base;
  239         mfs_rootsize = fs->fs_fsize * fs->fs_size;
  240         rootdev = makedev(255, mfs_minor);
  241         mfs_minor++;
  242         return (mfs_rootsize);
  243 }
  244 
  245 /*
  246  * VFS Operations.
  247  *
  248  * mount system call
  249  */
  250 /* ARGSUSED */
  251 int
  252 mfs_mount(mp, path, data, ndp, p)
  253         struct mount *mp;
  254         const char *path;
  255         void *data;
  256         struct nameidata *ndp;
  257         struct proc *p;
  258 {
  259         struct vnode *devvp;
  260         struct mfs_args args;
  261         struct ufsmount *ump;
  262         struct fs *fs;
  263         struct mfsnode *mfsp;
  264         int flags, error;
  265 
  266         if (mp->mnt_flag & MNT_GETARGS) {
  267                 struct vnode *vp;
  268                 struct mfsnode *mfsp;
  269 
  270                 ump = VFSTOUFS(mp);
  271                 if (ump == NULL)
  272                         return EIO;
  273 
  274                 vp = ump->um_devvp;
  275                 if (vp == NULL)
  276                         return EIO;
  277 
  278                 mfsp = VTOMFS(vp);
  279                 if (mfsp == NULL)
  280                         return EIO;
  281 
  282                 args.fspec = NULL;
  283                 vfs_showexport(mp, &args.export, &ump->um_export);
  284                 args.base = mfsp->mfs_baseoff;
  285                 args.size = mfsp->mfs_size;
  286                 return copyout(&args, data, sizeof(args));
  287         }
  288         /*
  289          * XXX turn off async to avoid hangs when writing lots of data.
  290          * the problem is that MFS needs to allocate pages to clean pages,
  291          * so if we wait until the last minute to clean pages then there
  292          * may not be any pages available to do the cleaning.
  293          * ... and since the default partially-synchronous mode turns out
  294          * to not be sufficient under heavy load, make it full synchronous.
  295          */
  296         mp->mnt_flag &= ~MNT_ASYNC;
  297         mp->mnt_flag |= MNT_SYNCHRONOUS;
  298 
  299         error = copyin(data, (caddr_t)&args, sizeof (struct mfs_args));
  300         if (error)
  301                 return (error);
  302 
  303         /*
  304          * If updating, check whether changing from read-only to
  305          * read/write; if there is no device name, that's all we do.
  306          */
  307         if (mp->mnt_flag & MNT_UPDATE) {
  308                 ump = VFSTOUFS(mp);
  309                 fs = ump->um_fs;
  310                 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
  311                         flags = WRITECLOSE;
  312                         if (mp->mnt_flag & MNT_FORCE)
  313                                 flags |= FORCECLOSE;
  314                         error = ffs_flushfiles(mp, flags, p);
  315                         if (error)
  316                                 return (error);
  317                 }
  318                 if (fs->fs_ronly && (mp->mnt_iflag & IMNT_WANTRDWR))
  319                         fs->fs_ronly = 0;
  320                 if (args.fspec == 0)
  321                         return (vfs_export(mp, &ump->um_export, &args.export));
  322                 return (0);
  323         }
  324         error = getnewvnode(VT_MFS, (struct mount *)0, mfs_vnodeop_p, &devvp);
  325         if (error)
  326                 return (error);
  327         devvp->v_type = VBLK;
  328         if (checkalias(devvp, makedev(255, mfs_minor), (struct mount *)0))
  329                 panic("mfs_mount: dup dev");
  330         mfs_minor++;
  331         mfsp = (struct mfsnode *)malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK);
  332         devvp->v_data = mfsp;
  333         mfsp->mfs_baseoff = args.base;
  334         mfsp->mfs_size = args.size;
  335         mfsp->mfs_vnode = devvp;
  336         mfsp->mfs_proc = p;
  337         mfsp->mfs_shutdown = 0;
  338         bufq_alloc(&mfsp->mfs_buflist, BUFQ_FCFS);
  339         if ((error = ffs_mountfs(devvp, mp, p)) != 0) {
  340                 mfsp->mfs_shutdown = 1;
  341                 vrele(devvp);
  342                 return (error);
  343         }
  344         ump = VFSTOUFS(mp);
  345         fs = ump->um_fs;
  346         error = set_statfs_info(path, UIO_USERSPACE, args.fspec,
  347             UIO_USERSPACE, mp, p);
  348         (void)memcpy(fs->fs_fsmnt, mp->mnt_stat.f_mntonname,
  349             sizeof(mp->mnt_stat.f_mntonname));
  350         return error;
  351 }
  352 
  353 int     mfs_pri = PWAIT | PCATCH;               /* XXX prob. temp */
  354 
  355 /*
  356  * Used to grab the process and keep it in the kernel to service
  357  * memory filesystem I/O requests.
  358  *
  359  * Loop servicing I/O requests.
  360  * Copy the requested data into or out of the memory filesystem
  361  * address space.
  362  */
  363 /* ARGSUSED */
  364 int
  365 mfs_start(mp, flags, p)
  366         struct mount *mp;
  367         int flags;
  368         struct proc *p;
  369 {
  370         struct vnode *vp = VFSTOUFS(mp)->um_devvp;
  371         struct mfsnode *mfsp = VTOMFS(vp);
  372         struct buf *bp;
  373         caddr_t base;
  374         int sleepreturn = 0;
  375         struct lwp *l; /* XXX NJWLWP */
  376 
  377         /* XXX NJWLWP the vnode interface again gives us a proc in a
  378          * place where we want a execution context. Cheat.
  379          */
  380         KASSERT(curproc == p);
  381         l = curlwp; 
  382         base = mfsp->mfs_baseoff;
  383         while (mfsp->mfs_shutdown != 1) {
  384                 while ((bp = BUFQ_GET(&mfsp->mfs_buflist)) != NULL) {
  385                         mfs_doio(bp, base);
  386                         wakeup((caddr_t)bp);
  387                 }
  388                 /*
  389                  * If a non-ignored signal is received, try to unmount.
  390                  * If that fails, or the filesystem is already in the
  391                  * process of being unmounted, clear the signal (it has been
  392                  * "processed"), otherwise we will loop here, as tsleep
  393                  * will always return EINTR/ERESTART.
  394                  */
  395                 if (sleepreturn != 0) {
  396                         /*
  397                          * XXX Freeze syncer.  Must do this before locking
  398                          * the mount point.  See dounmount() for details.
  399                          */
  400                         lockmgr(&syncer_lock, LK_EXCLUSIVE, NULL);
  401                         if (vfs_busy(mp, LK_NOWAIT, 0) != 0)
  402                                 lockmgr(&syncer_lock, LK_RELEASE, NULL);
  403                         else if (dounmount(mp, 0, p) != 0)
  404                                 CLRSIG(p, CURSIG(l));
  405                         sleepreturn = 0;
  406                         continue;
  407                 }
  408 
  409                 sleepreturn = tsleep(vp, mfs_pri, "mfsidl", 0);
  410         }
  411         KASSERT(BUFQ_PEEK(&mfsp->mfs_buflist) == NULL);
  412         bufq_free(&mfsp->mfs_buflist);
  413         return (sleepreturn);
  414 }
  415 
  416 /*
  417  * Get file system statistics.
  418  */
  419 int
  420 mfs_statfs(mp, sbp, p)
  421         struct mount *mp;
  422         struct statfs *sbp;
  423         struct proc *p;
  424 {
  425         int error;
  426 
  427         error = ffs_statfs(mp, sbp, p);
  428 #ifdef COMPAT_09
  429         sbp->f_type = 3;
  430 #else
  431         sbp->f_type = 0;
  432 #endif
  433         strncpy(&sbp->f_fstypename[0], mp->mnt_op->vfs_name, MFSNAMELEN);
  434         return (error);
  435 }

Cache object: 6bf1f0993624bec103eae40fbd1c2b14


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.