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 /*
    2  * Copyright (c) 1989, 1990, 1993, 1994
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by the University of
   16  *      California, Berkeley and its contributors.
   17  * 4. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  *      @(#)mfs_vfsops.c        8.11 (Berkeley) 6/19/95
   34  * $FreeBSD$
   35  */
   36 
   37 
   38 #include "opt_mfs.h"
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/conf.h>
   43 #include <sys/kernel.h>
   44 #include <sys/proc.h>
   45 #include <sys/buf.h>
   46 #include <sys/mount.h>
   47 #include <sys/signalvar.h>
   48 #include <sys/vnode.h>
   49 #include <sys/malloc.h>
   50 #include <sys/linker.h>
   51 
   52 #include <ufs/ufs/quota.h>
   53 #include <ufs/ufs/inode.h>
   54 #include <ufs/ufs/ufsmount.h>
   55 #include <ufs/ufs/ufs_extern.h>
   56 
   57 #include <ufs/ffs/fs.h>
   58 #include <ufs/ffs/ffs_extern.h>
   59 
   60 #include <ufs/mfs/mfsnode.h>
   61 #include <ufs/mfs/mfs_extern.h>
   62 
   63 MALLOC_DEFINE(M_MFSNODE, "MFS node", "MFS vnode private part");
   64 
   65 u_char *        mfs_getimage __P((void));
   66 
   67 static caddr_t  mfs_rootbase;   /* address of mini-root in kernel virtual memory */
   68 static u_long   mfs_rootsize;   /* size of mini-root in bytes */
   69 
   70 static  int mfs_minor;  /* used for building internal dev_t */
   71 
   72 extern vop_t **mfs_vnodeop_p;
   73 
   74 static int      mfs_mount __P((struct mount *mp,
   75                         char *path, caddr_t data, struct nameidata *ndp, 
   76                         struct proc *p));
   77 static int      mfs_start __P((struct mount *mp, int flags, struct proc *p));
   78 static int      mfs_statfs __P((struct mount *mp, struct statfs *sbp, 
   79                         struct proc *p));
   80 static int      mfs_init __P((struct vfsconf *));
   81 
   82 /*
   83  * mfs vfs operations.
   84  */
   85 static struct vfsops mfs_vfsops = {
   86         mfs_mount,
   87         mfs_start,
   88         ffs_unmount,
   89         ufs_root,
   90         ufs_quotactl,
   91         mfs_statfs,
   92         ffs_sync,
   93         ffs_vget,
   94         ffs_fhtovp,
   95         ffs_vptofh,
   96         mfs_init,
   97 };
   98 
   99 VFS_SET(mfs_vfsops, mfs, 0);
  100 
  101 #ifdef MFS_ROOT
  102 
  103 #ifdef MFS_ROOT_SIZE
  104 /* Image was already written into mfs_root */
  105 static u_char mfs_root[MFS_ROOT_SIZE*1024] = "MFS Filesystem goes here";
  106 static u_char end_mfs_root[] __unused = "MFS Filesystem had better STOP here";
  107 #endif
  108 
  109 u_char *
  110 mfs_getimage(void)
  111 {
  112 #ifdef MFS_ROOT_SIZE
  113         /* Get it from compiled-in code */
  114         return mfs_root;
  115 #else
  116         caddr_t p;
  117         vm_offset_t *q;
  118 
  119         p = preload_search_by_type("mfs_root");
  120         if (!p)
  121                 return NULL;
  122         q = (vm_offset_t *)preload_search_info(p, MODINFO_ADDR);
  123         if (!q)
  124                 return NULL;
  125         return (u_char *)*q;
  126 #endif
  127 }
  128 
  129 #endif  /* MFS_ROOT */
  130 
  131 /*
  132  * mfs_mount
  133  *
  134  * Called when mounting local physical media
  135  *
  136  * PARAMETERS:
  137  *              mountroot
  138  *                      mp      mount point structure
  139  *                      path    NULL (flag for root mount!!!)
  140  *                      data    <unused>
  141  *                      ndp     <unused>
  142  *                      p       process (user credentials check [statfs])
  143  *
  144  *              mount
  145  *                      mp      mount point structure
  146  *                      path    path to mount point
  147  *                      data    pointer to argument struct in user space
  148  *                      ndp     mount point namei() return (used for
  149  *                              credentials on reload), reused to look
  150  *                              up block device.
  151  *                      p       process (user credentials check)
  152  *
  153  * RETURNS:     0       Success
  154  *              !0      error number (errno.h)
  155  *
  156  * LOCK STATE:
  157  *
  158  *              ENTRY
  159  *                      mount point is locked
  160  *              EXIT
  161  *                      mount point is locked
  162  *
  163  * NOTES:
  164  *              A NULL path can be used for a flag since the mount
  165  *              system call will fail with EFAULT in copyinstr in
  166  *              namei() if it is a genuine NULL from the user.
  167  */
  168 /* ARGSUSED */
  169 static int
  170 mfs_mount(mp, path, data, ndp, p)
  171         register struct mount *mp;
  172         char *path;
  173         caddr_t data;
  174         struct nameidata *ndp;
  175         struct proc *p;
  176 {
  177         struct vnode *devvp;
  178         struct mfs_args args;
  179         struct ufsmount *ump;
  180         struct fs *fs;
  181         u_char *base;
  182         struct mfsnode *mfsp;
  183         u_int size;
  184         int flags, err;
  185 
  186         /*
  187          * Use NULL path to flag a root mount
  188          */
  189         if( path == NULL) {
  190                 /*
  191                  ***
  192                  * Mounting root file system
  193                  ***
  194                  */
  195 
  196 #ifdef MFS_ROOT
  197                 /* Get it from preload area */
  198                 base = mfs_getimage();
  199                 if (!base)
  200                     panic("No mfs_root image loaded; can't continue!");
  201                 fs = (struct fs *)(base + SBOFF);
  202                 /* check for valid super block */
  203                 if (fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE ||
  204                     fs->fs_bsize < sizeof(struct fs)) {
  205                         panic("MFS image is invalid!!");
  206                 }
  207 
  208                 mfs_rootbase = base;
  209                 mfs_rootsize = fs->fs_fsize * fs->fs_size;
  210                 rootdev = makedev(255, mfs_minor++);
  211                 printf("rootfs is %ld Kbyte compiled in MFS\n",
  212                        mfs_rootsize/1024);
  213                 if ((err = bdevvp(rootdev, &rootvp))) {
  214                         printf("mfs_mountroot: can't find rootvp");
  215                         return (err);
  216                 }
  217 
  218                 /*
  219                  * FS specific handling
  220                  */
  221                 MALLOC(mfsp, struct mfsnode *, sizeof *mfsp, M_MFSNODE, M_WAITOK);
  222                 rootvp->v_data = mfsp;
  223                 rootvp->v_op = mfs_vnodeop_p;
  224                 rootvp->v_tag = VT_MFS;
  225                 mfsp->mfs_baseoff = mfs_rootbase;
  226                 mfsp->mfs_size = mfs_rootsize;
  227                 mfsp->mfs_vnode = rootvp;
  228                 mfsp->mfs_pid = p->p_pid;
  229                 mfsp->mfs_active = 1;
  230                 bufq_init(&mfsp->buf_queue);
  231 
  232                 /* MFS wants to be read/write */
  233                 mp->mnt_flag &= ~MNT_RDONLY;
  234 
  235                 /*
  236                  * Attempt mount
  237                  */
  238                 if( (err = ffs_mountfs(rootvp, mp, p, M_MFSNODE)) != 0 ) {
  239                         /* fs specific cleanup (if any)*/
  240                         rootvp->v_data = NULL;
  241                         FREE(mfsp, M_MFSNODE);
  242                         goto error_1;
  243                 }
  244 
  245                 goto dostatfs;          /* success*/
  246 #else   /* !MFS_ROOT */
  247                 /* you loose */
  248                 panic("mfs_mount: mount MFS as root: not configured!");
  249 #endif /* MFS_ROOT */
  250         }
  251 
  252         /*
  253          ***
  254          * Mounting non-root file system or updating a file system
  255          ***
  256          */
  257 
  258         /* copy in user arguments*/
  259         if (err = copyin(data, (caddr_t)&args, sizeof (struct mfs_args)))
  260                 goto error_1;
  261 
  262         /*
  263          * If updating, check whether changing from read-only to
  264          * read/write; if there is no device name, that's all we do.
  265          */
  266         if (mp->mnt_flag & MNT_UPDATE) {
  267                 /*
  268                  ********************
  269                  * UPDATE
  270                  ********************
  271                  */
  272                 ump = VFSTOUFS(mp);
  273                 fs = ump->um_fs;
  274                 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
  275                         flags = WRITECLOSE;
  276                         if (mp->mnt_flag & MNT_FORCE)
  277                                 flags |= FORCECLOSE;
  278                         err = ffs_flushfiles(mp, flags, p);
  279                         if (err)
  280                                 goto error_1;
  281                 }
  282                 if (fs->fs_ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR))
  283                         fs->fs_ronly = 0;
  284 #ifdef EXPORTMFS
  285                 /* if not updating name...*/
  286                 if (args.fspec == 0) {
  287                         /*
  288                          * Process export requests.  Jumping to "success"
  289                          * will return the vfs_export() error code. 
  290                          */
  291                         err = vfs_export(mp, &ump->um_export, &args.export);
  292                         goto success;
  293                 }
  294 #endif
  295 
  296                 /* XXX MFS does not support name updating*/
  297                 goto success;
  298         }
  299         /*
  300          * Do the MALLOC before the getnewvnode since doing so afterward
  301          * might cause a bogus v_data pointer to get dereferenced
  302          * elsewhere if MALLOC should block.
  303          */
  304         MALLOC(mfsp, struct mfsnode *, sizeof *mfsp, M_MFSNODE, M_WAITOK);
  305 
  306         err = getnewvnode(VT_MFS, (struct mount *)0, mfs_vnodeop_p, &devvp);
  307         if (err) {
  308                 FREE(mfsp, M_MFSNODE);
  309                 goto error_1;
  310         }
  311         devvp->v_type = VBLK;
  312         if (checkalias(devvp, makedev(255, mfs_minor++), (struct mount *)0))
  313                 panic("mfs_mount: dup dev");
  314         devvp->v_data = mfsp;
  315         mfsp->mfs_baseoff = args.base;
  316         mfsp->mfs_size = args.size;
  317         mfsp->mfs_vnode = devvp;
  318         mfsp->mfs_pid = p->p_pid;
  319         mfsp->mfs_active = 1;
  320         bufq_init(&mfsp->buf_queue);
  321 
  322         /*
  323          * Since this is a new mount, we want the names for
  324          * the device and the mount point copied in.  If an
  325          * error occurs,  the mountpoint is discarded by the
  326          * upper level code.
  327          */
  328         /* Save "last mounted on" info for mount point (NULL pad)*/
  329         copyinstr(      path,                           /* mount point*/
  330                         mp->mnt_stat.f_mntonname,       /* save area*/
  331                         MNAMELEN - 1,                   /* max size*/
  332                         &size);                         /* real size*/
  333         bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
  334 
  335         /* Save "mounted from" info for mount point (NULL pad)*/
  336         copyinstr(      args.fspec,                     /* device name*/
  337                         mp->mnt_stat.f_mntfromname,     /* save area*/
  338                         MNAMELEN - 1,                   /* max size*/
  339                         &size);                         /* real size*/
  340         bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
  341 
  342         if (err = ffs_mountfs(devvp, mp, p, M_MFSNODE)) {
  343                 mfsp->mfs_active = 0;
  344                 goto error_2;
  345         }
  346 
  347 dostatfs:
  348         /*
  349          * Initialize FS stat information in mount struct; uses both
  350          * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
  351          *
  352          * This code is common to root and non-root mounts
  353          */
  354         (void) VFS_STATFS(mp, &mp->mnt_stat, p);
  355 
  356         goto success;
  357 
  358 error_2:        /* error with devvp held*/
  359 
  360         /* release devvp before failing*/
  361         vrele(devvp);
  362 
  363 error_1:        /* no state to back out*/
  364 
  365 success:
  366         return( err);
  367 }
  368 
  369 
  370 static int      mfs_pri = PWAIT | PCATCH;               /* XXX prob. temp */
  371 
  372 /*
  373  * Used to grab the process and keep it in the kernel to service
  374  * memory filesystem I/O requests.
  375  *
  376  * Loop servicing I/O requests.
  377  * Copy the requested data into or out of the memory filesystem
  378  * address space.
  379  */
  380 /* ARGSUSED */
  381 static int
  382 mfs_start(mp, flags, p)
  383         struct mount *mp;
  384         int flags;
  385         struct proc *p;
  386 {
  387         register struct vnode *vp = VFSTOUFS(mp)->um_devvp;
  388         register struct mfsnode *mfsp = VTOMFS(vp);
  389         register struct buf *bp;
  390         register caddr_t base;
  391         register int gotsig = 0;
  392 
  393         base = mfsp->mfs_baseoff;
  394 
  395         /*
  396          * We must set P_NOSWAP to prevent the system from trying to swap
  397          * out or kill ( when swap space is low, see vm/pageout.c ) the
  398          * process.  A deadlock can occur if the process is swapped out,
  399          * and the system can loop trying to kill the unkillable ( while
  400          * references exist ) MFS process when swap space is low.
  401          */
  402         curproc->p_flag |= P_NOSWAP;
  403 
  404         while (mfsp->mfs_active) {
  405                 int     s;
  406 
  407                 s = splbio();
  408                 while (bp = bufq_first(&mfsp->buf_queue)) {
  409                         bufq_remove(&mfsp->buf_queue, bp);
  410                         splx(s);
  411                         mfs_doio(bp, base);
  412                         wakeup((caddr_t)bp);
  413                         s = splbio();
  414                 }
  415                 splx(s);
  416 
  417                 /*
  418                  * If a non-ignored signal is received, try to unmount.
  419                  * If that fails, clear the signal (it has been "processed"),
  420                  * otherwise we will loop here, as tsleep will always return
  421                  * EINTR/ERESTART.
  422                  */
  423                 /*
  424                  * Note that dounmount() may fail if work was queued after
  425                  * we slept. We have to jump hoops here to make sure that we
  426                  * process any buffers after the sleep, before we dounmount()
  427                  */
  428                 if (gotsig) {
  429                         gotsig = 0;
  430                         if (dounmount(mp, 0, p) != 0)
  431                                 CLRSIG(p, CURSIG(p));   /* try sleep again.. */
  432                 }
  433                 else if (tsleep((caddr_t)vp, mfs_pri, "mfsidl", 0))
  434                         gotsig++;       /* try to unmount in next pass */
  435         }
  436         return (0);
  437 }
  438 
  439 /*
  440  * Get file system statistics.
  441  */
  442 static int
  443 mfs_statfs(mp, sbp, p)
  444         struct mount *mp;
  445         struct statfs *sbp;
  446         struct proc *p;
  447 {
  448         int error;
  449 
  450         error = ffs_statfs(mp, sbp, p);
  451         sbp->f_type = mp->mnt_vfc->vfc_typenum;
  452         return (error);
  453 }
  454 
  455 /*
  456  * Memory based filesystem initialization.
  457  */
  458 static int
  459 mfs_init(vfsp)
  460         struct vfsconf *vfsp;
  461 {
  462         return (0);
  463 }

Cache object: f4d0ca6af33611987ba2bea84414149d


[ 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.