Diff for /src/sys/kern/subr_disk.c between versions 1.9 and 1.10

version 1.9, 2004/04/20 01:52:22 version 1.10, 2004/05/19 22:52:58
Line 6 Line 6
  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp   * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
  * ----------------------------------------------------------------------------   * ----------------------------------------------------------------------------
  *   *
    * Copyright (c) 2004 Matthew Dillon.
  * Copyright (c) 1982, 1986, 1988, 1993   * Copyright (c) 1982, 1986, 1988, 1993
  *      The Regents of the University of California.  All rights reserved.   *      The Regents of the University of California.  All rights reserved.
  * (c) UNIX System Laboratories, Inc.   * (c) UNIX System Laboratories, Inc.
Line 75  static d_open_t diskopen; Line 76  static d_open_t diskopen;
 static d_close_t diskclose;   static d_close_t diskclose; 
 static d_ioctl_t diskioctl;  static d_ioctl_t diskioctl;
 static d_psize_t diskpsize;  static d_psize_t diskpsize;
   static d_clone_t diskclone;
 static int disk_putport(lwkt_port_t port, lwkt_msg_t msg);  static int disk_putport(lwkt_port_t port, lwkt_msg_t msg);
   
 static LIST_HEAD(, disk) disklist = LIST_HEAD_INITIALIZER(&disklist);  static LIST_HEAD(, disk) disklist = LIST_HEAD_INITIALIZER(&disklist);
   
 static void  
 inherit_raw(dev_t pdev, dev_t dev)  
 {  
         dev->si_disk = pdev->si_disk;  
         dev->si_drv1 = pdev->si_drv1;  
         dev->si_drv2 = pdev->si_drv2;  
         dev->si_iosize_max = pdev->si_iosize_max;  
         dev->si_bsize_phys = pdev->si_bsize_phys;  
         dev->si_bsize_best = pdev->si_bsize_best;  
 }  
   
 /*  /*
 * Create a slice and unit managed disk.  The underlying raw disk device * Create a slice and unit managed disk.
 * is specified by cdevsw.  We create the device as a managed device by *
 * first creating it normally then overriding the message port with our * Our port layer will be responsible for assigning pblkno and handling
 * own frontend (which will be responsible for assigning pblkno). * high level partition operations, then forwarding the requests to the
  * raw device.
  *
  * The raw device (based on rawsw) is returned to the caller, NOT the
  * slice and unit managed cdev.  The caller typically sets various
  * driver parameters and IO limits on the returned rawdev which we must
  * inherit when our managed device is opened.
  */   */
 dev_t  dev_t
disk_create(int unit, struct disk *dp, int flags, struct cdevsw *cdevsw)disk_create(int unit, struct disk *dp, int flags, struct cdevsw *rawsw)
 {  {
        dev_t dev;        dev_t rawdev;
         struct cdevsw *devsw;
 
         /*
          * Create the raw backing device
          */
         compile_devsw(rawsw);
         rawdev = make_dev(rawsw,
                             dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART),
                             UID_ROOT, GID_OPERATOR, 0640,
                             "%s%d", rawsw->d_name, unit);
   
           /*
            * Initialize our intercept port
            */
         bzero(dp, sizeof(*dp));          bzero(dp, sizeof(*dp));
        lwkt_initport(&dp->d_port, NULL);       /* intercept port */        lwkt_initport(&dp->d_port, NULL);
         dp->d_port.mp_putport = disk_putport;          dp->d_port.mp_putport = disk_putport;
           dp->d_rawsw = rawsw;
   
        dev = makedev(cdevsw->d_maj, 0);        /* base device */        /*
        dev->si_disk = dp;         * We install a custom cdevsw rather then the passed cdevsw,
                                                /* forwarding port */         * and save our disk structure in d_data so we can get at it easily
        dp->d_fwdport = cdevsw_add_override(cdevsw, &dp->d_port);         * without any complex cloning code.
 
        if (bootverbose) 
                printf("Creating DISK %s%d\n", cdevsw->d_name, unit); 
 
        /* 
         * The whole disk placemarker holds the disk structure. 
          */           */
        dev = make_dev(cdevsw, dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART),        devsw = cdevsw_add_override(rawdev, dkunitmask(), dkmakeunit(unit));
            UID_ROOT, GID_OPERATOR, 0640, "%s%d", cdevsw->d_name, unit);        devsw->d_port = &dp->d_port;
        dev->si_disk = dp;        devsw->d_data = dp;
        dp->d_dev = dev;        devsw->d_clone = diskclone;
         dp->d_devsw = devsw;
         dp->d_rawdev = rawdev;
         dp->d_cdev = make_dev(devsw, 
                             dkmakeminor(unit, WHOLE_DISK_SLICE, RAW_PART),
                             UID_ROOT, GID_OPERATOR, 0640,
                             "%s%d", devsw->d_name, unit);
 
         dp->d_dsflags = flags;          dp->d_dsflags = flags;
         LIST_INSERT_HEAD(&disklist, dp, d_list);          LIST_INSERT_HEAD(&disklist, dp, d_list);
        return (dev);        return (dp->d_rawdev);
 }  }
   
   /*
    * This routine is called when an adapter detaches.  The higher level
    * managed disk device is destroyed while the lower level raw device is
    * released.
    */
 void  void
 disk_destroy(struct disk *disk)  disk_destroy(struct disk *disk)
 {  {
        dev_t dev = disk->d_dev;        if (disk->d_devsw) {
            cdevsw_remove(disk->d_devsw, dkunitmask(), dkunit(disk->d_cdev));
        LIST_REMOVE(disk, d_list);            LIST_REMOVE(disk, d_list);
         }
         if (disk->d_rawsw)
             destroy_all_dev(disk->d_rawsw, dkunitmask(), dkunit(disk->d_rawdev));
         bzero(disk, sizeof(*disk));          bzero(disk, sizeof(*disk));
         dev->si_disk = NULL;  
         destroy_dev(dev);  
         /* YYY remove cdevsw entries? */  
         return;  
 }  }
   
 int  int
