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/dev/vn/vn.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) 1988 University of Utah.
    3  * Copyright (c) 1990, 1993
    4  *      The Regents of the University of California.  All rights reserved.
    5  *
    6  * This code is derived from software contributed to Berkeley by
    7  * the Systems Programming Group of the University of Utah Computer
    8  * Science Department.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the University of
   21  *      California, Berkeley and its contributors.
   22  * 4. Neither the name of the University nor the names of its contributors
   23  *    may be used to endorse or promote products derived from this software
   24  *    without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   36  * SUCH DAMAGE.
   37  *
   38  * from: Utah Hdr: vn.c 1.13 94/04/02
   39  *
   40  *      from: @(#)vn.c  8.6 (Berkeley) 4/1/94
   41  * $FreeBSD$
   42  */
   43 
   44 /*
   45  * Vnode disk driver.
   46  *
   47  * Block/character interface to a vnode.  Allows one to treat a file
   48  * as a disk (e.g. build a filesystem in it, mount it, etc.).
   49  *
   50  * NOTE 1: This uses the VOP_BMAP/VOP_STRATEGY interface to the vnode
   51  * instead of a simple VOP_RDWR.  We do this to avoid distorting the
   52  * local buffer cache.
   53  *
   54  * NOTE 2: There is a security issue involved with this driver.
   55  * Once mounted all access to the contents of the "mapped" file via
   56  * the special file is controlled by the permissions on the special
   57  * file, the protection of the mapped file is ignored (effectively,
   58  * by using root credentials in all transactions).
   59  *
   60  * NOTE 3: Doesn't interact with leases, should it?
   61  */
   62 #include "vn.h"
   63 #if NVN > 0
   64 
   65 /* default is to have 8 VN's */
   66 #if NVN < 8
   67 #undef NVN
   68 #define NVN     8
   69 #endif
   70 
   71 #include "opt_devfs.h"
   72 
   73 #include <sys/param.h>
   74 #include <sys/systm.h>
   75 #include <sys/kernel.h>
   76 #include <sys/namei.h>
   77 #include <sys/proc.h>
   78 #include <sys/buf.h>
   79 #include <sys/malloc.h>
   80 #include <sys/mount.h>
   81 #include <sys/vnode.h>
   82 #include <sys/fcntl.h>
   83 #include <sys/disklabel.h>
   84 #include <sys/diskslice.h>
   85 #include <sys/stat.h>
   86 #include <sys/conf.h>
   87 #ifdef DEVFS
   88 #include <sys/devfsext.h>
   89 #endif /*DEVFS*/
   90 #include <miscfs/specfs/specdev.h>
   91 #include <sys/vnioctl.h>
   92 
   93 static  d_ioctl_t       vnioctl;
   94 static  d_open_t        vnopen;
   95 static  d_read_t        vnread;
   96 static  d_write_t       vnwrite;
   97 static  d_close_t       vnclose;
   98 static  d_dump_t        vndump;
   99 static  d_psize_t       vnsize;
  100 static  d_strategy_t    vnstrategy;
  101 
  102 #define CDEV_MAJOR 43
  103 #define BDEV_MAJOR 15
  104 
  105 
  106 static struct cdevsw vn_cdevsw = {
  107           vnopen,       vnclose,        vnread,         vnwrite,
  108           vnioctl,      nostop,         nullreset,      nodevtotty,
  109           seltrue,      nommap,         vnstrategy,     "vn",
  110           NULL,         -1,             vndump,         vnsize,
  111           D_DISK|D_NOCLUSTERRW, 0,      -1 };
  112 
  113 
  114 #define vnunit(dev)     dkunit(dev)
  115 
  116 #define getvnbuf()      \
  117         ((struct buf *)malloc(sizeof(struct buf), M_DEVBUF, M_WAITOK))
  118 
  119 #define putvnbuf(bp)    \
  120         free((caddr_t)(bp), M_DEVBUF)
  121 
  122 struct vn_softc {
  123         int              sc_flags;      /* flags */
  124         size_t           sc_size;       /* size of vn */
  125         struct diskslices *sc_slices;
  126         struct vnode    *sc_vp;         /* vnode */
  127         struct ucred    *sc_cred;       /* credentials */
  128         int              sc_maxactive;  /* max # of active requests */
  129         struct buf       sc_tab;        /* transfer queue */
  130         u_long           sc_options;    /* options */
  131 #ifdef DEVFS
  132         void            *r_devfs_token;
  133         void            *devfs_token;
  134 #endif
  135 };
  136 
  137 /* sc_flags */
  138 #define VNF_INITED      0x01
  139 
  140 static struct vn_softc *vn_softc[NVN];
  141 static u_long   vn_options;
  142 
  143 #define IFOPT(vn,opt) if (((vn)->sc_options|vn_options) & (opt))
  144 
  145 static void     vniodone (struct buf *bp);
  146 static int      vnsetcred (struct vn_softc *vn, struct ucred *cred);
  147 static void     vnshutdown (int, void *);
  148 static void     vnclear (struct vn_softc *vn);
  149 
  150 static  int
  151 vnclose(dev_t dev, int flags, int mode, struct proc *p)
  152 {
  153         struct vn_softc *vn = vn_softc[vnunit(dev)];
  154 
  155         IFOPT(vn, VN_LABELS)
  156                 if (vn->sc_slices != NULL)
  157                         dsclose(dev, mode, vn->sc_slices);
  158         return (0);
  159 }
  160 
  161 static  int
  162 vnopen(dev_t dev, int flags, int mode, struct proc *p)
  163 {
  164         int unit = vnunit(dev);
  165         struct vn_softc *vn;
  166 
  167         if (unit >= NVN) {
  168                 if (vn_options & VN_FOLLOW)
  169                         printf("vnopen(0x%lx, 0x%x, 0x%x, %p)\n",
  170                             (u_long)dev, flags, mode, (void *)p);
  171                 return(ENOENT);
  172         }
  173 
  174         vn = vn_softc[unit];
  175         if (!vn) {
  176                 vn = malloc(sizeof *vn, M_DEVBUF, M_WAITOK);
  177                 if (!vn)
  178                         return (ENOMEM);
  179                 bzero(vn, sizeof *vn);
  180                 vn_softc[unit] = vn;
  181         }
  182 
  183         IFOPT(vn, VN_FOLLOW)
  184                 printf("vnopen(0x%lx, 0x%x, 0x%x, %p)\n",
  185                     (u_long)dev, flags, mode, (void *)p);
  186 
  187         IFOPT(vn, VN_LABELS) {
  188                 if (vn->sc_flags & VNF_INITED) {
  189                         struct disklabel label;
  190 
  191                         /* Build label for whole disk. */
  192                         bzero(&label, sizeof label);
  193                         label.d_secsize = DEV_BSIZE;
  194                         label.d_nsectors = 32;
  195                         label.d_ntracks = 64;
  196                         label.d_ncylinders = vn->sc_size / (32 * 64);
  197                         label.d_secpercyl = 32 * 64;
  198                         label.d_secperunit =
  199                                         label.d_partitions[RAW_PART].p_size =
  200                                         vn->sc_size;
  201 
  202                         return (dsopen("vn", dev, mode, 0, &vn->sc_slices,
  203                                        &label, vnstrategy, (ds_setgeom_t *)NULL,
  204                                        &vn_cdevsw));
  205                 }
  206                 if (dkslice(dev) != WHOLE_DISK_SLICE ||
  207                     dkpart(dev) != RAW_PART ||
  208                     mode != S_IFCHR)
  209                         return (ENXIO);
  210         }
  211         return(0);
  212 }
  213 
  214 static int
  215 vnread(dev_t dev, struct uio *uio, int ioflag)
  216 {
  217         return (physio(vnstrategy, NULL, dev, 1, minphys, uio));
  218 }
  219 
  220 static int
  221 vnwrite(dev_t dev, struct uio *uio, int ioflag)
  222 {
  223         return (physio(vnstrategy, NULL, dev, 0, minphys, uio));
  224 }
  225 
  226 /*
  227  * this code does I/O calls through the appropriate VOP entry point...
  228  * unless a swap_pager I/O request is being done.  This strategy (-))
  229  * allows for coherency with mmap except in the case of paging.  This
  230  * is necessary, because the VOP calls use lots of memory (and actually
  231  * are not extremely efficient -- but we want to keep semantics correct),
  232  * and the pageout daemon gets really unhappy (and so does the rest of the
  233  * system) when it runs out of memory.
  234  */
  235 static  void
  236 vnstrategy(struct buf *bp)
  237 {
  238         int unit = vnunit(bp->b_dev);
  239         register struct vn_softc *vn = vn_softc[unit];
  240         register daddr_t bn;
  241         int error;
  242         int isvplocked = 0;
  243         long sz;
  244         struct uio auio;
  245         struct iovec aiov;
  246 
  247         IFOPT(vn, VN_DEBUG)
  248                 printf("vnstrategy(%p): unit %d\n", bp, unit);
  249 
  250         if ((vn->sc_flags & VNF_INITED) == 0) {
  251                 bp->b_error = ENXIO;
  252                 bp->b_flags |= B_ERROR;
  253                 biodone(bp);
  254                 return;
  255         }
  256         IFOPT(vn, VN_LABELS) {
  257                 bp->b_resid = bp->b_bcount;/* XXX best place to set this? */
  258                 if (vn->sc_slices != NULL && dscheck(bp, vn->sc_slices) <= 0) {
  259                         biodone(bp);
  260                         return;
  261                 }
  262                 bn = bp->b_pblkno;
  263                 bp->b_resid = bp->b_bcount;/* XXX best place to set this? */
  264         } else {
  265                 bn = bp->b_blkno;
  266                 sz = howmany(bp->b_bcount, DEV_BSIZE);
  267                 bp->b_resid = bp->b_bcount;
  268                 if (bn < 0 || bn + sz > vn->sc_size) {
  269                         if (bn != vn->sc_size) {
  270                                 bp->b_error = EINVAL;
  271                                 bp->b_flags |= B_ERROR;
  272                         }
  273                         biodone(bp);
  274                         return;
  275                 }
  276         }
  277 
  278         if( (bp->b_flags & B_PAGING) == 0) {
  279                 aiov.iov_base = bp->b_data;
  280                 aiov.iov_len = bp->b_bcount;
  281                 auio.uio_iov = &aiov;
  282                 auio.uio_iovcnt = 1;
  283                 auio.uio_offset = dbtob(bn);
  284                 auio.uio_segflg = UIO_SYSSPACE;
  285                 if( bp->b_flags & B_READ)
  286                         auio.uio_rw = UIO_READ;
  287                 else
  288                         auio.uio_rw = UIO_WRITE;
  289                 auio.uio_resid = bp->b_bcount;
  290                 auio.uio_procp = curproc;
  291                 if (!VOP_ISLOCKED(vn->sc_vp)) {
  292                         isvplocked = 1;
  293                         vn_lock(vn->sc_vp, LK_EXCLUSIVE | LK_RETRY, curproc);
  294                 }
  295                 if( bp->b_flags & B_READ)
  296                         error = VOP_READ(vn->sc_vp, &auio, 0, vn->sc_cred);
  297                 else
  298                         error = VOP_WRITE(vn->sc_vp, &auio, 0, vn->sc_cred);
  299                 if (isvplocked) {
  300                         VOP_UNLOCK(vn->sc_vp, 0, curproc);
  301                         isvplocked = 0;
  302                 }
  303                 bp->b_resid = auio.uio_resid;
  304 
  305                 if( error )
  306                         bp->b_flags |= B_ERROR;
  307                 biodone(bp);
  308         } else {
  309                 long bsize, resid;
  310                 off_t byten;
  311                 int flags;
  312                 caddr_t addr;
  313                 struct buf *nbp;
  314 
  315                 nbp = getvnbuf();
  316                 bzero(nbp, sizeof(struct buf));
  317                 LIST_INIT(&nbp->b_dep);
  318                 byten = dbtob(bn);
  319                 bsize = vn->sc_vp->v_mount->mnt_stat.f_iosize;
  320                 addr = bp->b_data;
  321                 flags = bp->b_flags | B_CALL;
  322                 for (resid = bp->b_resid; resid; ) {
  323                         struct vnode *vp;
  324                         daddr_t nbn;
  325                         int off, s, nra;
  326 
  327                         nra = 0;
  328                         if (!VOP_ISLOCKED(vn->sc_vp)) {
  329                                 isvplocked = 1;
  330                                 vn_lock(vn->sc_vp, LK_EXCLUSIVE | LK_RETRY, curproc);
  331                         }
  332                         error = VOP_BMAP(vn->sc_vp, (daddr_t)(byten / bsize),
  333                                          &vp, &nbn, &nra, NULL);
  334                         if (isvplocked) {
  335                                 VOP_UNLOCK(vn->sc_vp, 0, curproc);
  336                                 isvplocked = 0;
  337                         }
  338                         if (error == 0 && nbn == -1)
  339                                 error = EIO;
  340 
  341                         IFOPT(vn, VN_DONTCLUSTER)
  342                                 nra = 0;
  343 
  344                         off = byten % bsize;
  345                         if (off)
  346                                 sz = bsize - off;
  347                         else
  348                                 sz = (1 + nra) * bsize;
  349                         if (resid < sz)
  350                                 sz = resid;
  351 
  352                         if (error) {
  353                                 bp->b_resid -= (resid - sz);
  354                                 bp->b_flags |= B_ERROR;
  355                                 biodone(bp);
  356                                 putvnbuf(nbp);
  357                                 return;
  358                         }
  359 
  360                         IFOPT(vn,VN_IO)
  361                                 printf(
  362                         /* XXX no %qx in kernel.  Synthesize it. */
  363                         "vnstrategy: vp %p/%p bn 0x%lx%08lx/0x%lx sz 0x%lx\n",
  364                                    (void *)vn->sc_vp, (void *)vp,
  365                                    (u_long)(byten >> 32), (u_long)byten,
  366                                    (u_long)nbn, sz);
  367 
  368                         nbp->b_flags = flags;
  369                         nbp->b_bcount = sz;
  370                         nbp->b_bufsize = sz;
  371                         nbp->b_error = 0;
  372                         if (vp->v_type == VBLK || vp->v_type == VCHR)
  373                                 nbp->b_dev = vp->v_rdev;
  374                         else
  375                                 nbp->b_dev = NODEV;
  376                         nbp->b_data = addr;
  377                         nbp->b_blkno = nbn + btodb(off);
  378                         nbp->b_offset = dbtob(nbn) + off;
  379                         nbp->b_proc = bp->b_proc;
  380                         nbp->b_iodone = vniodone;
  381                         nbp->b_vp = vp;
  382                         nbp->b_rcred = vn->sc_cred;     /* XXX crdup? */
  383                         nbp->b_wcred = vn->sc_cred;     /* XXX crdup? */
  384                         nbp->b_dirtyoff = bp->b_dirtyoff;
  385                         nbp->b_dirtyend = bp->b_dirtyend;
  386                         nbp->b_validoff = bp->b_validoff;
  387                         nbp->b_validend = bp->b_validend;
  388 
  389                         if ((nbp->b_flags & B_READ) == 0)
  390                                 nbp->b_vp->v_numoutput++;
  391 
  392                         VOP_STRATEGY(vp, nbp);
  393 
  394                         s = splbio();
  395                         while ((nbp->b_flags & B_DONE) == 0) {
  396                                 nbp->b_flags |= B_WANTED;
  397                                 tsleep(nbp, PRIBIO, "vnwait", 0);
  398                         }
  399                         splx(s);
  400 
  401                         if( nbp->b_flags & B_ERROR) {
  402                                 bp->b_flags |= B_ERROR;
  403                                 bp->b_resid -= (resid - sz);
  404                                 biodone(bp);
  405                                 putvnbuf(nbp);
  406                                 return;
  407                         }
  408 
  409                         byten += sz;
  410                         addr += sz;
  411                         resid -= sz;
  412                 }
  413                 bp->b_resid = resid;
  414                 biodone(bp);
  415                 putvnbuf(nbp);
  416         }
  417 }
  418 
  419 
  420 void
  421 vniodone( struct buf *bp) {
  422         bp->b_flags |= B_DONE;
  423         wakeup((caddr_t) bp);
  424 }
  425 
  426 /* ARGSUSED */
  427 static  int
  428 vnioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
  429 {
  430         struct vn_softc *vn = vn_softc[vnunit(dev)];
  431         struct vn_ioctl *vio;
  432         struct vattr vattr;
  433         struct nameidata nd;
  434         int error;
  435         u_long *f;
  436 
  437         IFOPT(vn,VN_FOLLOW)
  438                 printf("vnioctl(0x%lx, 0x%lx, %p, 0x%x, %p): unit %d\n",
  439                    (u_long)dev, cmd, (void *)data, flag, (void *)p,
  440                    vnunit(dev));
  441 
  442         switch (cmd) {
  443         case VNIOCATTACH:
  444         case VNIOCDETACH:
  445         case VNIOCGSET:
  446         case VNIOCGCLEAR:
  447         case VNIOCUSET:
  448         case VNIOCUCLEAR:
  449                 goto vn_specific;
  450         }
  451 
  452         IFOPT(vn,VN_LABELS) {
  453                 if (vn->sc_slices != NULL) {
  454                         error = dsioctl("vn", dev, cmd, data, flag,
  455                                         &vn->sc_slices, vnstrategy,
  456                                         (ds_setgeom_t *)NULL);
  457                         if (error != ENOIOCTL)
  458                                 return (error);
  459                 }
  460                 if (dkslice(dev) != WHOLE_DISK_SLICE ||
  461                     dkpart(dev) != RAW_PART)
  462                         return (ENOTTY);
  463         }
  464 
  465     vn_specific:
  466 
  467         error = suser(p->p_ucred, &p->p_acflag);
  468         if (error)
  469                 return (error);
  470 
  471         vio = (struct vn_ioctl *)data;
  472         f = (u_long*)data;
  473         switch (cmd) {
  474 
  475         case VNIOCATTACH:
  476                 if (vn->sc_flags & VNF_INITED)
  477                         return(EBUSY);
  478                 /*
  479                  * Always open for read and write.
  480                  * This is probably bogus, but it lets vn_open()
  481                  * weed out directories, sockets, etc. so we don't
  482                  * have to worry about them.
  483                  */
  484                 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, vio->vn_file, p);
  485                 error = vn_open(&nd, FREAD|FWRITE, 0);
  486                 if (error)
  487                         return(error);
  488                 error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p);
  489                 if (error) {
  490                         VOP_UNLOCK(nd.ni_vp, 0, p);
  491                         (void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p);
  492                         return(error);
  493                 }
  494                 VOP_UNLOCK(nd.ni_vp, 0, p);
  495                 vn->sc_vp = nd.ni_vp;
  496                 vn->sc_size = btodb(vattr.va_size);     /* note truncation */
  497                 error = vnsetcred(vn, p->p_ucred);
  498                 if (error) {
  499                         (void) vn_close(nd.ni_vp, FREAD|FWRITE, p->p_ucred, p);
  500                         return(error);
  501                 }
  502                 vio->vn_size = dbtob(vn->sc_size);
  503                 vn->sc_flags |= VNF_INITED;
  504                 IFOPT(vn, VN_LABELS) {
  505                         /*
  506                          * Reopen so that `ds' knows which devices are open.
  507                          * If this is the first VNIOCSET, then we've
  508                          * guaranteed that the device is the cdev and that
  509                          * no other slices or labels are open.  Otherwise,
  510                          * we rely on VNIOCCLR not being abused.
  511                          */
  512                         error = vnopen(dev, flag, S_IFCHR, p);
  513                         if (error)
  514                                 vnclear(vn);
  515                 }
  516                 IFOPT(vn, VN_FOLLOW)
  517                         printf("vnioctl: SET vp %p size %x\n",
  518                                vn->sc_vp, vn->sc_size);
  519                 break;
  520 
  521         case VNIOCDETACH:
  522                 if ((vn->sc_flags & VNF_INITED) == 0)
  523                         return(ENXIO);
  524                 /*
  525                  * XXX handle i/o in progress.  Return EBUSY, or wait, or
  526                  * flush the i/o.
  527                  * XXX handle multiple opens of the device.  Return EBUSY,
  528                  * or revoke the fd's.
  529                  * How are these problems handled for removable and failing
  530                  * hardware devices?
  531                  */
  532                 vnclear(vn);
  533                 IFOPT(vn, VN_FOLLOW)
  534                         printf("vnioctl: CLRed\n");
  535                 break;
  536 
  537         case VNIOCGSET:
  538                 vn_options |= *f;
  539                 *f = vn_options;
  540                 break;
  541 
  542         case VNIOCGCLEAR:
  543                 vn_options &= ~(*f);
  544                 *f = vn_options;
  545                 break;
  546 
  547         case VNIOCUSET:
  548                 vn->sc_options |= *f;
  549                 *f = vn->sc_options;
  550                 break;
  551 
  552         case VNIOCUCLEAR:
  553                 vn->sc_options &= ~(*f);
  554                 *f = vn->sc_options;
  555                 break;
  556 
  557         default:
  558                 return (ENOTTY);
  559         }
  560         return(0);
  561 }
  562 
  563 /*
  564  * Duplicate the current processes' credentials.  Since we are called only
  565  * as the result of a SET ioctl and only root can do that, any future access
  566  * to this "disk" is essentially as root.  Note that credentials may change
  567  * if some other uid can write directly to the mapped file (NFS).
  568  */
  569 int
  570 vnsetcred(struct vn_softc *vn, struct ucred *cred)
  571 {
  572         struct uio auio;
  573         struct iovec aiov;
  574         char *tmpbuf;
  575         int error;
  576 
  577         vn->sc_cred = crdup(cred);
  578         tmpbuf = malloc(DEV_BSIZE, M_TEMP, M_WAITOK);
  579 
  580         /* XXX: Horrible kludge to establish credentials for NFS */
  581         aiov.iov_base = tmpbuf;
  582         aiov.iov_len = min(DEV_BSIZE, dbtob(vn->sc_size));
  583         auio.uio_iov = &aiov;
  584         auio.uio_iovcnt = 1;
  585         auio.uio_offset = 0;
  586         auio.uio_rw = UIO_READ;
  587         auio.uio_segflg = UIO_SYSSPACE;
  588         auio.uio_resid = aiov.iov_len;
  589         vn_lock(vn->sc_vp, LK_EXCLUSIVE | LK_RETRY, curproc);
  590         error = VOP_READ(vn->sc_vp, &auio, 0, vn->sc_cred);
  591         VOP_UNLOCK(vn->sc_vp, 0, curproc);
  592 
  593         free(tmpbuf, M_TEMP);
  594         return (error);
  595 }
  596 
  597 void
  598 vnshutdown(int howto, void *ignored)
  599 {
  600         int i;
  601 
  602         for (i = 0; i < NVN; i++)
  603                 if (vn_softc[i] && vn_softc[i]->sc_flags & VNF_INITED)
  604                         vnclear(vn_softc[i]);
  605 }
  606 
  607 void
  608 vnclear(struct vn_softc *vn)
  609 {
  610         register struct vnode *vp = vn->sc_vp;
  611         struct proc *p = curproc;               /* XXX */
  612 
  613         IFOPT(vn, VN_FOLLOW)
  614                 printf("vnclear(%p): vp=%p\n", vn, vp);
  615         if (vn->sc_slices != NULL)
  616                 dsgone(&vn->sc_slices);
  617         vn->sc_flags &= ~VNF_INITED;
  618         if (vp == (struct vnode *)0)
  619                 panic("vnclear: null vp");
  620         (void) vn_close(vp, FREAD|FWRITE, vn->sc_cred, p);
  621         crfree(vn->sc_cred);
  622         vn->sc_vp = (struct vnode *)0;
  623         vn->sc_cred = (struct ucred *)0;
  624         vn->sc_size = 0;
  625 }
  626 
  627 static  int
  628 vnsize(dev_t dev)
  629 {
  630         int unit = vnunit(dev);
  631 
  632         if (unit >= NVN || (!vn_softc[unit]) ||
  633             (vn_softc[unit]->sc_flags & VNF_INITED) == 0)
  634                 return(-1);
  635         return(vn_softc[unit]->sc_size);
  636 }
  637 
  638 static  int
  639 vndump(dev_t dev)
  640 {
  641         return (ENODEV);
  642 }
  643 
  644 static vn_devsw_installed = 0;
  645 
  646 static void 
  647 vn_drvinit(void *unused)
  648 {
  649 #ifdef DEVFS
  650         int unit;
  651 #endif
  652         if(!vn_devsw_installed ) {
  653                 if (at_shutdown(&vnshutdown, NULL, SHUTDOWN_POST_SYNC)) {
  654                         printf("vn: could not install shutdown hook\n");
  655                         return;
  656                 }
  657                 cdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &vn_cdevsw);
  658                 vn_devsw_installed = 1;
  659         }
  660 #ifdef DEVFS
  661         for (unit = 0; unit < NVN; unit++) {
  662                 struct vn_softc *vn;
  663 
  664                 vn = malloc(sizeof *vn, M_DEVBUF, M_NOWAIT);
  665                 if (!vn)
  666                         return;
  667                 bzero(vn, sizeof *vn);
  668                 vn_softc[unit] = vn;
  669                 vn->r_devfs_token = devfs_add_devswf(&vn_cdevsw, 
  670                                                      dkmakeminor(unit, 0, 0),
  671                                                      DV_CHR, UID_ROOT, 
  672                                                      GID_OPERATOR, 0640,
  673                                                      "rvn%d", unit);
  674                 vn->devfs_token = devfs_add_devswf(&vn_cdevsw,
  675                                                    dkmakeminor(unit, 0, 0),
  676                                                    DV_BLK, UID_ROOT, 
  677                                                    GID_OPERATOR, 0640,
  678                                                    "vn%d", unit);
  679         }
  680 #endif
  681 }
  682 
  683 SYSINIT(vndev, SI_SUB_DRIVERS, SI_ORDER_ANY, vn_drvinit, NULL)
  684 
  685 #endif

Cache object: f9a178ec4910d01ac91e9e1b225b6a94


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