Diff for /src/sys/kern/vfs_subr.c between versions 1.29 and 1.30

version 1.29, 2004/04/08 17:56:48 version 1.30, 2004/05/19 22:52:58
Line 192  static void vbusy(struct vnode *vp); Line 192  static void vbusy(struct vnode *vp);
 static void vfree(struct vnode *vp);  static void vfree(struct vnode *vp);
 static void vmaybefree(struct vnode *vp);  static void vmaybefree(struct vnode *vp);
   
   extern int dev_ref_debug;
   
 /*  /*
  * NOTE: the vnode interlock must be held on call.   * NOTE: the vnode interlock must be held on call.
  */   */
Line 1458  reassignbuf(bp, newvp) Line 1460  reassignbuf(bp, newvp)
                                 break;                                  break;
                         case VCHR:                          case VCHR:
                         case VBLK:                          case VBLK:
                                 if (newvp->v_specmountpoint != NULL) {                                  if (newvp->v_rdev && 
                                       newvp->v_rdev->si_mountpoint != NULL) {
                                         delay = metadelay;                                          delay = metadelay;
                                         break;                                          break;
                                 }                                  }
Line 1541  reassignbuf(bp, newvp) Line 1544  reassignbuf(bp, newvp)
  * Used for mounting the root file system.   * Used for mounting the root file system.
  */   */
 int  int
 bdevvp(dev, vpp)  bdevvp(dev_t dev, struct vnode **vpp)
         dev_t dev;  
         struct vnode **vpp;  
 {  {
         struct vnode *vp;          struct vnode *vp;
         struct vnode *nvp;          struct vnode *nvp;
Line 1559  bdevvp(dev, vpp) Line 1560  bdevvp(dev, vpp)
                 return (error);                  return (error);
         }          }
         vp = nvp;          vp = nvp;
         vp->v_type = VBLK;          vp->v_type = VCHR;
         addalias(vp, dev);          vp->v_udev = dev->si_udev;
         *vpp = vp;          *vpp = vp;
         return (0);          return (0);
 }  }
   
 /*  int
  * Add a vnode to the alias list hung off the dev_t.  v_associate_rdev(struct vnode *vp, dev_t dev)
  *  
  * The reason for this gunk is that multiple vnodes can reference  
  * the same physical device, so checking vp->v_usecount to see  
  * how many users there are is inadequate; the v_usecount for  
  * the vnodes need to be accumulated.  vcount() does that.  
  */  
 void  
 addaliasu(struct vnode *nvp, udev_t nvp_rdev)  
 {  {
         dev_t dev;          lwkt_tokref ilock;
   
         if (nvp->v_type != VBLK && nvp->v_type != VCHR)          if (dev == NULL || dev == NODEV)
                 panic("addaliasu on non-special vnode");                  return(ENXIO);
         dev = udev2dev(nvp_rdev, nvp->v_type == VBLK ? 1 : 0);          if (dev_is_good(dev) == 0)
         if (dev != NODEV) {                  return(ENXIO);
                 nvp->v_rdev = dev;          KKASSERT(vp->v_rdev == NULL);
                 addalias(nvp, dev);          if (dev_ref_debug)
         } else                  printf("Z1");
                 nvp->v_rdev = NULL;          vp->v_rdev = reference_dev(dev);
           lwkt_gettoken(&ilock, &spechash_token);
           SLIST_INSERT_HEAD(&dev->si_hlist, vp, v_specnext);
           lwkt_reltoken(&ilock);
           return(0);
 }  }
   
 void  void
 addalias(struct vnode *nvp, dev_t dev)  v_release_rdev(struct vnode *vp)
 {  {
         lwkt_tokref ilock;          lwkt_tokref ilock;
           dev_t dev;
   
         if (nvp->v_type != VBLK && nvp->v_type != VCHR)          if ((dev = vp->v_rdev) != NULL) {
                 panic("addalias on non-special vnode");                  lwkt_gettoken(&ilock, &spechash_token);
                   SLIST_REMOVE(&dev->si_hlist, vp, vnode, v_specnext);
                   if (dev_ref_debug)
                           printf("Y2");
                   vp->v_rdev = NULL;
                   release_dev(dev);
                   lwkt_reltoken(&ilock);
           }
   }
   
         nvp->v_rdev = dev;  /*
         lwkt_gettoken(&ilock, &spechash_token);   * Add a vnode to the alias list hung off the dev_t.  We only associate
         SLIST_INSERT_HEAD(&dev->si_hlist, nvp, v_specnext);   * the device number with the vnode.  The actual device is not associated
         lwkt_reltoken(&ilock);   * until the vnode is opened (usually in spec_open()), and will be 
    * disassociated on last close.
    */
   void
   addaliasu(struct vnode *nvp, udev_t nvp_udev)
   {
           if (nvp->v_type != VBLK && nvp->v_type != VCHR)
                   panic("addaliasu on non-special vnode");
           nvp->v_udev = nvp_udev;
 }  }
   
 /*  /*
Line 2150  vop_revoke(ap) Line 2164  vop_revoke(ap)
                 tsleep((caddr_t)vp, 0, "vop_revokeall", 0);                  tsleep((caddr_t)vp, 0, "vop_revokeall", 0);
                 return (0);                  return (0);
         }          }
         dev = vp->v_rdev;  
           /*
            * If the vnode has a device association, scrap all vnodes associated
            * with the device.  Don't let the device disappear on us while we
            * are scrapping the vnodes.
            */
           if (vp->v_type != VCHR && vp->v_type != VBLK)
                   return(0);
           if ((dev = vp->v_rdev) == NULL) {
                   if ((dev = udev2dev(vp->v_udev, vp->v_type == VBLK)) == NODEV)
                           return(0);
           }
           reference_dev(dev);
         for (;;) {          for (;;) {
                 lwkt_gettoken(&ilock, &spechash_token);                  lwkt_gettoken(&ilock, &spechash_token);
                 vq = SLIST_FIRST(&dev->si_hlist);                  vq = SLIST_FIRST(&dev->si_hlist);
                 lwkt_reltoken(&ilock);                  lwkt_reltoken(&ilock);
                 if (!vq)                  if (vq == NULL)
                         break;                          break;
                 vgone(vq);                  vgone(vq);
         }          }
           release_dev(dev);
         return (0);          return (0);
 }  }
   
