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 
   66 static int mfs_minor;           /* used for building internal dev_t */
   67 
   68 extern vop_t **mfs_vnodeop_p;
   69 
   70 static int      mfs_mount __P((struct mount *mp,
   71                         char *path, caddr_t data, struct nameidata *ndp, 
   72                         struct proc *p));
   73 static int      mfs_start __P((struct mount *mp, int flags, struct proc *p));
   74 static int      mfs_statfs __P((struct mount *mp, struct statfs *sbp, 
   75                         struct proc *p));
   76 static int      mfs_init __P((struct vfsconf *));
   77 
   78 static struct cdevsw mfs_cdevsw = {
   79         /* open */      noopen,
   80         /* close */     noclose,
   81         /* read */      physread,
   82         /* write */     physwrite,
   83         /* ioctl */     noioctl,
   84         /* poll */      nopoll,
   85         /* mmap */      nommap,
   86         /* strategy */  nostrategy,
   87         /* name */      "MFS",
   88         /* maj */       253,
   89         /* dump */      nodump,
   90         /* psize */     nopsize,
   91         /* flags */     D_DISK,
   92         /* bmaj */      253,
   93 };
   94 
   95 /*
   96  * mfs vfs operations.
   97  */
   98 static struct vfsops mfs_vfsops = {
   99         mfs_mount,
  100         mfs_start,
  101         ffs_unmount,
  102         ufs_root,
  103         ufs_quotactl,
  104         mfs_statfs,
  105         ffs_sync,
  106         ffs_vget,
  107         ffs_fhtovp,
  108         ufs_check_export,
  109         ffs_vptofh,
  110         mfs_init,
  111         vfs_stduninit,
  112         vfs_stdextattrctl,
  113 };
  114 
  115 VFS_SET(mfs_vfsops, mfs, 0);
  116 
  117 
  118 /*
  119  * mfs_mount
  120  *
  121  * Called when mounting local physical media
  122  *
  123  * PARAMETERS:
  124  *              mountroot
  125  *                      mp      mount point structure
  126  *                      path    NULL (flag for root mount!!!)
  127  *                      data    <unused>
  128  *                      ndp     <unused>
  129  *                      p       process (user credentials check [statfs])
  130  *
  131  *              mount
  132  *                      mp      mount point structure
  133  *                      path    path to mount point
  134  *                      data    pointer to argument struct in user space
  135  *                      ndp     mount point namei() return (used for
  136  *                              credentials on reload), reused to look
  137  *                              up block device.
  138  *                      p       process (user credentials check)
  139  *
  140  * RETURNS:     0       Success
  141  *              !0      error number (errno.h)
  142  *
  143  * LOCK STATE:
  144  *
  145  *              ENTRY
  146  *                      mount point is locked
  147  *              EXIT
  148  *                      mount point is locked
  149  *
  150  * NOTES:
  151  *              A NULL path can be used for a flag since the mount
  152  *              system call will fail with EFAULT in copyinstr in
  153  *              namei() if it is a genuine NULL from the user.
  154  */
  155 /* ARGSUSED */
  156 static int
  157 mfs_mount(mp, path, data, ndp, p)
  158         register struct mount *mp;
  159         char *path;
  160         caddr_t data;
  161         struct nameidata *ndp;
  162         struct proc *p;
  163 {
  164         struct vnode *devvp;
  165         struct mfs_args args;
  166         struct ufsmount *ump;
  167         struct fs *fs;
  168         struct mfsnode *mfsp;
  169         size_t size;
  170         int flags, err;
  171         dev_t dev;
  172 
  173         /*
  174          * Use NULL path to flag a root mount
  175          */
  176         if( path == NULL) {
  177                 /*
  178                  ***
  179                  * Mounting root file system
  180                  ***
  181                  */
  182 
  183                 /* you lose */
  184                 panic("mfs_mount: mount MFS as root: not configured!");
  185         }
  186 
  187         /*
  188          ***
  189          * Mounting non-root file system or updating a file system
  190          ***
  191          */
  192 
  193         /* copy in user arguments*/
  194         if ((err = copyin(data, (caddr_t)&args, sizeof (struct mfs_args))) != 0)
  195                 goto error_1;
  196 
  197         /*
  198          * If updating, check whether changing from read-only to
  199          * read/write; if there is no device name, that's all we do.
  200          */
  201         if (mp->mnt_flag & MNT_UPDATE) {
  202                 /*
  203                  ********************
  204                  * UPDATE
  205                  ********************
  206                  */
  207                 ump = VFSTOUFS(mp);
  208                 fs = ump->um_fs;
  209                 if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) {
  210                         flags = WRITECLOSE;
  211                         if (mp->mnt_flag & MNT_FORCE)
  212                                 flags |= FORCECLOSE;
  213                         err = ffs_flushfiles(mp, flags, p);
  214                         if (err)
  215                                 goto error_1;
  216                 }
  217                 if (fs->fs_ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR))
  218                         fs->fs_ronly = 0;
  219                 /* if not updating name...*/
  220                 if (args.fspec == 0) {
  221                         /*
  222                          * Process export requests.  Jumping to "success"
  223                          * will return the vfs_export() error code. 
  224                          */
  225                         err = vfs_export(mp, &ump->um_export, &args.export);
  226                         goto success;
  227                 }
  228 
  229                 /* XXX MFS does not support name updating*/
  230                 goto success;
  231         }
  232         /*
  233          * Do the MALLOC before the getnewvnode since doing so afterward
  234          * might cause a bogus v_data pointer to get dereferenced
  235          * elsewhere if MALLOC should block.
  236          */
  237         MALLOC(mfsp, struct mfsnode *, sizeof *mfsp, M_MFSNODE, M_WAITOK);
  238 
  239         err = getnewvnode(VT_MFS, (struct mount *)0, mfs_vnodeop_p, &devvp);
  240         if (err) {
  241                 FREE(mfsp, M_MFSNODE);
  242                 goto error_1;
  243         }
  244         devvp->v_type = VBLK;
  245         dev = make_dev(&mfs_cdevsw, mfs_minor, 0, 0, 0, "MFS%d", mfs_minor);
  246         /* It is not clear that these will get initialized otherwise */
  247         dev->si_bsize_phys = DEV_BSIZE;
  248         dev->si_iosize_max = DFLTPHYS;
  249         addaliasu(devvp, makeudev(253, mfs_minor++));
  250         devvp->v_data = mfsp;
  251         mfsp->mfs_baseoff = args.base;
  252         mfsp->mfs_size = args.size;
  253         mfsp->mfs_vnode = devvp;
  254         mfsp->mfs_pid = p->p_pid;
  255         mfsp->mfs_active = 1;
  256         bufq_init(&mfsp->buf_queue);
  257 
  258         /*
  259          * Since this is a new mount, we want the names for
  260          * the device and the mount point copied in.  If an
  261          * error occurs,  the mountpoint is discarded by the
  262          * upper level code.
  263          */
  264         /* Save "last mounted on" info for mount point (NULL pad)*/
  265         copyinstr(      path,                           /* mount point*/
  266                         mp->mnt_stat.f_mntonname,       /* save area*/
  267                         MNAMELEN - 1,                   /* max size*/
  268                         &size);                         /* real size*/
  269         bzero( mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
  270 
  271         /* Save "mounted from" info for mount point (NULL pad)*/
  272         copyinstr(      args.fspec,                     /* device name*/
  273                         mp->mnt_stat.f_mntfromname,     /* save area*/
  274                         MNAMELEN - 1,                   /* max size*/
  275                         &size);                         /* real size*/
  276         bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
  277 
  278         if ((err = ffs_mountfs(devvp, mp, p, M_MFSNODE)) != 0) { 
  279                 mfsp->mfs_active = 0;
  280                 goto error_2;
  281         }
  282 
  283         /*
  284          * Initialize FS stat information in mount struct; uses both
  285          * mp->mnt_stat.f_mntonname and mp->mnt_stat.f_mntfromname
  286          *
  287          * This code is common to root and non-root mounts
  288          */
  289         (void) VFS_STATFS(mp, &mp->mnt_stat, p);
  290 
  291         goto success;
  292 
  293 error_2:        /* error with devvp held*/
  294 
  295         /* release devvp before failing*/
  296         vrele(devvp);
  297 
  298 error_1:        /* no state to back out*/
  299 
  300 success:
  301         return( err);
  302 }
  303 
  304 
  305 static int      mfs_pri = PWAIT | PCATCH;               /* XXX prob. temp */
  306 
  307 /*
  308  * Used to grab the process and keep it in the kernel to service
  309  * memory filesystem I/O requests.
  310  *
  311  * Loop servicing I/O requests.
  312  * Copy the requested data into or out of the memory filesystem
  313  * address space.
  314  */
  315 /* ARGSUSED */
  316 static int
  317 mfs_start(mp, flags, p)
  318         struct mount *mp;
  319         int flags;
  320         struct proc *p;
  321 {
  322         register struct vnode *vp = VFSTOUFS(mp)->um_devvp;
  323         register struct mfsnode *mfsp = VTOMFS(vp);
  324         register struct buf *bp;
  325         register int gotsig = 0, sig;
  326 
  327         /*
  328          * We must prevent the system from trying to swap
  329          * out or kill ( when swap space is low, see vm/pageout.c ) the
  330          * process.  A deadlock can occur if the process is swapped out,
  331          * and the system can loop trying to kill the unkillable ( while
  332          * references exist ) MFS process when swap space is low.
  333          */
  334         PHOLD(curproc);
  335 
  336         while (mfsp->mfs_active) {
  337                 int s;
  338 
  339                 s = splbio();
  340 
  341                 while ((bp = bufq_first(&mfsp->buf_queue)) != NULL) {
  342                         bufq_remove(&mfsp->buf_queue, bp);
  343                         splx(s);
  344                         mfs_doio(bp, mfsp);
  345                         wakeup((caddr_t)bp);
  346                         s = splbio();
  347                 }
  348 
  349                 splx(s);
  350 
  351                 /*
  352                  * If a non-ignored signal is received, try to unmount.
  353                  * If that fails, clear the signal (it has been "processed"),
  354                  * otherwise we will loop here, as tsleep will always return
  355                  * EINTR/ERESTART.
  356                  */
  357                 /*
  358                  * Note that dounmount() may fail if work was queued after
  359                  * we slept. We have to jump hoops here to make sure that we
  360                  * process any buffers after the sleep, before we dounmount()
  361                  */
  362                 if (gotsig) {
  363                         gotsig = 0;
  364                         if (dounmount(mp, 0, p) != 0) {
  365                                 sig = CURSIG(p);
  366                                 if (sig)
  367                                         SIGDELSET(p->p_siglist, sig);
  368                         }
  369                 }
  370                 else if (tsleep((caddr_t)vp, mfs_pri, "mfsidl", 0))
  371                         gotsig++;       /* try to unmount in next pass */
  372         }
  373         return (0);
  374 }
  375 
  376 /*
  377  * Get file system statistics.
  378  */
  379 static int
  380 mfs_statfs(mp, sbp, p)
  381         struct mount *mp;
  382         struct statfs *sbp;
  383         struct proc *p;
  384 {
  385         int error;
  386 
  387         error = ffs_statfs(mp, sbp, p);
  388         sbp->f_type = mp->mnt_vfc->vfc_typenum;
  389         return (error);
  390 }
  391 
  392 /*
  393  * Memory based filesystem initialization.
  394  */
  395 static int
  396 mfs_init(vfsp)
  397         struct vfsconf *vfsp;
  398 {
  399 
  400         cdevsw_add(&mfs_cdevsw);
  401         return (0);
  402 }
  403 

Cache object: 6daabc88cae3539b4a23018dee76a6dd


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