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