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