Diff for /src/sys/vfs/specfs/spec_vnops.c between versions 1.14 and 1.15

version 1.14, 2004/05/03 18:46:34 version 1.15, 2004/05/19 22:53:06
Line 113  static struct vnodeopv_desc spec_vnodeop Line 113  static struct vnodeopv_desc spec_vnodeop
   
 VNODEOP_SET(spec_vnodeop_opv_desc);  VNODEOP_SET(spec_vnodeop_opv_desc);
   
   extern int dev_ref_debug;
   
 /*  /*
  * spec_vnoperate(struct vnodeop_desc *a_desc, ...)   * spec_vnoperate(struct vnodeop_desc *a_desc, ...)
  */   */
Line 135  static int Line 137  static int
 spec_open(struct vop_open_args *ap)  spec_open(struct vop_open_args *ap)
 {  {
         struct vnode *vp = ap->a_vp;          struct vnode *vp = ap->a_vp;
        dev_t dev = vp->v_rdev;        dev_t dev;
         int error;          int error;
           int isblk = (vp->v_type == VBLK) ? 1 : 0;
         const char *cp;          const char *cp;
   
         /*          /*
Line 145  spec_open(struct vop_open_args *ap) Line 148  spec_open(struct vop_open_args *ap)
         if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV))          if (vp->v_mount && (vp->v_mount->mnt_flag & MNT_NODEV))
                 return (ENXIO);                  return (ENXIO);
   
        if (dev_dport(dev) == NULL)        /*
                return ENXIO;         * Resolve the device.  If the vnode is already open v_rdev may
          * already be resolved.  However, if the device changes out from
          * under us we report it (and, for now, we allow it).
          */
         if (vp->v_rdev != NULL) {
                 dev = udev2dev(vp->v_udev, isblk);
                 if (dev != vp->v_rdev) {
                         printf(
                             "Warning: spec_open: dev %s was lost",
                             vp->v_rdev->si_name);
                         v_release_rdev(vp);
                         error = v_associate_rdev(vp, 
                                         udev2dev(vp->v_udev, isblk));
                         if (error)
                                 printf(", reacquisition failed\n");
                         else
                                 printf(", reacquisition successful\n");
                 } else {
                         error = 0;
                 }
         } else {
                 error = v_associate_rdev(vp, udev2dev(vp->v_udev, isblk));
         }
         if (error)
                 return(error);
 
         dev = vp->v_rdev;
   
        /* Make this field valid before any I/O in ->d_open */        /*
          * Make this field valid before any I/O in ->d_open.  XXX the
          * device itself should probably be required to initialize
          * this field in d_open.
          */
         if (!dev->si_iosize_max)          if (!dev->si_iosize_max)
                 dev->si_iosize_max = DFLTPHYS;                  dev->si_iosize_max = DFLTPHYS;
   
Line 163  spec_open(struct vop_open_args *ap) Line 196  spec_open(struct vop_open_args *ap)
                 /*                  /*
                  * Never allow opens for write if the device is mounted R/W                   * Never allow opens for write if the device is mounted R/W
                  */                   */
                if (vp->v_specmountpoint != NULL &&                if (vp->v_rdev && vp->v_rdev->si_mountpoint &&
                    !(vp->v_specmountpoint->mnt_flag & MNT_RDONLY))                    !(vp->v_rdev->si_mountpoint->mnt_flag & MNT_RDONLY)) {
                                return (EBUSY);                                error = EBUSY;
                                 goto done;
                 }
   
                 /*                  /*
                  * When running in secure mode, do not allow opens                   * When running in secure mode, do not allow opens
                  * for writing if the device is mounted                   * for writing if the device is mounted
                  */                   */
                if (securelevel >= 1 && vp->v_specmountpoint != NULL)                if (securelevel >= 1 && vfs_mountedon(vp)) {
                        return (EPERM);                        error = EPERM;
                         goto done;
                 }
   
                 /*                  /*
                  * When running in very secure mode, do not allow                   * When running in very secure mode, do not allow
                  * opens for writing of any devices.                   * opens for writing of any devices.
                  */                   */
                if (securelevel >= 2)                if (securelevel >= 2) {
                        return (EPERM);                        error = EPERM;
                         goto done;
                 }
         }          }
   
         /* XXX: Special casing of ttys for deadfs.  Probably redundant */          /* XXX: Special casing of ttys for deadfs.  Probably redundant */
         if (dev_dflags(dev) & D_TTY)          if (dev_dflags(dev) & D_TTY)
                 vp->v_flag |= VISTTY;                  vp->v_flag |= VISTTY;
   
           /*
            * dev_dopen() is always called for each open.  dev_dclose() is
            * only called for the last close unless D_TRACKCLOSE is set.
            */
         VOP_UNLOCK(vp, NULL, 0, ap->a_td);          VOP_UNLOCK(vp, NULL, 0, ap->a_td);
         error = dev_dopen(dev, ap->a_mode, S_IFCHR, ap->a_td);          error = dev_dopen(dev, ap->a_mode, S_IFCHR, ap->a_td);
         vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, ap->a_td);          vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, ap->a_td);
   
         if (error)          if (error)
                return (error);                goto done;
   
         if (dev_dflags(dev) & D_TTY) {          if (dev_dflags(dev) & D_TTY) {
                 if (dev->si_tty) {                  if (dev->si_tty) {
Line 215  spec_open(struct vop_open_args *ap) Line 258  spec_open(struct vop_open_args *ap)
                             dev_dname(dev), cp);                              dev_dname(dev), cp);
                 }                  }
         }          }
           ++vp->v_opencount;
           if (dev_ref_debug)
                   printf("spec_open: %s %d\n", dev->si_name, vp->v_opencount);
   done:
           if (error) {
                   if (vp->v_opencount == 0)
                           v_release_rdev(vp);
           }
         return (error);          return (error);
 }  }
   