Line 2232  vgonel(struct vnode *vp, lwkt_tokref_t v Line 2259  vgonel(struct vnode *vp, lwkt_tokref_t v
          * if it is on one.           * if it is on one.
          */           */
         if ((vp->v_type == VBLK || vp->v_type == VCHR) && vp->v_rdev != NULL) {          if ((vp->v_type == VBLK || vp->v_type == VCHR) && vp->v_rdev != NULL) {
                 lwkt_gettoken(&ilock, &spechash_token);                  v_release_rdev(vp);
                 SLIST_REMOVE(&vp->v_hashchain, vp, vnode, v_specnext);  
                 freedev(vp->v_rdev);  
                 lwkt_reltoken(&ilock);  
                 vp->v_rdev = NULL;  
         }          }
   
         /*          /*
Line 2290  vfinddev(dev, type, vpp) Line 2313  vfinddev(dev, type, vpp)
 }  }
   
 /*  /*
  * Calculate the total number of references to a special device.   * Calculate the total number of references to a special device.  This
    * routine may only be called for VBLK and VCHR vnodes since v_rdev is
    * an overloaded field.  Since udev2dev can now return NODEV, we have
    * to check for a NULL v_rdev.
  */   */
 int  int
 vcount(vp)  count_dev(dev_t dev)
         struct vnode *vp;  
 {  {
         lwkt_tokref ilock;          lwkt_tokref ilock;
         struct vnode *vq;          struct vnode *vp;
         int count;          int count = 0;
   
         count = 0;          if (SLIST_FIRST(&dev->si_hlist)) {
         lwkt_gettoken(&ilock, &spechash_token);                  lwkt_gettoken(&ilock, &spechash_token);
         SLIST_FOREACH(vq, &vp->v_hashchain, v_specnext)                  SLIST_FOREACH(vp, &dev->si_hlist, v_specnext) {
                 count += vq->v_usecount;                          count += vp->v_usecount;
         lwkt_reltoken(&ilock);                  }
         return (count);                  lwkt_reltoken(&ilock);
           }
           return(count);
 }  }
   
 /*  
  * Same as above, but using the dev_t as argument  
  */  
   
 int  int
 count_dev(dev)  count_udev(udev_t udev)
         dev_t dev;  
 {  {
         struct vnode *vp;          dev_t dev;
   
         vp = SLIST_FIRST(&dev->si_hlist);          if ((dev = udev2dev(udev, 0)) == NODEV)
         if (vp == NULL)                  return(0);
                 return (0);          return(count_dev(dev));
         return(vcount(vp));  }
   
   int
   vcount(struct vnode *vp)
   {
           if (vp->v_rdev == NULL)
                   return(0);
           return(count_dev(vp->v_rdev));
 }  }
   
 /*  /*
Line 2557  SYSCTL_PROC(_kern, KERN_VNODE, vnode, CT Line 2586  SYSCTL_PROC(_kern, KERN_VNODE, vnode, CT
  * Check to see if a filesystem is mounted on a block device.   * Check to see if a filesystem is mounted on a block device.
  */   */
 int  int
 vfs_mountedon(vp)  vfs_mountedon(struct vnode *vp)
         struct vnode *vp;  
 {  {
           dev_t dev;
   
         if (vp->v_specmountpoint != NULL)          if ((dev = vp->v_rdev) == NULL)
                   dev = udev2dev(vp->v_udev, (vp->v_type == VBLK));
           if (dev != NODEV && dev->si_mountpoint)
                 return (EBUSY);                  return (EBUSY);
         return (0);          return (0);
 }  }
Line 3266  sync_print(ap) Line 3297  sync_print(ap)
 }  }
   
 /*  /*
  * extract the dev_t from a VBLK or VCHR   * extract the dev_t from a VBLK or VCHR.  The vnode must have been opened
    * (or v_rdev might be NULL).
  */   */
 dev_t  dev_t
 vn_todev(vp)  vn_todev(struct vnode *vp)
         struct vnode *vp;  
 {  {
         if (vp->v_type != VBLK && vp->v_type != VCHR)          if (vp->v_type != VBLK && vp->v_type != VCHR)
                 return (NODEV);                  return (NODEV);
           KKASSERT(vp->v_rdev != NULL);
         return (vp->v_rdev);          return (vp->v_rdev);
 }  }
   
 /*  /*
  * Check if vnode represents a disk device   * Check if vnode represents a disk device.  The vnode does not need to be
    * opened.
  */   */
 int  int
 vn_isdisk(vp, errp)  vn_isdisk(struct vnode *vp, int *errp)
         struct vnode *vp;  
         int *errp;  
 {  {
           dev_t dev;
   
         if (vp->v_type != VBLK && vp->v_type != VCHR) {          if (vp->v_type != VBLK && vp->v_type != VCHR) {
                 if (errp != NULL)                  if (errp != NULL)
                         *errp = ENOTBLK;                          *errp = ENOTBLK;
                 return (0);                  return (0);
         }          }
         if (vp->v_rdev == NULL) {  
           if ((dev = vp->v_rdev) == NULL)
                   dev = udev2dev(vp->v_udev, (vp->v_type == VBLK));
           if (dev == NULL || dev == NODEV) {
                 if (errp != NULL)                  if (errp != NULL)
                         *errp = ENXIO;                          *errp = ENXIO;
                 return (0);                  return (0);
         }          }
         if (!dev_dport(vp->v_rdev)) {          if (dev_is_good(dev) == 0) {
                 if (errp != NULL)                  if (errp != NULL)
                         *errp = ENXIO;                          *errp = ENXIO;
                 return (0);                  return (0);
         }          }
         if (!(dev_dflags(vp->v_rdev) & D_DISK)) {          if ((dev_dflags(dev) & D_DISK) == 0) {
                 if (errp != NULL)                  if (errp != NULL)
                         *errp = ENOTBLK;                          *errp = ENOTBLK;
                 return (0);                  return (0);

Removed from v.1.29  
changed lines
  Added in v.1.30