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/fs/devfs/devfs_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) 2000-2004
    3  *      Poul-Henning Kamp.  All rights reserved.
    4  * Copyright (c) 1989, 1992-1993, 1995
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software donated to Berkeley by
    8  * Jan-Simon Pendry.
    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. 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  *      @(#)kernfs_vnops.c      8.15 (Berkeley) 5/21/95
   32  * From: FreeBSD: src/sys/miscfs/kernfs/kernfs_vnops.c 1.43
   33  *
   34  * $FreeBSD$
   35  */
   36 
   37 /*
   38  * TODO:
   39  *      remove empty directories
   40  *      mkdir: want it ?
   41  */
   42 
   43 #include "opt_mac.h"
   44 
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 #include <sys/conf.h>
   48 #include <sys/dirent.h>
   49 #include <sys/fcntl.h>
   50 #include <sys/file.h>
   51 #include <sys/filedesc.h>
   52 #include <sys/filio.h>
   53 #include <sys/kernel.h>
   54 #include <sys/lock.h>
   55 #include <sys/malloc.h>
   56 #include <sys/mount.h>
   57 #include <sys/namei.h>
   58 #include <sys/priv.h>
   59 #include <sys/proc.h>
   60 #include <sys/stat.h>
   61 #include <sys/sx.h>
   62 #include <sys/time.h>
   63 #include <sys/ttycom.h>
   64 #include <sys/unistd.h>
   65 #include <sys/vnode.h>
   66 
   67 static struct vop_vector devfs_vnodeops;
   68 static struct vop_vector devfs_specops;
   69 static struct fileops devfs_ops_f;
   70 
   71 #include <fs/devfs/devfs.h>
   72 #include <fs/devfs/devfs_int.h>
   73 
   74 #include <security/mac/mac_framework.h>
   75 
   76 struct mtx      devfs_de_interlock;
   77 MTX_SYSINIT(devfs_de_interlock, &devfs_de_interlock, "devfs interlock", MTX_DEF);
   78 struct sx       clone_drain_lock;
   79 SX_SYSINIT(clone_drain_lock, &clone_drain_lock, "clone events drain lock");
   80 
   81 static int
   82 devfs_fp_check(struct file *fp, struct cdev **devp, struct cdevsw **dswp)
   83 {
   84 
   85         *dswp = devvn_refthread(fp->f_vnode, devp);
   86         if (*devp != fp->f_data) {
   87                 if (*dswp != NULL)
   88                         dev_relthread(*devp);
   89                 return (ENXIO);
   90         }
   91         KASSERT((*devp)->si_refcount > 0,
   92             ("devfs: un-referenced struct cdev *(%s)", devtoname(*devp)));
   93         if (*dswp == NULL)
   94                 return (ENXIO);
   95         return (0);
   96 }
   97 
   98 /*
   99  * Construct the fully qualified path name relative to the mountpoint
  100  */
  101 static char *
  102 devfs_fqpn(char *buf, struct vnode *dvp, struct componentname *cnp)
  103 {
  104         int i;
  105         struct devfs_dirent *de, *dd;
  106         struct devfs_mount *dmp;
  107 
  108         dmp = VFSTODEVFS(dvp->v_mount);
  109         dd = dvp->v_data;
  110         i = SPECNAMELEN;
  111         buf[i] = '\0';
  112         i -= cnp->cn_namelen;
  113         if (i < 0)
  114                  return (NULL);
  115         bcopy(cnp->cn_nameptr, buf + i, cnp->cn_namelen);
  116         de = dd;
  117         while (de != dmp->dm_rootdir) {
  118                 i--;
  119                 if (i < 0)
  120                          return (NULL);
  121                 buf[i] = '/';
  122                 i -= de->de_dirent->d_namlen;
  123                 if (i < 0)
  124                          return (NULL);
  125                 bcopy(de->de_dirent->d_name, buf + i,
  126                     de->de_dirent->d_namlen);
  127                 de = TAILQ_FIRST(&de->de_dlist);        /* "." */
  128                 de = TAILQ_NEXT(de, de_list);           /* ".." */
  129                 de = de->de_dir;
  130         }
  131         return (buf + i);
  132 }
  133 
  134 static int
  135 devfs_allocv_drop_refs(int drop_dm_lock, struct devfs_mount *dmp,
  136         struct devfs_dirent *de)
  137 {
  138         int not_found;
  139 
  140         not_found = 0;
  141         if (de->de_flags & DE_DOOMED)
  142                 not_found = 1;
  143         if (DEVFS_DE_DROP(de)) {
  144                 KASSERT(not_found == 1, ("DEVFS de dropped but not doomed"));
  145                 devfs_dirent_free(de);
  146         }
  147         if (DEVFS_DMP_DROP(dmp)) {
  148                 KASSERT(not_found == 1,
  149                         ("DEVFS mount struct freed before dirent"));
  150                 not_found = 2;
  151                 sx_xunlock(&dmp->dm_lock);
  152                 devfs_unmount_final(dmp);
  153         }
  154         if (not_found == 1 || (drop_dm_lock && not_found != 2))
  155                 sx_unlock(&dmp->dm_lock);
  156         return (not_found);
  157 }
  158 
  159 static void
  160 devfs_insmntque_dtr(struct vnode *vp, void *arg)
  161 {
  162         struct devfs_dirent *de;
  163 
  164         de = (struct devfs_dirent *)arg;
  165         mtx_lock(&devfs_de_interlock);
  166         vp->v_data = NULL;
  167         de->de_vnode = NULL;
  168         mtx_unlock(&devfs_de_interlock);
  169         vgone(vp);
  170         vput(vp);
  171 }
  172 
  173 /*
  174  * devfs_allocv shall be entered with dmp->dm_lock held, and it drops
  175  * it on return.
  176  */
  177 int
  178 devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, struct thread *td)
  179 {
  180         int error;
  181         struct vnode *vp;
  182         struct cdev *dev;
  183         struct devfs_mount *dmp;
  184 
  185         KASSERT(td == curthread, ("devfs_allocv: td != curthread"));
  186         dmp = VFSTODEVFS(mp);
  187         if (de->de_flags & DE_DOOMED) {
  188                 sx_xunlock(&dmp->dm_lock);
  189                 return (ENOENT);
  190         }
  191  loop:
  192         DEVFS_DE_HOLD(de);
  193         DEVFS_DMP_HOLD(dmp);
  194         mtx_lock(&devfs_de_interlock);
  195         vp = de->de_vnode;
  196         if (vp != NULL) {
  197                 VI_LOCK(vp);
  198                 mtx_unlock(&devfs_de_interlock);
  199                 sx_xunlock(&dmp->dm_lock);
  200                 error = vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td);
  201                 sx_xlock(&dmp->dm_lock);
  202                 if (devfs_allocv_drop_refs(0, dmp, de)) {
  203                         if (error == 0)
  204                                 vput(vp);
  205                         return (ENOENT);
  206                 }
  207                 else if (error)
  208                         goto loop;
  209                 sx_xunlock(&dmp->dm_lock);
  210                 *vpp = vp;
  211                 return (0);
  212         }
  213         mtx_unlock(&devfs_de_interlock);
  214         if (de->de_dirent->d_type == DT_CHR) {
  215                 if (!(de->de_cdp->cdp_flags & CDP_ACTIVE)) {
  216                         devfs_allocv_drop_refs(1, dmp, de);
  217                         return (ENOENT);
  218                 }
  219                 dev = &de->de_cdp->cdp_c;
  220         } else {
  221                 dev = NULL;
  222         }
  223         error = getnewvnode("devfs", mp, &devfs_vnodeops, &vp);
  224         if (error != 0) {
  225                 devfs_allocv_drop_refs(1, dmp, de);
  226                 printf("devfs_allocv: failed to allocate new vnode\n");
  227                 return (error);
  228         }
  229 
  230         if (de->de_dirent->d_type == DT_CHR) {
  231                 vp->v_type = VCHR;
  232                 VI_LOCK(vp);
  233                 dev_lock();
  234                 dev_refl(dev);
  235                 /* XXX: v_rdev should be protect by vnode lock */
  236                 vp->v_rdev = dev;
  237                 KASSERT(vp->v_usecount == 1,
  238                     ("%s %d (%d)\n", __func__, __LINE__, vp->v_usecount));
  239                 dev->si_usecount += vp->v_usecount;
  240                 dev_unlock();
  241                 VI_UNLOCK(vp);
  242                 vp->v_op = &devfs_specops;
  243         } else if (de->de_dirent->d_type == DT_DIR) {
  244                 vp->v_type = VDIR;
  245         } else if (de->de_dirent->d_type == DT_LNK) {
  246                 vp->v_type = VLNK;
  247         } else {
  248                 vp->v_type = VBAD;
  249         }
  250         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  251         mtx_lock(&devfs_de_interlock);
  252         vp->v_data = de;
  253         de->de_vnode = vp;
  254         mtx_unlock(&devfs_de_interlock);
  255         error = insmntque1(vp, mp, devfs_insmntque_dtr, de);
  256         if (error != 0) {
  257                 (void) devfs_allocv_drop_refs(1, dmp, de);
  258                 return (error);
  259         }
  260         if (devfs_allocv_drop_refs(0, dmp, de)) {
  261                 vput(vp);
  262                 return (ENOENT);
  263         }
  264 #ifdef MAC
  265         mac_associate_vnode_devfs(mp, de, vp);
  266 #endif
  267         sx_xunlock(&dmp->dm_lock);
  268         *vpp = vp;
  269         return (0);
  270 }
  271 
  272 static int
  273 devfs_access(struct vop_access_args *ap)
  274 {
  275         struct vnode *vp = ap->a_vp;
  276         struct devfs_dirent *de;
  277         int error;
  278 
  279         de = vp->v_data;
  280         if (vp->v_type == VDIR)
  281                 de = de->de_dir;
  282 
  283         error = vaccess(vp->v_type, de->de_mode, de->de_uid, de->de_gid,
  284             ap->a_mode, ap->a_cred, NULL);
  285         if (!error)
  286                 return (error);
  287         if (error != EACCES)
  288                 return (error);
  289         /* We do, however, allow access to the controlling terminal */
  290         if (!(ap->a_td->td_proc->p_flag & P_CONTROLT))
  291                 return (error);
  292         if (ap->a_td->td_proc->p_session->s_ttyvp == de->de_vnode)
  293                 return (0);
  294         return (error);
  295 }
  296 
  297 /* ARGSUSED */
  298 static int
  299 devfs_advlock(struct vop_advlock_args *ap)
  300 {
  301 
  302         return (ap->a_flags & F_FLOCK ? EOPNOTSUPP : EINVAL);
  303 }
  304 
  305 /* ARGSUSED */
  306 static int
  307 devfs_close(struct vop_close_args *ap)
  308 {
  309         struct vnode *vp = ap->a_vp, *oldvp;
  310         struct thread *td = ap->a_td;
  311         struct cdev *dev = vp->v_rdev;
  312         struct cdevsw *dsw;
  313         int vp_locked, error;
  314 
  315         /*
  316          * Hack: a tty device that is a controlling terminal
  317          * has a reference from the session structure.
  318          * We cannot easily tell that a character device is
  319          * a controlling terminal, unless it is the closing
  320          * process' controlling terminal.  In that case,
  321          * if the reference count is 2 (this last descriptor
  322          * plus the session), release the reference from the session.
  323          */
  324         oldvp = NULL;
  325         sx_xlock(&proctree_lock);
  326         if (td && vp == td->td_proc->p_session->s_ttyvp) {
  327                 SESS_LOCK(td->td_proc->p_session);
  328                 VI_LOCK(vp);
  329                 if (count_dev(dev) == 2 && (vp->v_iflag & VI_DOOMED) == 0) {
  330                         td->td_proc->p_session->s_ttyvp = NULL;
  331                         oldvp = vp;
  332                 }
  333                 VI_UNLOCK(vp);
  334                 SESS_UNLOCK(td->td_proc->p_session);
  335         }
  336         sx_xunlock(&proctree_lock);
  337         if (oldvp != NULL)
  338                 vrele(oldvp);
  339         /*
  340          * We do not want to really close the device if it
  341          * is still in use unless we are trying to close it
  342          * forcibly. Since every use (buffer, vnode, swap, cmap)
  343          * holds a reference to the vnode, and because we mark
  344          * any other vnodes that alias this device, when the
  345          * sum of the reference counts on all the aliased
  346          * vnodes descends to one, we are on last close.
  347          */
  348         dsw = dev_refthread(dev);
  349         if (dsw == NULL)
  350                 return (ENXIO);
  351         VI_LOCK(vp);
  352         if (vp->v_iflag & VI_DOOMED) {
  353                 /* Forced close. */
  354         } else if (dsw->d_flags & D_TRACKCLOSE) {
  355                 /* Keep device updated on status. */
  356         } else if (count_dev(dev) > 1) {
  357                 VI_UNLOCK(vp);
  358                 dev_relthread(dev);
  359                 return (0);
  360         }
  361         vholdl(vp);
  362         VI_UNLOCK(vp);
  363         vp_locked = VOP_ISLOCKED(vp, td);
  364         VOP_UNLOCK(vp, 0, td);
  365         KASSERT(dev->si_refcount > 0,
  366             ("devfs_close() on un-referenced struct cdev *(%s)", devtoname(dev)));
  367         if (!(dsw->d_flags & D_NEEDGIANT)) {
  368                 DROP_GIANT();
  369                 error = dsw->d_close(dev, ap->a_fflag, S_IFCHR, td);
  370                 PICKUP_GIANT();
  371         } else {
  372                 error = dsw->d_close(dev, ap->a_fflag, S_IFCHR, td);
  373         }
  374         dev_relthread(dev);
  375         vn_lock(vp, vp_locked | LK_RETRY, td);
  376         vdrop(vp);
  377         return (error);
  378 }
  379 
  380 static int
  381 devfs_close_f(struct file *fp, struct thread *td)
  382 {
  383 
  384         return (vnops.fo_close(fp, td));
  385 }
  386 
  387 /* ARGSUSED */
  388 static int
  389 devfs_fsync(struct vop_fsync_args *ap)
  390 {
  391         if (!vn_isdisk(ap->a_vp, NULL))
  392                 return (0);
  393 
  394         return (vop_stdfsync(ap));
  395 }
  396 
  397 static int
  398 devfs_getattr(struct vop_getattr_args *ap)
  399 {
  400         struct vnode *vp = ap->a_vp;
  401         struct vattr *vap = ap->a_vap;
  402         int error = 0;
  403         struct devfs_dirent *de;
  404         struct cdev *dev;
  405 
  406         de = vp->v_data;
  407         KASSERT(de != NULL, ("Null dirent in devfs_getattr vp=%p", vp));
  408         if (vp->v_type == VDIR) {
  409                 de = de->de_dir;
  410                 KASSERT(de != NULL,
  411                     ("Null dir dirent in devfs_getattr vp=%p", vp));
  412         }
  413         bzero((caddr_t) vap, sizeof(*vap));
  414         vattr_null(vap);
  415         vap->va_uid = de->de_uid;
  416         vap->va_gid = de->de_gid;
  417         vap->va_mode = de->de_mode;
  418         if (vp->v_type == VLNK)
  419                 vap->va_size = strlen(de->de_symlink);
  420         else if (vp->v_type == VDIR)
  421                 vap->va_size = vap->va_bytes = DEV_BSIZE;
  422         else
  423                 vap->va_size = 0;
  424         if (vp->v_type != VDIR)
  425                 vap->va_bytes = 0;
  426         vap->va_blocksize = DEV_BSIZE;
  427         vap->va_type = vp->v_type;
  428 
  429 #define fix(aa)                                                 \
  430         do {                                                    \
  431                 if ((aa).tv_sec <= 3600) {                      \
  432                         (aa).tv_sec = boottime.tv_sec;          \
  433                         (aa).tv_nsec = boottime.tv_usec * 1000; \
  434                 }                                               \
  435         } while (0)
  436 
  437         if (vp->v_type != VCHR)  {
  438                 fix(de->de_atime);
  439                 vap->va_atime = de->de_atime;
  440                 fix(de->de_mtime);
  441                 vap->va_mtime = de->de_mtime;
  442                 fix(de->de_ctime);
  443                 vap->va_ctime = de->de_ctime;
  444         } else {
  445                 dev = vp->v_rdev;
  446                 fix(dev->si_atime);
  447                 vap->va_atime = dev->si_atime;
  448                 fix(dev->si_mtime);
  449                 vap->va_mtime = dev->si_mtime;
  450                 fix(dev->si_ctime);
  451                 vap->va_ctime = dev->si_ctime;
  452 
  453                 vap->va_rdev = dev->si_priv->cdp_inode;
  454         }
  455         vap->va_gen = 0;
  456         vap->va_flags = 0;
  457         vap->va_nlink = de->de_links;
  458         vap->va_fileid = de->de_inode;
  459 
  460         return (error);
  461 }
  462 
  463 /* ARGSUSED */
  464 static int
  465 devfs_ioctl_f(struct file *fp, u_long com, void *data, struct ucred *cred, struct thread *td)
  466 {
  467         struct cdev *dev;
  468         struct cdevsw *dsw;
  469         struct vnode *vp;
  470         struct vnode *vpold;
  471         int error, i;
  472         const char *p;
  473         struct fiodgname_arg *fgn;
  474 
  475         error = devfs_fp_check(fp, &dev, &dsw);
  476         if (error)
  477                 return (error);
  478 
  479         if (com == FIODTYPE) {
  480                 *(int *)data = dsw->d_flags & D_TYPEMASK;
  481                 dev_relthread(dev);
  482                 return (0);
  483         } else if (com == FIODGNAME) {
  484                 fgn = data;
  485                 p = devtoname(dev);
  486                 i = strlen(p) + 1;
  487                 if (i > fgn->len)
  488                         error = EINVAL;
  489                 else
  490                         error = copyout(p, fgn->buf, i);
  491                 dev_relthread(dev);
  492                 return (error);
  493         }
  494         error = dsw->d_ioctl(dev, com, data, fp->f_flag, td);
  495         dev_relthread(dev);
  496         if (error == ENOIOCTL)
  497                 error = ENOTTY;
  498         if (error == 0 && com == TIOCSCTTY) {
  499                 vp = fp->f_vnode;
  500 
  501                 /* Do nothing if reassigning same control tty */
  502                 sx_slock(&proctree_lock);
  503                 if (td->td_proc->p_session->s_ttyvp == vp) {
  504                         sx_sunlock(&proctree_lock);
  505                         return (0);
  506                 }
  507 
  508                 mtx_lock(&Giant);       /* XXX TTY */
  509 
  510                 vpold = td->td_proc->p_session->s_ttyvp;
  511                 VREF(vp);
  512                 SESS_LOCK(td->td_proc->p_session);
  513                 td->td_proc->p_session->s_ttyvp = vp;
  514                 SESS_UNLOCK(td->td_proc->p_session);
  515 
  516                 sx_sunlock(&proctree_lock);
  517 
  518                 /* Get rid of reference to old control tty */
  519                 if (vpold)
  520                         vrele(vpold);
  521                 mtx_unlock(&Giant);     /* XXX TTY */
  522         }
  523         return (error);
  524 }
  525 
  526 /* ARGSUSED */
  527 static int
  528 devfs_kqfilter_f(struct file *fp, struct knote *kn)
  529 {
  530         struct cdev *dev;
  531         struct cdevsw *dsw;
  532         int error;
  533 
  534         error = devfs_fp_check(fp, &dev, &dsw);
  535         if (error)
  536                 return (error);
  537         error = dsw->d_kqfilter(dev, kn);
  538         dev_relthread(dev);
  539         return (error);
  540 }
  541 
  542 static int
  543 devfs_lookupx(struct vop_lookup_args *ap, int *dm_unlock)
  544 {
  545         struct componentname *cnp;
  546         struct vnode *dvp, **vpp;
  547         struct thread *td;
  548         struct devfs_dirent *de, *dd;
  549         struct devfs_dirent **dde;
  550         struct devfs_mount *dmp;
  551         struct cdev *cdev;
  552         int error, flags, nameiop;
  553         char specname[SPECNAMELEN + 1], *pname;
  554 
  555         cnp = ap->a_cnp;
  556         vpp = ap->a_vpp;
  557         dvp = ap->a_dvp;
  558         pname = cnp->cn_nameptr;
  559         td = cnp->cn_thread;
  560         flags = cnp->cn_flags;
  561         nameiop = cnp->cn_nameiop;
  562         dmp = VFSTODEVFS(dvp->v_mount);
  563         dd = dvp->v_data;
  564         *vpp = NULLVP;
  565 
  566         if ((flags & ISLASTCN) && nameiop == RENAME)
  567                 return (EOPNOTSUPP);
  568 
  569         if (dvp->v_type != VDIR)
  570                 return (ENOTDIR);
  571 
  572         if ((flags & ISDOTDOT) && (dvp->v_vflag & VV_ROOT))
  573                 return (EIO);
  574 
  575         error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td);
  576         if (error)
  577                 return (error);
  578 
  579         if (cnp->cn_namelen == 1 && *pname == '.') {
  580                 if ((flags & ISLASTCN) && nameiop != LOOKUP)
  581                         return (EINVAL);
  582                 *vpp = dvp;
  583                 VREF(dvp);
  584                 return (0);
  585         }
  586 
  587         if (flags & ISDOTDOT) {
  588                 if ((flags & ISLASTCN) && nameiop != LOOKUP)
  589                         return (EINVAL);
  590                 VOP_UNLOCK(dvp, 0, td);
  591                 de = TAILQ_FIRST(&dd->de_dlist);        /* "." */
  592                 de = TAILQ_NEXT(de, de_list);           /* ".." */
  593                 de = de->de_dir;
  594                 error = devfs_allocv(de, dvp->v_mount, vpp, td);
  595                 *dm_unlock = 0;
  596                 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
  597                 return (error);
  598         }
  599 
  600         DEVFS_DMP_HOLD(dmp);
  601         devfs_populate(dmp);
  602         if (DEVFS_DMP_DROP(dmp)) {
  603                 *dm_unlock = 0;
  604                 sx_xunlock(&dmp->dm_lock);
  605                 devfs_unmount_final(dmp);
  606                 return (ENOENT);
  607         }
  608         dd = dvp->v_data;
  609         de = devfs_find(dd, cnp->cn_nameptr, cnp->cn_namelen);
  610         while (de == NULL) {    /* While(...) so we can use break */
  611 
  612                 if (nameiop == DELETE)
  613                         return (ENOENT);
  614 
  615                 /*
  616                  * OK, we didn't have an entry for the name we were asked for
  617                  * so we try to see if anybody can create it on demand.
  618                  */
  619                 pname = devfs_fqpn(specname, dvp, cnp);
  620                 if (pname == NULL)
  621                         break;
  622 
  623                 cdev = NULL;
  624                 DEVFS_DMP_HOLD(dmp);
  625                 sx_xunlock(&dmp->dm_lock);
  626                 sx_slock(&clone_drain_lock);
  627                 EVENTHANDLER_INVOKE(dev_clone,
  628                     td->td_ucred, pname, strlen(pname), &cdev);
  629                 sx_sunlock(&clone_drain_lock);
  630                 sx_xlock(&dmp->dm_lock);
  631                 if (DEVFS_DMP_DROP(dmp)) {
  632                         *dm_unlock = 0;
  633                         sx_xunlock(&dmp->dm_lock);
  634                         devfs_unmount_final(dmp);
  635                         return (ENOENT);
  636                 }
  637                 if (cdev == NULL)
  638                         break;
  639 
  640                 DEVFS_DMP_HOLD(dmp);
  641                 devfs_populate(dmp);
  642                 if (DEVFS_DMP_DROP(dmp)) {
  643                         *dm_unlock = 0;
  644                         sx_xunlock(&dmp->dm_lock);
  645                         devfs_unmount_final(dmp);
  646                         return (ENOENT);
  647                 }
  648 
  649                 dev_lock();
  650                 dde = &cdev->si_priv->cdp_dirents[dmp->dm_idx];
  651                 if (dde != NULL && *dde != NULL)
  652                         de = *dde;
  653                 dev_unlock();
  654                 dev_rel(cdev);
  655                 break;
  656         }
  657 
  658         if (de == NULL || de->de_flags & DE_WHITEOUT) {
  659                 if ((nameiop == CREATE || nameiop == RENAME) &&
  660                     (flags & (LOCKPARENT | WANTPARENT)) && (flags & ISLASTCN)) {
  661                         cnp->cn_flags |= SAVENAME;
  662                         return (EJUSTRETURN);
  663                 }
  664                 return (ENOENT);
  665         }
  666 
  667         if ((cnp->cn_nameiop == DELETE) && (flags & ISLASTCN)) {
  668                 error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td);
  669                 if (error)
  670                         return (error);
  671                 if (*vpp == dvp) {
  672                         VREF(dvp);
  673                         *vpp = dvp;
  674                         return (0);
  675                 }
  676         }
  677         error = devfs_allocv(de, dvp->v_mount, vpp, td);
  678         *dm_unlock = 0;
  679         return (error);
  680 }
  681 
  682 static int
  683 devfs_lookup(struct vop_lookup_args *ap)
  684 {
  685         int j;
  686         struct devfs_mount *dmp;
  687         int dm_unlock;
  688 
  689         dmp = VFSTODEVFS(ap->a_dvp->v_mount);
  690         dm_unlock = 1;
  691         sx_xlock(&dmp->dm_lock);
  692         j = devfs_lookupx(ap, &dm_unlock);
  693         if (dm_unlock == 1)
  694                 sx_xunlock(&dmp->dm_lock);
  695         return (j);
  696 }
  697 
  698 static int
  699 devfs_mknod(struct vop_mknod_args *ap)
  700 {
  701         struct componentname *cnp;
  702         struct vnode *dvp, **vpp;
  703         struct thread *td;
  704         struct devfs_dirent *dd, *de;
  705         struct devfs_mount *dmp;
  706         int error;
  707 
  708         /*
  709          * The only type of node we should be creating here is a
  710          * character device, for anything else return EOPNOTSUPP.
  711          */
  712         if (ap->a_vap->va_type != VCHR)
  713                 return (EOPNOTSUPP);
  714         dvp = ap->a_dvp;
  715         dmp = VFSTODEVFS(dvp->v_mount);
  716 
  717         cnp = ap->a_cnp;
  718         vpp = ap->a_vpp;
  719         td = cnp->cn_thread;
  720         dd = dvp->v_data;
  721 
  722         error = ENOENT;
  723         sx_xlock(&dmp->dm_lock);
  724         TAILQ_FOREACH(de, &dd->de_dlist, de_list) {
  725                 if (cnp->cn_namelen != de->de_dirent->d_namlen)
  726                         continue;
  727                 if (bcmp(cnp->cn_nameptr, de->de_dirent->d_name,
  728                     de->de_dirent->d_namlen) != 0)
  729                         continue;
  730                 if (de->de_flags & DE_WHITEOUT)
  731                         break;
  732                 goto notfound;
  733         }
  734         if (de == NULL)
  735                 goto notfound;
  736         de->de_flags &= ~DE_WHITEOUT;
  737         error = devfs_allocv(de, dvp->v_mount, vpp, td);
  738         return (error);
  739 notfound:
  740         sx_xunlock(&dmp->dm_lock);
  741         return (error);
  742 }
  743 
  744 /* ARGSUSED */
  745 static int
  746 devfs_open(struct vop_open_args *ap)
  747 {
  748         struct thread *td = ap->a_td;
  749         struct vnode *vp = ap->a_vp;
  750         struct cdev *dev = vp->v_rdev;
  751         struct file *fp = ap->a_fp;
  752         int error;
  753         struct cdevsw *dsw;
  754 
  755         if (vp->v_type == VBLK)
  756                 return (ENXIO);
  757 
  758         if (dev == NULL)
  759                 return (ENXIO);
  760 
  761         /* Make this field valid before any I/O in d_open. */
  762         if (dev->si_iosize_max == 0)
  763                 dev->si_iosize_max = DFLTPHYS;
  764 
  765         dsw = dev_refthread(dev);
  766         if (dsw == NULL)
  767                 return (ENXIO);
  768 
  769         /* XXX: Special casing of ttys for deadfs.  Probably redundant. */
  770         if (dsw->d_flags & D_TTY)
  771                 vp->v_vflag |= VV_ISTTY;
  772 
  773         VOP_UNLOCK(vp, 0, td);
  774 
  775         if(!(dsw->d_flags & D_NEEDGIANT)) {
  776                 DROP_GIANT();
  777                 if (dsw->d_fdopen != NULL)
  778                         error = dsw->d_fdopen(dev, ap->a_mode, td, fp);
  779                 else
  780                         error = dsw->d_open(dev, ap->a_mode, S_IFCHR, td);
  781                 PICKUP_GIANT();
  782         } else {
  783                 if (dsw->d_fdopen != NULL)
  784                         error = dsw->d_fdopen(dev, ap->a_mode, td, fp);
  785                 else
  786                         error = dsw->d_open(dev, ap->a_mode, S_IFCHR, td);
  787         }
  788 
  789         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
  790 
  791         dev_relthread(dev);
  792 
  793         if (error)
  794                 return (error);
  795 
  796 #if 0   /* /dev/console */
  797         KASSERT(fp != NULL,
  798              ("Could not vnode bypass device on NULL fp"));
  799 #else
  800         if(fp == NULL)
  801                 return (error);
  802 #endif
  803         FILE_LOCK(fp);
  804         KASSERT(fp->f_ops == &badfileops,
  805              ("Could not vnode bypass device on fdops %p", fp->f_ops));
  806         fp->f_data = dev;
  807         fp->f_ops = &devfs_ops_f;
  808         FILE_UNLOCK(fp);
  809         return (error);
  810 }
  811 
  812 static int
  813 devfs_pathconf(struct vop_pathconf_args *ap)
  814 {
  815 
  816         switch (ap->a_name) {
  817         case _PC_MAC_PRESENT:
  818 #ifdef MAC
  819                 /*
  820                  * If MAC is enabled, devfs automatically supports
  821                  * trivial non-persistant label storage.
  822                  */
  823                 *ap->a_retval = 1;
  824 #else
  825                 *ap->a_retval = 0;
  826 #endif
  827                 return (0);
  828         default:
  829                 return (vop_stdpathconf(ap));
  830         }
  831         /* NOTREACHED */
  832 }
  833 
  834 /* ARGSUSED */
  835 static int
  836 devfs_poll_f(struct file *fp, int events, struct ucred *cred, struct thread *td)
  837 {
  838         struct cdev *dev;
  839         struct cdevsw *dsw;
  840         int error;
  841 
  842         error = devfs_fp_check(fp, &dev, &dsw);
  843         if (error)
  844                 return (error);
  845         error = dsw->d_poll(dev, events, td);
  846         dev_relthread(dev);
  847         return(error);
  848 }
  849 
  850 /*
  851  * Print out the contents of a special device vnode.
  852  */
  853 static int
  854 devfs_print(struct vop_print_args *ap)
  855 {
  856 
  857         printf("\tdev %s\n", devtoname(ap->a_vp->v_rdev));
  858         return (0);
  859 }
  860 
  861 /* ARGSUSED */
  862 static int
  863 devfs_read_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, struct thread *td)
  864 {
  865         struct cdev *dev;
  866         int ioflag, error, resid;
  867         struct cdevsw *dsw;
  868 
  869         error = devfs_fp_check(fp, &dev, &dsw);
  870         if (error)
  871                 return (error);
  872         resid = uio->uio_resid;
  873         ioflag = fp->f_flag & (O_NONBLOCK | O_DIRECT);
  874         if (ioflag & O_DIRECT)
  875                 ioflag |= IO_DIRECT;
  876 
  877         if ((flags & FOF_OFFSET) == 0)
  878                 uio->uio_offset = fp->f_offset;
  879 
  880         error = dsw->d_read(dev, uio, ioflag);
  881         if (uio->uio_resid != resid || (error == 0 && resid != 0))
  882                 vfs_timestamp(&dev->si_atime);
  883         dev_relthread(dev);
  884 
  885         if ((flags & FOF_OFFSET) == 0)
  886                 fp->f_offset = uio->uio_offset;
  887         fp->f_nextoff = uio->uio_offset;
  888         return (error);
  889 }
  890 
  891 static int
  892 devfs_readdir(struct vop_readdir_args *ap)
  893 {
  894         int error;
  895         struct uio *uio;
  896         struct dirent *dp;
  897         struct devfs_dirent *dd;
  898         struct devfs_dirent *de;
  899         struct devfs_mount *dmp;
  900         off_t off, oldoff;
  901         int *tmp_ncookies = NULL;
  902 
  903         if (ap->a_vp->v_type != VDIR)
  904                 return (ENOTDIR);
  905 
  906         uio = ap->a_uio;
  907         if (uio->uio_offset < 0)
  908                 return (EINVAL);
  909 
  910         /*
  911          * XXX: This is a temporary hack to get around this filesystem not
  912          * supporting cookies. We store the location of the ncookies pointer
  913          * in a temporary variable before calling vfs_subr.c:vfs_read_dirent()
  914          * and set the number of cookies to 0. We then set the pointer to
  915          * NULL so that vfs_read_dirent doesn't try to call realloc() on 
  916          * ap->a_cookies. Later in this function, we restore the ap->a_ncookies
  917          * pointer to its original location before returning to the caller.
  918          */
  919         if (ap->a_ncookies != NULL) {
  920                 tmp_ncookies = ap->a_ncookies;
  921                 *ap->a_ncookies = 0;
  922                 ap->a_ncookies = NULL;
  923         }
  924 
  925         dmp = VFSTODEVFS(ap->a_vp->v_mount);
  926         sx_xlock(&dmp->dm_lock);
  927         DEVFS_DMP_HOLD(dmp);
  928         devfs_populate(dmp);
  929         if (DEVFS_DMP_DROP(dmp)) {
  930                 sx_xunlock(&dmp->dm_lock);
  931                 devfs_unmount_final(dmp);
  932                 if (tmp_ncookies != NULL)
  933                         ap->a_ncookies = tmp_ncookies;
  934                 return (EIO);
  935         }
  936         error = 0;
  937         de = ap->a_vp->v_data;
  938         off = 0;
  939         oldoff = uio->uio_offset;
  940         TAILQ_FOREACH(dd, &de->de_dlist, de_list) {
  941                 KASSERT(dd->de_cdp != (void *)0xdeadc0de, ("%s %d\n", __func__, __LINE__));
  942                 if (dd->de_flags & DE_WHITEOUT)
  943                         continue;
  944                 if (dd->de_dirent->d_type == DT_DIR)
  945                         de = dd->de_dir;
  946                 else
  947                         de = dd;
  948                 dp = dd->de_dirent;
  949                 if (dp->d_reclen > uio->uio_resid)
  950                         break;
  951                 dp->d_fileno = de->de_inode;
  952                 if (off >= uio->uio_offset) {
  953                         error = vfs_read_dirent(ap, dp, off);
  954                         if (error)
  955                                 break;
  956                 }
  957                 off += dp->d_reclen;
  958         }
  959         sx_xunlock(&dmp->dm_lock);
  960         uio->uio_offset = off;
  961 
  962         /*
  963          * Restore ap->a_ncookies if it wasn't originally NULL in the first
  964          * place.
  965          */
  966         if (tmp_ncookies != NULL)
  967                 ap->a_ncookies = tmp_ncookies;
  968 
  969         return (error);
  970 }
  971 
  972 static int
  973 devfs_readlink(struct vop_readlink_args *ap)
  974 {
  975         struct devfs_dirent *de;
  976 
  977         de = ap->a_vp->v_data;
  978         return (uiomove(de->de_symlink, strlen(de->de_symlink), ap->a_uio));
  979 }
  980 
  981 static int
  982 devfs_reclaim(struct vop_reclaim_args *ap)
  983 {
  984         struct vnode *vp = ap->a_vp;
  985         struct devfs_dirent *de;
  986         struct cdev *dev;
  987 
  988         mtx_lock(&devfs_de_interlock);
  989         de = vp->v_data;
  990         if (de != NULL) {
  991                 de->de_vnode = NULL;
  992                 vp->v_data = NULL;
  993         }
  994         mtx_unlock(&devfs_de_interlock);
  995 
  996         vnode_destroy_vobject(vp);
  997 
  998         VI_LOCK(vp);
  999         dev_lock();
 1000         dev = vp->v_rdev;
 1001         vp->v_rdev = NULL;
 1002 
 1003         if (dev == NULL) {
 1004                 dev_unlock();
 1005                 VI_UNLOCK(vp);
 1006                 return (0);
 1007         }
 1008 
 1009         dev->si_usecount -= vp->v_usecount;
 1010         dev_unlock();
 1011         VI_UNLOCK(vp);
 1012         dev_rel(dev);
 1013         return (0);
 1014 }
 1015 
 1016 static int
 1017 devfs_remove(struct vop_remove_args *ap)
 1018 {
 1019         struct vnode *vp = ap->a_vp;
 1020         struct devfs_dirent *dd;
 1021         struct devfs_dirent *de;
 1022         struct devfs_mount *dmp = VFSTODEVFS(vp->v_mount);
 1023 
 1024         sx_xlock(&dmp->dm_lock);
 1025         dd = ap->a_dvp->v_data;
 1026         de = vp->v_data;
 1027         if (de->de_cdp == NULL) {
 1028                 TAILQ_REMOVE(&dd->de_dlist, de, de_list);
 1029                 devfs_delete(dmp, de, 1);
 1030         } else {
 1031                 de->de_flags |= DE_WHITEOUT;
 1032         }
 1033         sx_xunlock(&dmp->dm_lock);
 1034         return (0);
 1035 }
 1036 
 1037 /*
 1038  * Revoke is called on a tty when a terminal session ends.  The vnode
 1039  * is orphaned by setting v_op to deadfs so we need to let go of it
 1040  * as well so that we create a new one next time around.
 1041  *
 1042  */
 1043 static int
 1044 devfs_revoke(struct vop_revoke_args *ap)
 1045 {
 1046         struct vnode *vp = ap->a_vp, *vp2;
 1047         struct cdev *dev;
 1048         struct cdev_priv *cdp;
 1049         struct devfs_dirent *de;
 1050         int i;
 1051 
 1052         KASSERT((ap->a_flags & REVOKEALL) != 0, ("devfs_revoke !REVOKEALL"));
 1053 
 1054         dev = vp->v_rdev;
 1055         cdp = dev->si_priv;
 1056  
 1057         dev_lock();
 1058         cdp->cdp_inuse++;
 1059         dev_unlock();
 1060 
 1061         vhold(vp);
 1062         vgone(vp);
 1063         vdrop(vp);
 1064 
 1065         VOP_UNLOCK(vp,0,curthread);
 1066  loop:
 1067         for (;;) {
 1068                 mtx_lock(&devfs_de_interlock);
 1069                 dev_lock();
 1070                 vp2 = NULL;
 1071                 for (i = 0; i <= cdp->cdp_maxdirent; i++) {
 1072                         de = cdp->cdp_dirents[i];
 1073                         if (de == NULL)
 1074                                 continue;
 1075 
 1076                         vp2 = de->de_vnode;
 1077                         if (vp2 != NULL) {
 1078                                 dev_unlock();
 1079                                 VI_LOCK(vp2);
 1080                                 mtx_unlock(&devfs_de_interlock);
 1081                                 if (vget(vp2, LK_EXCLUSIVE | LK_INTERLOCK,
 1082                                     curthread))
 1083                                         goto loop;
 1084                                 vhold(vp2);
 1085                                 vgone(vp2);
 1086                                 vdrop(vp2);
 1087                                 vput(vp2);
 1088                                 break;
 1089                         } 
 1090                 }
 1091                 if (vp2 != NULL) {
 1092                         continue;
 1093                 }
 1094                 dev_unlock();
 1095                 mtx_unlock(&devfs_de_interlock);
 1096                 break;
 1097         }
 1098         dev_lock();
 1099         cdp->cdp_inuse--;
 1100         if (!(cdp->cdp_flags & CDP_ACTIVE) && cdp->cdp_inuse == 0) {
 1101                 TAILQ_REMOVE(&cdevp_list, cdp, cdp_list);
 1102                 dev_unlock();
 1103                 dev_rel(&cdp->cdp_c);
 1104         } else
 1105                 dev_unlock();
 1106 
 1107         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread);
 1108         return (0);
 1109 }
 1110 
 1111 static int
 1112 devfs_rioctl(struct vop_ioctl_args *ap)
 1113 {
 1114         int error;
 1115         struct devfs_mount *dmp;
 1116 
 1117         dmp = VFSTODEVFS(ap->a_vp->v_mount);
 1118         sx_xlock(&dmp->dm_lock);
 1119         DEVFS_DMP_HOLD(dmp);
 1120         devfs_populate(dmp);
 1121         if (DEVFS_DMP_DROP(dmp)) {
 1122                 sx_xunlock(&dmp->dm_lock);
 1123                 devfs_unmount_final(dmp);
 1124                 return (ENOENT);
 1125         }
 1126         error = devfs_rules_ioctl(dmp, ap->a_command, ap->a_data, ap->a_td);
 1127         sx_xunlock(&dmp->dm_lock);
 1128         return (error);
 1129 }
 1130 
 1131 static int
 1132 devfs_rread(struct vop_read_args *ap)
 1133 {
 1134 
 1135         if (ap->a_vp->v_type != VDIR)
 1136                 return (EINVAL);
 1137         return (VOP_READDIR(ap->a_vp, ap->a_uio, ap->a_cred, NULL, NULL, NULL));
 1138 }
 1139 
 1140 static int
 1141 devfs_setattr(struct vop_setattr_args *ap)
 1142 {
 1143         struct devfs_dirent *de;
 1144         struct vattr *vap;
 1145         struct vnode *vp;
 1146         int c, error;
 1147         uid_t uid;
 1148         gid_t gid;
 1149 
 1150         vap = ap->a_vap;
 1151         vp = ap->a_vp;
 1152         if ((vap->va_type != VNON) ||
 1153             (vap->va_nlink != VNOVAL) ||
 1154             (vap->va_fsid != VNOVAL) ||
 1155             (vap->va_fileid != VNOVAL) ||
 1156             (vap->va_blocksize != VNOVAL) ||
 1157             (vap->va_flags != VNOVAL && vap->va_flags != 0) ||
 1158             (vap->va_rdev != VNOVAL) ||
 1159             ((int)vap->va_bytes != VNOVAL) ||
 1160             (vap->va_gen != VNOVAL)) {
 1161                 return (EINVAL);
 1162         }
 1163 
 1164         de = vp->v_data;
 1165         if (vp->v_type == VDIR)
 1166                 de = de->de_dir;
 1167 
 1168         error = c = 0;
 1169         if (vap->va_uid == (uid_t)VNOVAL)
 1170                 uid = de->de_uid;
 1171         else
 1172                 uid = vap->va_uid;
 1173         if (vap->va_gid == (gid_t)VNOVAL)
 1174                 gid = de->de_gid;
 1175         else
 1176                 gid = vap->va_gid;
 1177         if (uid != de->de_uid || gid != de->de_gid) {
 1178                 if ((ap->a_cred->cr_uid != de->de_uid) || uid != de->de_uid ||
 1179                     (gid != de->de_gid && !groupmember(gid, ap->a_cred))) {
 1180                         error = priv_check(ap->a_td, PRIV_VFS_CHOWN);
 1181                         if (error)
 1182                                 return (error);
 1183                 }
 1184                 de->de_uid = uid;
 1185                 de->de_gid = gid;
 1186                 c = 1;
 1187         }
 1188 
 1189         if (vap->va_mode != (mode_t)VNOVAL) {
 1190                 if (ap->a_cred->cr_uid != de->de_uid) {
 1191                         error = priv_check(ap->a_td, PRIV_VFS_ADMIN);
 1192                         if (error)
 1193                                 return (error);
 1194                 }
 1195                 de->de_mode = vap->va_mode;
 1196                 c = 1;
 1197         }
 1198 
 1199         if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
 1200                 /* See the comment in ufs_vnops::ufs_setattr(). */
 1201                 if ((error = VOP_ACCESS(vp, VADMIN, ap->a_cred, ap->a_td)) &&
 1202                     ((vap->va_vaflags & VA_UTIMES_NULL) == 0 ||
 1203                     (error = VOP_ACCESS(vp, VWRITE, ap->a_cred, ap->a_td))))
 1204                         return (error);
 1205                 if (vap->va_atime.tv_sec != VNOVAL) {
 1206                         if (vp->v_type == VCHR)
 1207                                 vp->v_rdev->si_atime = vap->va_atime;
 1208                         else
 1209                                 de->de_atime = vap->va_atime;
 1210                 }
 1211                 if (vap->va_mtime.tv_sec != VNOVAL) {
 1212                         if (vp->v_type == VCHR)
 1213                                 vp->v_rdev->si_mtime = vap->va_mtime;
 1214                         else
 1215                                 de->de_mtime = vap->va_mtime;
 1216                 }
 1217                 c = 1;
 1218         }
 1219 
 1220         if (c) {
 1221                 if (vp->v_type == VCHR)
 1222                         vfs_timestamp(&vp->v_rdev->si_ctime);
 1223                 else
 1224                         vfs_timestamp(&de->de_mtime);
 1225         }
 1226         return (0);
 1227 }
 1228 
 1229 #ifdef MAC
 1230 static int
 1231 devfs_setlabel(struct vop_setlabel_args *ap)
 1232 {
 1233         struct vnode *vp;
 1234         struct devfs_dirent *de;
 1235 
 1236         vp = ap->a_vp;
 1237         de = vp->v_data;
 1238 
 1239         mac_relabel_vnode(ap->a_cred, vp, ap->a_label);
 1240         mac_update_devfs(vp->v_mount, de, vp);
 1241 
 1242         return (0);
 1243 }
 1244 #endif
 1245 
 1246 static int
 1247 devfs_stat_f(struct file *fp, struct stat *sb, struct ucred *cred, struct thread *td)
 1248 {
 1249 
 1250         return (vnops.fo_stat(fp, sb, cred, td));
 1251 }
 1252 
 1253 static int
 1254 devfs_symlink(struct vop_symlink_args *ap)
 1255 {
 1256         int i, error;
 1257         struct devfs_dirent *dd;
 1258         struct devfs_dirent *de;
 1259         struct devfs_mount *dmp;
 1260         struct thread *td;
 1261 
 1262         td = ap->a_cnp->cn_thread;
 1263         KASSERT(td == curthread, ("devfs_symlink: td != curthread"));
 1264 
 1265         error = priv_check(td, PRIV_DEVFS_SYMLINK);
 1266         if (error)
 1267                 return(error);
 1268         dmp = VFSTODEVFS(ap->a_dvp->v_mount);
 1269         dd = ap->a_dvp->v_data;
 1270         de = devfs_newdirent(ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen);
 1271         de->de_uid = 0;
 1272         de->de_gid = 0;
 1273         de->de_mode = 0755;
 1274         de->de_inode = alloc_unr(devfs_inos);
 1275         de->de_dirent->d_type = DT_LNK;
 1276         i = strlen(ap->a_target) + 1;
 1277         de->de_symlink = malloc(i, M_DEVFS, M_WAITOK);
 1278         bcopy(ap->a_target, de->de_symlink, i);
 1279         sx_xlock(&dmp->dm_lock);
 1280 #ifdef MAC
 1281         mac_create_devfs_symlink(ap->a_cnp->cn_cred, dmp->dm_mount, dd, de);
 1282 #endif
 1283         TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list);
 1284         return (devfs_allocv(de, ap->a_dvp->v_mount, ap->a_vpp, td));
 1285 }
 1286 
 1287 /* ARGSUSED */
 1288 static int
 1289 devfs_write_f(struct file *fp, struct uio *uio, struct ucred *cred, int flags, struct thread *td)
 1290 {
 1291         struct cdev *dev;
 1292         int error, ioflag, resid;
 1293         struct cdevsw *dsw;
 1294 
 1295         error = devfs_fp_check(fp, &dev, &dsw);
 1296         if (error)
 1297                 return (error);
 1298         KASSERT(uio->uio_td == td, ("uio_td %p is not td %p", uio->uio_td, td));
 1299         ioflag = fp->f_flag & (O_NONBLOCK | O_DIRECT | O_FSYNC);
 1300         if (ioflag & O_DIRECT)
 1301                 ioflag |= IO_DIRECT;
 1302         if ((flags & FOF_OFFSET) == 0)
 1303                 uio->uio_offset = fp->f_offset;
 1304 
 1305         resid = uio->uio_resid;
 1306 
 1307         error = dsw->d_write(dev, uio, ioflag);
 1308         if (uio->uio_resid != resid || (error == 0 && resid != 0)) {
 1309                 vfs_timestamp(&dev->si_ctime);
 1310                 dev->si_mtime = dev->si_ctime;
 1311         }
 1312         dev_relthread(dev);
 1313 
 1314         if ((flags & FOF_OFFSET) == 0)
 1315                 fp->f_offset = uio->uio_offset;
 1316         fp->f_nextoff = uio->uio_offset;
 1317         return (error);
 1318 }
 1319 
 1320 dev_t
 1321 dev2udev(struct cdev *x)
 1322 {
 1323         if (x == NULL)
 1324                 return (NODEV);
 1325         return (x->si_priv->cdp_inode);
 1326 }
 1327 
 1328 static struct fileops devfs_ops_f = {
 1329         .fo_read =      devfs_read_f,
 1330         .fo_write =     devfs_write_f,
 1331         .fo_ioctl =     devfs_ioctl_f,
 1332         .fo_poll =      devfs_poll_f,
 1333         .fo_kqfilter =  devfs_kqfilter_f,
 1334         .fo_stat =      devfs_stat_f,
 1335         .fo_close =     devfs_close_f,
 1336         .fo_flags =     DFLAG_PASSABLE | DFLAG_SEEKABLE
 1337 };
 1338 
 1339 static struct vop_vector devfs_vnodeops = {
 1340         .vop_default =          &default_vnodeops,
 1341 
 1342         .vop_access =           devfs_access,
 1343         .vop_getattr =          devfs_getattr,
 1344         .vop_ioctl =            devfs_rioctl,
 1345         .vop_lookup =           devfs_lookup,
 1346         .vop_mknod =            devfs_mknod,
 1347         .vop_pathconf =         devfs_pathconf,
 1348         .vop_read =             devfs_rread,
 1349         .vop_readdir =          devfs_readdir,
 1350         .vop_readlink =         devfs_readlink,
 1351         .vop_reclaim =          devfs_reclaim,
 1352         .vop_remove =           devfs_remove,
 1353         .vop_revoke =           devfs_revoke,
 1354         .vop_setattr =          devfs_setattr,
 1355 #ifdef MAC
 1356         .vop_setlabel =         devfs_setlabel,
 1357 #endif
 1358         .vop_symlink =          devfs_symlink,
 1359 };
 1360 
 1361 static struct vop_vector devfs_specops = {
 1362         .vop_default =          &default_vnodeops,
 1363 
 1364         .vop_access =           devfs_access,
 1365         .vop_advlock =          devfs_advlock,
 1366         .vop_bmap =             VOP_PANIC,
 1367         .vop_close =            devfs_close,
 1368         .vop_create =           VOP_PANIC,
 1369         .vop_fsync =            devfs_fsync,
 1370         .vop_getattr =          devfs_getattr,
 1371         .vop_lease =            VOP_NULL,
 1372         .vop_link =             VOP_PANIC,
 1373         .vop_mkdir =            VOP_PANIC,
 1374         .vop_mknod =            VOP_PANIC,
 1375         .vop_open =             devfs_open,
 1376         .vop_pathconf =         devfs_pathconf,
 1377         .vop_print =            devfs_print,
 1378         .vop_read =             VOP_PANIC,
 1379         .vop_readdir =          VOP_PANIC,
 1380         .vop_readlink =         VOP_PANIC,
 1381         .vop_reallocblks =      VOP_PANIC,
 1382         .vop_reclaim =          devfs_reclaim,
 1383         .vop_remove =           devfs_remove,
 1384         .vop_rename =           VOP_PANIC,
 1385         .vop_revoke =           devfs_revoke,
 1386         .vop_rmdir =            VOP_PANIC,
 1387         .vop_setattr =          devfs_setattr,
 1388 #ifdef MAC
 1389         .vop_setlabel =         devfs_setlabel,
 1390 #endif
 1391         .vop_strategy =         VOP_PANIC,
 1392         .vop_symlink =          VOP_PANIC,
 1393         .vop_write =            VOP_PANIC,
 1394 };
 1395 
 1396 /*
 1397  * Our calling convention to the device drivers used to be that we passed
 1398  * vnode.h IO_* flags to read()/write(), but we're moving to fcntl.h O_ 
 1399  * flags instead since that's what open(), close() and ioctl() takes and
 1400  * we don't really want vnode.h in device drivers.
 1401  * We solved the source compatibility by redefining some vnode flags to
 1402  * be the same as the fcntl ones and by sending down the bitwise OR of
 1403  * the respective fcntl/vnode flags.  These CTASSERTS make sure nobody
 1404  * pulls the rug out under this.
 1405  */
 1406 CTASSERT(O_NONBLOCK == IO_NDELAY);
 1407 CTASSERT(O_FSYNC == IO_SYNC);

Cache object: c343a72260979ebbc08c28533bc331d0


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