Line 430  spec_strategy(struct vop_strategy_args * Line 481  spec_strategy(struct vop_strategy_args *
          * and write counts for disks that have associated filesystems.           * and write counts for disks that have associated filesystems.
          */           */
         vp = ap->a_vp;          vp = ap->a_vp;
        if (vn_isdisk(vp, NULL) && (mp = vp->v_specmountpoint) != NULL) {        if (vn_isdisk(vp, NULL) && (mp = vp->v_rdev->si_mountpoint) != NULL) {
                 if ((bp->b_flags & B_READ) == 0) {                  if ((bp->b_flags & B_READ) == 0) {
                         if (bp->b_lock.lk_lockholder == LK_KERNTHREAD)                          if (bp->b_lock.lk_lockholder == LK_KERNTHREAD)
                                 mp->mnt_stat.f_asyncwrites++;                                  mp->mnt_stat.f_asyncwrites++;
Line 443  spec_strategy(struct vop_strategy_args * Line 494  spec_strategy(struct vop_strategy_args *
                                 mp->mnt_stat.f_syncreads++;                                  mp->mnt_stat.f_syncreads++;
                 }                  }
         }          }
#if 0        bp->b_dev = vp->v_rdev;
        KASSERT(devsw(bp->b_dev) != NULL,  
           ("No devsw on dev %s responsible for buffer %p\n",  
           devtoname(bp->b_dev), bp)); 
        KASSERT(devsw(bp->b_dev)->d_strategy != NULL,  
           ("No strategy on dev %s responsible for buffer %p\n",  
           devtoname(bp->b_dev), bp)); 
#endif 
         BUF_STRATEGY(bp, 0);          BUF_STRATEGY(bp, 0);
         return (0);          return (0);
 }  }
Line 520  spec_close(struct vop_close_args *ap) Line 564  spec_close(struct vop_close_args *ap)
         struct proc *p = ap->a_td->td_proc;          struct proc *p = ap->a_td->td_proc;
         struct vnode *vp = ap->a_vp;          struct vnode *vp = ap->a_vp;
         dev_t dev = vp->v_rdev;          dev_t dev = vp->v_rdev;
           int error;
   
         /*          /*
          * Hack: a tty device that is a controlling terminal           * Hack: a tty device that is a controlling terminal
Line 530  spec_close(struct vop_close_args *ap) Line 575  spec_close(struct vop_close_args *ap)
          * if the reference count is 2 (this last descriptor           * if the reference count is 2 (this last descriptor
          * plus the session), release the reference from the session.           * plus the session), release the reference from the session.
          */           */
        if (vcount(vp) == 2 && p && (vp->v_flag & VXLOCK) == 0 &&        reference_dev(dev);
            vp == p->p_session->s_ttyvp) {        if (vcount(vp) == 2 && vp->v_opencount == 1 && 
             p && (vp->v_flag & VXLOCK) == 0 && vp == p->p_session->s_ttyvp) {
                 vrele(vp);                  vrele(vp);
                 p->p_session->s_ttyvp = NULL;                  p->p_session->s_ttyvp = NULL;
         }          }
   
         /*          /*
         * We do not want to really close the device if it         * Vnodes can be opened and close multiple times.  Do not really
         * is still in use unless we are trying to close it         * close the device unless (1) it is being closed forcibly,
         * forcibly. Since every use (buffer, vnode, swap, cmap)         * (2) the device wants to track closes, or (3) this is the last
         * holds a reference to the vnode, and because we mark         * vnode doing its last close on the device.
         * any other vnodes that alias this device, when the         *
         * sum of the reference counts on all the aliased         * XXX the VXLOCK (force close) case can leave vnodes referencing
         * vnodes descends to one, we are on last close.         * a closed device.
         */         */
        if (vp->v_flag & VXLOCK) {        if ((vp->v_flag & VXLOCK) ||
                /* Forced close */            (dev_dflags(dev) & D_TRACKCLOSE) ||
        } else if (dev_dflags(dev) & D_TRACKCLOSE) {            (vcount(vp) <= 1 && vp->v_opencount == 1)) {
                /* Keep device updated on status */                error = dev_dclose(dev, ap->a_fflag, S_IFCHR, ap->a_td);
        } else if (vcount(vp) > 1) {        } else {
                return (0);                error = 0;
         }          }
        return (dev_dclose(dev, ap->a_fflag, S_IFCHR, ap->a_td));
         /*
          * Track the actual opens and closes on the vnode.  The last close
          * disassociates the rdev.
          */
         KKASSERT(vp->v_opencount > 0);
         if (dev_ref_debug)
                 printf("spec_close: %s %d\n", dev->si_name, vp->v_opencount - 1);
         if (--vp->v_opencount == 0)
                 v_release_rdev(vp);
         release_dev(dev);
         return(error);
 }  }
   
 /*  /*
Line 631  spec_getpages(struct vop_getpages_args * Line 689  spec_getpages(struct vop_getpages_args *
          * the device.  i.e. it's usually '/dev'.  We need the physical block           * the device.  i.e. it's usually '/dev'.  We need the physical block
          * size for the device itself.           * size for the device itself.
          *           *
         * We can't use v_specmountpoint because it only exists when the         * We can't use v_rdev->si_mountpoint because it only exists when the
          * block device is mounted.  However, we can use v_rdev.           * block device is mounted.  However, we can use v_rdev.
          */           */
   

Removed from v.1.14  
changed lines
  Added in v.1.15