Line 198  sysctl_disks(SYSCTL_HANDLER_ARGS) Line 214  sysctl_disks(SYSCTL_HANDLER_ARGS)
                 } else {                  } else {
                         first = 0;                          first = 0;
                 }                  }
                error = SYSCTL_OUT(req, disk->d_dev->si_name, strlen(disk->d_dev->si_name));                error = SYSCTL_OUT(req, disk->d_rawdev->si_name, strlen(disk->d_rawdev->si_name));
                 if (error)                  if (error)
                         return error;                          return error;
         }          }
Line 251  disk_putport(lwkt_port_t port, lwkt_msg_ Line 267  disk_putport(lwkt_port_t port, lwkt_msg_
                 msg->am_psize.result = diskpsize(msg->am_psize.msg.dev);                  msg->am_psize.result = diskpsize(msg->am_psize.msg.dev);
                 error = 0;      /* XXX */                  error = 0;      /* XXX */
                 break;                  break;
           case CDEV_CMD_READ:
                   error = physio(msg->am_read.msg.dev, 
                                   msg->am_read.uio, msg->am_read.ioflag);
                   break;
           case CDEV_CMD_WRITE:
                   error = physio(msg->am_write.msg.dev, 
                                   msg->am_write.uio, msg->am_write.ioflag);
                   break;
           case CDEV_CMD_POLL:
           case CDEV_CMD_KQFILTER:
                   error = ENODEV;
           case CDEV_CMD_MMAP:
                   error = -1;
                   break;
           case CDEV_CMD_DUMP:
                   error = disk_dumpcheck(msg->am_dump.msg.dev,
                                   &msg->am_dump.count,
                                   &msg->am_dump.blkno,
                                   &msg->am_dump.secsize);
                   if (error == 0) {
                           msg->am_dump.msg.dev = disk->d_rawdev;
                           error = lwkt_forwardmsg(disk->d_rawdev->si_port,
                                                   &msg->am_dump.msg.msg);
                           printf("error2 %d\n", error);
                   }
                   break;
         default:          default:
                error = lwkt_forwardmsg(disk->d_fwdport, &msg->am_lmsg);                error = ENOTSUP;
                 break;                  break;
         }          }
         return(error);          return(error);
 }  }
   
   /*
    * When new device entries are instantiated, make sure they inherit our
    * si_disk structure and block and iosize limits from the raw device.
    *
    * This routine is always called synchronously in the context of the 
    * client.
    *
    * XXX The various io and block size constraints are not always initialized
    * properly by devices.
    */
   static
   int
   diskclone(dev_t dev)
   {
           struct disk *dp;
   
           dp = dev->si_devsw->d_data;
           KKASSERT(dp != NULL);
           dev->si_disk = dp;
           dev->si_iosize_max = dp->d_rawdev->si_iosize_max;
           dev->si_bsize_phys = dp->d_rawdev->si_bsize_phys;
           dev->si_bsize_best = dp->d_rawdev->si_bsize_best;
           return(0);
   }
   
   /*
    * Open a disk device or partition.
    */
 static int  static int
 diskopen(dev_t dev, int oflags, int devtype, struct thread *td)  diskopen(dev_t dev, int oflags, int devtype, struct thread *td)
 {  {
         dev_t pdev;  
         struct disk *dp;          struct disk *dp;
         int error;          int error;
   
           /*
            * dp can't be NULL here XXX.
            */
         error = 0;          error = 0;
        pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);        dp = dev->si_disk;
 
        dp = pdev->si_disk; 
         if (dp == NULL)          if (dp == NULL)
                 return (ENXIO);                  return (ENXIO);
   
           /*
            * Deal with open races
            */
         while (dp->d_flags & DISKFLAG_LOCK) {          while (dp->d_flags & DISKFLAG_LOCK) {
                 dp->d_flags |= DISKFLAG_WANTED;                  dp->d_flags |= DISKFLAG_WANTED;
                 error = tsleep(dp, PCATCH, "diskopen", hz);                  error = tsleep(dp, PCATCH, "diskopen", hz);
Line 280  diskopen(dev_t dev, int oflags, int devt Line 353  diskopen(dev_t dev, int oflags, int devt
         }          }
         dp->d_flags |= DISKFLAG_LOCK;          dp->d_flags |= DISKFLAG_LOCK;
   
           /*
            * Open the underlying raw device.
            */
         if (!dsisopen(dp->d_slice)) {          if (!dsisopen(dp->d_slice)) {
   #if 0
                 if (!pdev->si_iosize_max)                  if (!pdev->si_iosize_max)
                         pdev->si_iosize_max = dev->si_iosize_max;                          pdev->si_iosize_max = dev->si_iosize_max;
                error = dev_port_dopen(dp->d_fwdport, pdev, oflags, devtype, td);#endif
                 error = dev_dopen(dp->d_rawdev, oflags, devtype, td);
         }          }
   
        /* Inherit properties from the whole/raw dev_t */        /*
        inherit_raw(pdev, dev);         * Inherit properties from the underlying device now that it is
          * open.
          */
         diskclone(dev);
   
         if (error)          if (error)
                 goto out;                  goto out;
Line 295  diskopen(dev_t dev, int oflags, int devt Line 376  diskopen(dev_t dev, int oflags, int devt
         error = dsopen(dev, devtype, dp->d_dsflags, &dp->d_slice, &dp->d_label);          error = dsopen(dev, devtype, dp->d_dsflags, &dp->d_slice, &dp->d_label);
   
         if (!dsisopen(dp->d_slice))           if (!dsisopen(dp->d_slice)) 
                dev_port_dclose(dp->d_fwdport, pdev, oflags, devtype, td);                dev_dclose(dp->d_rawdev, oflags, devtype, td);
 out:      out:    
         dp->d_flags &= ~DISKFLAG_LOCK;          dp->d_flags &= ~DISKFLAG_LOCK;
         if (dp->d_flags & DISKFLAG_WANTED) {          if (dp->d_flags & DISKFLAG_WANTED) {
Line 306  out: Line 387  out:
         return(error);          return(error);
 }  }
   
   /*
    * Close a disk device or partition
    */
 static int  static int
 diskclose(dev_t dev, int fflag, int devtype, struct thread *td)  diskclose(dev_t dev, int fflag, int devtype, struct thread *td)
 {  {
         struct disk *dp;          struct disk *dp;
         int error;          int error;
         dev_t pdev;  
   
         error = 0;          error = 0;
        pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);        dp = dev->si_disk;
        dp = pdev->si_disk;
        if (!dp) 
                return (ENXIO); 
         dsclose(dev, devtype, dp->d_slice);          dsclose(dev, devtype, dp->d_slice);
         if (!dsisopen(dp->d_slice))          if (!dsisopen(dp->d_slice))
                error = dev_port_dclose(dp->d_fwdport, pdev, fflag, devtype, td);                error = dev_dclose(dp->d_rawdev, fflag, devtype, td);
         return (error);          return (error);
 }  }
   
   /*
    * Execute strategy routine
    */
 static void  static void
 diskstrategy(struct buf *bp)  diskstrategy(struct buf *bp)
 {  {
         dev_t pdev;  
         struct disk *dp;          struct disk *dp;
   
        pdev = dkmodpart(dkmodslice(bp->b_dev, WHOLE_DISK_SLICE), RAW_PART);        dp = bp->b_dev->si_disk;
        dp = pdev->si_disk; 
        if (dp != bp->b_dev->si_disk) 
                inherit_raw(pdev, bp->b_dev); 
   
        if (!dp) {        if (dp == NULL) {
                 bp->b_error = ENXIO;                  bp->b_error = ENXIO;
                 bp->b_flags |= B_ERROR;                  bp->b_flags |= B_ERROR;
                 biodone(bp);                  biodone(bp);
                 return;                  return;
         }          }
           KKASSERT(bp->b_dev->si_disk == dp);
   
         if (dscheck(bp, dp->d_slice) <= 0) {          if (dscheck(bp, dp->d_slice) <= 0) {
                 biodone(bp);                  biodone(bp);
                 return;                  return;
         }          }
        dev_port_dstrategy(dp->d_fwdport, dp->d_dev, bp);        bp->b_dev = dp->d_rawdev;
         dev_dstrategy(dp->d_rawdev, bp);
 }  }
   
 /*  /*
 * note: when forwarding the ioctl we use the original device rather then * First execute the ioctl on the disk device, and if it isn't supported 
 * the whole disk slice. * try running it on the backing device.
  */   */
 static int  static int
 diskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)  diskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
 {  {
         struct disk *dp;          struct disk *dp;
         int error;          int error;
         dev_t pdev;  
   
        pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);        dp = dev->si_disk;
        dp = pdev->si_disk;        if (dp == NULL)
        if (!dp) 
                 return (ENXIO);                  return (ENXIO);
   
         error = dsioctl(dev, cmd, data, fflag, &dp->d_slice);          error = dsioctl(dev, cmd, data, fflag, &dp->d_slice);
         if (error == ENOIOCTL)          if (error == ENOIOCTL)
                error = dev_port_dioctl(dp->d_fwdport, dev, cmd, data, fflag, td);                error = dev_dioctl(dp->d_rawdev, cmd, data, fflag, td);
         return (error);          return (error);
 }  }
   
   /*
    *
    */
 static int  static int
 diskpsize(dev_t dev)  diskpsize(dev_t dev)
 {  {
         struct disk *dp;          struct disk *dp;
         dev_t pdev;  
   
        pdev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);        dp = dev->si_disk;
        dp = pdev->si_disk;        if (dp == NULL)
        if (!dp) 
                 return (-1);                  return (-1);
           return(dssize(dev, &dp->d_slice));
   #if 0
         if (dp != dev->si_disk) {          if (dp != dev->si_disk) {
                 dev->si_drv1 = pdev->si_drv1;                  dev->si_drv1 = pdev->si_drv1;
                 dev->si_drv2 = pdev->si_drv2;                  dev->si_drv2 = pdev->si_drv2;
                 /* XXX: don't set bp->b_dev->si_disk (?) */                  /* XXX: don't set bp->b_dev->si_disk (?) */
         }          }
        return (dssize(dev, &dp->d_slice));#endif
 }  }
   
 SYSCTL_DECL(_debug_sizeof);  SYSCTL_DECL(_debug_sizeof);
Line 520  bufqdisksort(bufq, bp) Line 604  bufqdisksort(bufq, bp)
  * Returns NULL on success and an error string on failure.   * Returns NULL on success and an error string on failure.
  */   */
 char *  char *
readdisklabel(dev, lp)readdisklabel(dev_t dev, struct disklabel *lp)
        dev_t dev; 
        struct disklabel *lp; 
 {  {
         struct buf *bp;          struct buf *bp;
         struct disklabel *dlp;          struct disklabel *dlp;
Line 613  setdisklabel(olp, nlp, openmask) Line 695  setdisklabel(olp, nlp, openmask)
  * Write disk label back to device after modification.   * Write disk label back to device after modification.
  */   */
 int  int
writedisklabel(dev, lp)writedisklabel(dev_t dev, struct disklabel *lp)
        dev_t dev; 
        struct disklabel *lp; 
 {  {
         struct buf *bp;          struct buf *bp;
         struct disklabel *dlp;          struct disklabel *dlp;
Line 650  writedisklabel(dev, lp) Line 730  writedisklabel(dev, lp)
                         *dlp = *lp;                          *dlp = *lp;
                         bp->b_flags &= ~(B_DONE | B_READ);                          bp->b_flags &= ~(B_DONE | B_READ);
                         bp->b_flags |= B_WRITE;                          bp->b_flags |= B_WRITE;
                           bp->b_dev = dkmodpart(dev, RAW_PART);
 #ifdef __alpha__  #ifdef __alpha__
                         alpha_fix_srm_checksum(bp);                          alpha_fix_srm_checksum(bp);
 #endif  #endif

Removed from v.1.9  
changed lines
  Added in v.1.10