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_vnops.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, 1993
    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_vnops.c 8.11 (Berkeley) 5/22/95
   34  * $FreeBSD$
   35  */
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/kernel.h>
   40 #include <sys/proc.h>
   41 #include <sys/buf.h>
   42 #include <sys/vnode.h>
   43 #include <sys/malloc.h>
   44 #include <sys/sysproto.h>
   45 #include <sys/mman.h>
   46 #include <sys/conf.h>
   47 
   48 #include <ufs/mfs/mfsnode.h>
   49 #include <ufs/mfs/mfs_extern.h>
   50 
   51 static int      mfs_badop __P((struct vop_generic_args *));
   52 static int      mfs_bmap __P((struct vop_bmap_args *));
   53 static int      mfs_close __P((struct vop_close_args *));
   54 static int      mfs_fsync __P((struct vop_fsync_args *));
   55 static int      mfs_freeblks __P((struct vop_freeblks_args *));
   56 static int      mfs_inactive __P((struct vop_inactive_args *)); /* XXX */
   57 static int      mfs_open __P((struct vop_open_args *));
   58 static int      mfs_reclaim __P((struct vop_reclaim_args *)); /* XXX */
   59 static int      mfs_print __P((struct vop_print_args *)); /* XXX */
   60 static int      mfs_strategy __P((struct vop_strategy_args *)); /* XXX */
   61 static int      mfs_getpages __P((struct vop_getpages_args *)); /* XXX */
   62 /*
   63  * mfs vnode operations.
   64  */
   65 vop_t **mfs_vnodeop_p;
   66 static struct vnodeopv_entry_desc mfs_vnodeop_entries[] = {
   67         { &vop_default_desc,            (vop_t *) mfs_badop },
   68         { &vop_bmap_desc,               (vop_t *) mfs_bmap },
   69         { &vop_bwrite_desc,             (vop_t *) vop_defaultop },
   70         { &vop_close_desc,              (vop_t *) mfs_close },
   71         { &vop_createvobject_desc,      (vop_t *) vop_stdcreatevobject },
   72         { &vop_destroyvobject_desc,     (vop_t *) vop_stddestroyvobject },
   73         { &vop_freeblks_desc,           (vop_t *) mfs_freeblks },
   74         { &vop_fsync_desc,              (vop_t *) mfs_fsync },
   75         { &vop_getpages_desc,           (vop_t *) mfs_getpages },
   76         { &vop_getvobject_desc,         (vop_t *) vop_stdgetvobject },
   77         { &vop_inactive_desc,           (vop_t *) mfs_inactive },
   78         { &vop_ioctl_desc,              (vop_t *) vop_enotty },
   79         { &vop_islocked_desc,           (vop_t *) vop_defaultop },
   80         { &vop_lock_desc,               (vop_t *) vop_defaultop },
   81         { &vop_open_desc,               (vop_t *) mfs_open },
   82         { &vop_print_desc,              (vop_t *) mfs_print },
   83         { &vop_reclaim_desc,            (vop_t *) mfs_reclaim },
   84         { &vop_strategy_desc,           (vop_t *) mfs_strategy },
   85         { &vop_unlock_desc,             (vop_t *) vop_defaultop },
   86         { NULL, NULL }
   87 };
   88 static struct vnodeopv_desc mfs_vnodeop_opv_desc =
   89         { &mfs_vnodeop_p, mfs_vnodeop_entries };
   90 
   91 VNODEOP_SET(mfs_vnodeop_opv_desc);
   92 
   93 /*
   94  * Vnode Operations.
   95  *
   96  * Open called to allow memory filesystem to initialize and
   97  * validate before actual IO. Record our process identifier
   98  * so we can tell when we are doing I/O to ourself.
   99  */
  100 /* ARGSUSED */
  101 static int
  102 mfs_open(ap)
  103         struct vop_open_args /* {
  104                 struct vnode *a_vp;
  105                 int  a_mode;
  106                 struct ucred *a_cred;
  107                 struct proc *a_p;
  108         } */ *ap;
  109 {
  110 
  111         if (ap->a_vp->v_type != VBLK) {
  112                 panic("mfs_open not VBLK");
  113                 /* NOTREACHED */
  114         }
  115         return (0);
  116 }
  117 
  118 static int
  119 mfs_fsync(ap)
  120         struct vop_fsync_args *ap;
  121 {
  122 
  123         return (VOCALL(spec_vnodeop_p, VOFFSET(vop_fsync), ap));
  124 }
  125 
  126 /*
  127  * mfs_freeblks() - hook to allow us to free physical memory.
  128  *
  129  *      We implement the B_FREEBUF strategy.  We can't just madvise()
  130  *      here because we have to do it in the correct order vs other bio
  131  *      requests, so we queue it.
  132  *
  133  *      Note: geteblk() sets B_INVAL.  We leave it set to guarentee buffer
  134  *      throw-away on brelse()? XXX
  135  */
  136 
  137 static int
  138 mfs_freeblks(ap)
  139         struct vop_freeblks_args /* {   
  140                 struct vnode *a_vp;     
  141                 daddr_t a_addr;         
  142                 daddr_t a_length;       
  143         } */ *ap;
  144 {       
  145         struct buf *bp;
  146         struct vnode *vp;
  147 
  148         if (!vfinddev(ap->a_vp->v_rdev, VBLK, &vp) || vp->v_usecount == 0)
  149                 panic("mfs_freeblks: bad dev");
  150 
  151         bp = geteblk(ap->a_length);
  152         bp->b_flags |= B_FREEBUF | B_ASYNC;
  153         bp->b_dev = ap->a_vp->v_rdev;
  154         bp->b_blkno = ap->a_addr;
  155         bp->b_offset = dbtob(ap->a_addr);
  156         bp->b_bcount = ap->a_length;
  157         BUF_KERNPROC(bp);
  158         VOP_STRATEGY(vp, bp);
  159         return(0);
  160 }
  161 
  162 /*
  163  * Pass I/O requests to the memory filesystem process.
  164  */
  165 static int
  166 mfs_strategy(ap)
  167         struct vop_strategy_args /* {
  168                 struct vnode *a_vp;
  169                 struct buf *a_bp;
  170         } */ *ap;
  171 {
  172         register struct buf *bp = ap->a_bp;
  173         register struct mfsnode *mfsp;
  174         struct vnode *vp;
  175         struct proc *p = curproc;               /* XXX */
  176         int s;
  177 
  178         if (!vfinddev(bp->b_dev, VBLK, &vp) || vp->v_usecount == 0)
  179                 panic("mfs_strategy: bad dev");
  180         mfsp = VTOMFS(vp);
  181 
  182         /*
  183          * splbio required for queueing/dequeueing, in case of forwarded
  184          * BPs from bio interrupts (?).  It may not be necessary.
  185          */
  186 
  187         s = splbio();
  188 
  189         if (mfsp->mfs_pid == 0) {
  190                 /*
  191                  * mini-root.  Note: B_FREEBUF not supported at the moment,
  192                  * I'm not sure what kind of dataspace b_data is in.
  193                  */
  194                 caddr_t base;
  195 
  196                 base = mfsp->mfs_baseoff + (bp->b_blkno << DEV_BSHIFT);
  197                 if (bp->b_flags & B_FREEBUF)
  198                         ;
  199                 if (bp->b_flags & B_READ)
  200                         bcopy(base, bp->b_data, bp->b_bcount);
  201                 else
  202                         bcopy(bp->b_data, base, bp->b_bcount);
  203                 biodone(bp);
  204         } else if (mfsp->mfs_pid == p->p_pid) {
  205                 /*
  206                  * VOP to self
  207                  */
  208                 splx(s);
  209                 mfs_doio(bp, mfsp);
  210                 s = splbio();
  211         } else {
  212                 /*
  213                  * VOP from some other process, queue to MFS process and
  214                  * wake it up.
  215                  */
  216                 bufq_insert_tail(&mfsp->buf_queue, bp);
  217                 wakeup((caddr_t)vp);
  218         }
  219         splx(s);
  220         return (0);
  221 }
  222 
  223 /*
  224  * Memory file system I/O.
  225  *
  226  * Trivial on the HP since buffer has already been mapping into KVA space.
  227  *
  228  * Read and Write are handled with a simple copyin and copyout.    
  229  *
  230  * We also partially support VOP_FREEBLKS() via B_FREEBUF.  We can't implement
  231  * completely -- for example, on fragments or inode metadata, but we can
  232  * implement it for page-aligned requests.
  233  */
  234 void
  235 mfs_doio(bp, mfsp)
  236         register struct buf *bp;
  237         struct mfsnode *mfsp;
  238 {
  239         caddr_t base = mfsp->mfs_baseoff + (bp->b_blkno << DEV_BSHIFT);
  240 
  241         if (bp->b_flags & B_FREEBUF) {
  242                 /*
  243                  * Implement B_FREEBUF, which allows the filesystem to tell
  244                  * a block device when blocks are no longer needed (like when
  245                  * a file is deleted).  We use the hook to MADV_FREE the VM.
  246                  * This makes an MFS filesystem work as well or better then
  247                  * a sun-style swap-mounted filesystem.
  248                  */
  249                 int bytes = bp->b_bcount;
  250 
  251                 if ((vm_offset_t)base & PAGE_MASK) {
  252                         int n = PAGE_SIZE - ((vm_offset_t)base & PAGE_MASK);
  253                         bytes -= n;
  254                         base += n;
  255                 }
  256                 if (bytes > 0) {
  257                         struct madvise_args uap;
  258 
  259                         bytes &= ~PAGE_MASK;
  260                         if (bytes != 0) {
  261                                 bzero(&uap, sizeof(uap));
  262                                 uap.addr  = base;
  263                                 uap.len   = bytes;
  264                                 uap.behav = MADV_FREE;
  265                                 madvise(curproc, &uap);
  266                         }
  267                 }
  268                 bp->b_error = 0;
  269         } else if (bp->b_flags & B_READ) {
  270                 /*
  271                  * Read data from our 'memory' disk
  272                  */
  273                 bp->b_error = copyin(base, bp->b_data, bp->b_bcount);
  274         } else {
  275                 /*
  276                  * Write data to our 'memory' disk
  277                  */
  278                 bp->b_error = copyout(bp->b_data, base, bp->b_bcount);
  279         }
  280         if (bp->b_error)
  281                 bp->b_flags |= B_ERROR;
  282         biodone(bp);
  283 }
  284 
  285 /*
  286  * This is a noop, simply returning what one has been given.
  287  */
  288 static int
  289 mfs_bmap(ap)
  290         struct vop_bmap_args /* {
  291                 struct vnode *a_vp;
  292                 ufs_daddr_t  a_bn;
  293                 struct vnode **a_vpp;
  294                 ufs_daddr_t *a_bnp;
  295                 int *a_runp;
  296         } */ *ap;
  297 {
  298 
  299         if (ap->a_vpp != NULL)
  300                 *ap->a_vpp = ap->a_vp;
  301         if (ap->a_bnp != NULL)
  302                 *ap->a_bnp = ap->a_bn;
  303         if (ap->a_runp != NULL)
  304                 *ap->a_runp = 0;
  305         return (0);
  306 }
  307 
  308 /*
  309  * Memory filesystem close routine
  310  */
  311 /* ARGSUSED */
  312 static int
  313 mfs_close(ap)
  314         struct vop_close_args /* {
  315                 struct vnode *a_vp;
  316                 int  a_fflag;
  317                 struct ucred *a_cred;
  318                 struct proc *a_p;
  319         } */ *ap;
  320 {
  321         register struct vnode *vp = ap->a_vp;
  322         register struct mfsnode *mfsp = VTOMFS(vp);
  323         register struct buf *bp;
  324         int error;
  325 
  326         /*
  327          * Finish any pending I/O requests.
  328          */
  329         while ((bp = bufq_first(&mfsp->buf_queue)) != NULL) {
  330                 bufq_remove(&mfsp->buf_queue, bp);
  331                 mfs_doio(bp, mfsp);
  332                 wakeup((caddr_t)bp);
  333         }
  334         /*
  335          * On last close of a memory filesystem
  336          * we must invalidate any in core blocks, so that
  337          * we can, free up its vnode.
  338          */
  339         if ((error = vinvalbuf(vp, 1, ap->a_cred, ap->a_p, 0, 0)) != 0)
  340                 return (error);
  341         /*
  342          * There should be no way to have any more uses of this
  343          * vnode, so if we find any other uses, it is a panic.
  344          */
  345         if (vp->v_usecount > 1)
  346                 printf("mfs_close: ref count %d > 1\n", vp->v_usecount);
  347         if (vp->v_usecount > 1 || (bufq_first(&mfsp->buf_queue) != NULL))
  348                 panic("mfs_close");
  349         /*
  350          * Send a request to the filesystem server to exit.
  351          */
  352         mfsp->mfs_active = 0;
  353         wakeup((caddr_t)vp);
  354         return (0);
  355 }
  356 
  357 /*
  358  * Memory filesystem inactive routine
  359  */
  360 /* ARGSUSED */
  361 static int
  362 mfs_inactive(ap)
  363         struct vop_inactive_args /* {
  364                 struct vnode *a_vp;
  365                 struct proc *a_p;
  366         } */ *ap;
  367 {
  368         struct vnode *vp = ap->a_vp;
  369         struct mfsnode *mfsp = VTOMFS(vp);
  370 
  371         if (bufq_first(&mfsp->buf_queue) != NULL)
  372                 panic("mfs_inactive: not inactive (next buffer %p)",
  373                         bufq_first(&mfsp->buf_queue));
  374         VOP_UNLOCK(vp, 0, ap->a_p);
  375         return (0);
  376 }
  377 
  378 /*
  379  * Reclaim a memory filesystem devvp so that it can be reused.
  380  */
  381 static int
  382 mfs_reclaim(ap)
  383         struct vop_reclaim_args /* {
  384                 struct vnode *a_vp;
  385         } */ *ap;
  386 {
  387         register struct vnode *vp = ap->a_vp;
  388 
  389         FREE(vp->v_data, M_MFSNODE);
  390         vp->v_data = NULL;
  391         return (0);
  392 }
  393 
  394 /*
  395  * Print out the contents of an mfsnode.
  396  */
  397 static int
  398 mfs_print(ap)
  399         struct vop_print_args /* {
  400                 struct vnode *a_vp;
  401         } */ *ap;
  402 {
  403         register struct mfsnode *mfsp = VTOMFS(ap->a_vp);
  404 
  405         printf("tag VT_MFS, pid %ld, base %p, size %ld\n",
  406             (long)mfsp->mfs_pid, (void *)mfsp->mfs_baseoff, mfsp->mfs_size);
  407         return (0);
  408 }
  409 
  410 /*
  411  * Block device bad operation
  412  */
  413 static int
  414 mfs_badop(struct vop_generic_args *ap)
  415 {
  416         int i;
  417 
  418         printf("mfs_badop[%s]\n", ap->a_desc->vdesc_name);
  419         i = vop_defaultop(ap);
  420         printf("mfs_badop[%s] = %d\n", ap->a_desc->vdesc_name,i);
  421         return (i);
  422 }
  423 
  424 
  425 static int
  426 mfs_getpages(ap)
  427         struct vop_getpages_args *ap;
  428 {
  429 
  430         return (VOCALL(spec_vnodeop_p, VOFFSET(vop_getpages), ap));
  431 }

Cache object: 825c044d543ba588aa525e07b9f9fbf1


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