[BACK]Return to rf_netbsdkintf.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / raidframe

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/dev/raidframe/rf_netbsdkintf.c between version 1.356.4.4 and 1.357

version 1.356.4.4, 2020/04/21 18:42:37 version 1.357, 2019/01/08 07:18:18
Line 104 
Line 104 
 __KERNEL_RCSID(0, "$NetBSD$");  __KERNEL_RCSID(0, "$NetBSD$");
   
 #ifdef _KERNEL_OPT  #ifdef _KERNEL_OPT
 #include "opt_raid_autoconfig.h"  #include "opt_compat_netbsd.h"
 #include "opt_compat_netbsd32.h"  #include "opt_compat_netbsd32.h"
   #include "opt_raid_autoconfig.h"
 #endif  #endif
   
 #include <sys/param.h>  #include <sys/param.h>
Line 127  __KERNEL_RCSID(0, "$NetBSD$");
Line 128  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/reboot.h>  #include <sys/reboot.h>
 #include <sys/kauth.h>  #include <sys/kauth.h>
 #include <sys/module.h>  #include <sys/module.h>
 #include <sys/compat_stub.h>  
   
 #include <prop/proplib.h>  #include <prop/proplib.h>
   
Line 149  __KERNEL_RCSID(0, "$NetBSD$");
Line 149  __KERNEL_RCSID(0, "$NetBSD$");
 #include "rf_parityscan.h"  #include "rf_parityscan.h"
 #include "rf_threadstuff.h"  #include "rf_threadstuff.h"
   
   #ifdef COMPAT_50
   #include "rf_compat50.h"
   #endif
   
   #ifdef COMPAT_80
   #include "rf_compat80.h"
   #endif
   
   #ifdef COMPAT_NETBSD32
   #include "rf_compat32.h"
   #endif
   
 #include "ioconf.h"  #include "ioconf.h"
   
 #ifdef DEBUG  #ifdef DEBUG
Line 182  static void KernelWakeupFunc(struct buf 
Line 194  static void KernelWakeupFunc(struct buf 
 static void InitBP(struct buf *, struct vnode *, unsigned,  static void InitBP(struct buf *, struct vnode *, unsigned,
     dev_t, RF_SectorNum_t, RF_SectorCount_t, void *, void (*) (struct buf *),      dev_t, RF_SectorNum_t, RF_SectorCount_t, void *, void (*) (struct buf *),
     void *, int, struct proc *);      void *, int, struct proc *);
   struct raid_softc;
 static void raidinit(struct raid_softc *);  static void raidinit(struct raid_softc *);
 static int raiddoaccess(RF_Raid_t *raidPtr, struct buf *bp);  static int raiddoaccess(RF_Raid_t *raidPtr, struct buf *bp);
 static int rf_get_component_caches(RF_Raid_t *raidPtr, int *);  static int rf_get_component_caches(RF_Raid_t *raidPtr, int *);
Line 249  static struct dkdriver rf_dkdriver = {
Line 262  static struct dkdriver rf_dkdriver = {
         .d_minphys = minphys          .d_minphys = minphys
 };  };
   
   struct raid_softc {
           struct dk_softc sc_dksc;
           int     sc_unit;
           int     sc_flags;       /* flags */
           int     sc_cflags;      /* configuration flags */
           kmutex_t sc_mutex;      /* interlock mutex */
           kcondvar_t sc_cv;       /* and the condvar */
           uint64_t sc_size;       /* size of the raid device */
           char    sc_xname[20];   /* XXX external name */
           RF_Raid_t sc_r;
           LIST_ENTRY(raid_softc) sc_link;
   };
   /* sc_flags */
   #define RAIDF_INITED            0x01    /* unit has been initialized */
   #define RAIDF_SHUTDOWN          0x02    /* unit is being shutdown */
   #define RAIDF_DETACH            0x04    /* detach after final close */
   #define RAIDF_WANTED            0x08    /* someone waiting to obtain a lock */
   #define RAIDF_LOCKED            0x10    /* unit is locked */
   #define RAIDF_UNIT_CHANGED      0x20    /* unit is being changed */
   
 #define raidunit(x)     DISKUNIT(x)  #define raidunit(x)     DISKUNIT(x)
 #define raidsoftc(dev)  (((struct raid_softc *)device_private(dev))->sc_r.softc)  #define raidsoftc(dev)  (((struct raid_softc *)device_private(dev))->sc_r.softc)
   
Line 370  raidget(int unit, bool create) {
Line 403  raidget(int unit, bool create) {
         mutex_exit(&raid_lock);          mutex_exit(&raid_lock);
         if (!create)          if (!create)
                 return NULL;                  return NULL;
         sc = raidcreate(unit);          if ((sc = raidcreate(unit)) == NULL)
                   return NULL;
         mutex_enter(&raid_lock);          mutex_enter(&raid_lock);
         LIST_INSERT_HEAD(&raids, sc, sc_link);          LIST_INSERT_HEAD(&raids, sc, sc_link);
         mutex_exit(&raid_lock);          mutex_exit(&raid_lock);
Line 433  rf_autoconfig(device_t self)
Line 467  rf_autoconfig(device_t self)
         return 1;          return 1;
 }  }
   
 int  
 rf_inited(const struct raid_softc *rs) {  
         return (rs->sc_flags & RAIDF_INITED) != 0;  
 }  
   
 RF_Raid_t *  
 rf_get_raid(struct raid_softc *rs) {  
         return &rs->sc_r;  
 }  
   
 int  
 rf_get_unit(const struct raid_softc *rs) {  
         return rs->sc_unit;  
 }  
   
 static int  static int
 rf_containsboot(RF_Raid_t *r, device_t bdv) {  rf_containsboot(RF_Raid_t *r, device_t bdv) {
         const char *bootname;          const char *bootname = device_xname(bdv);
         size_t len;          size_t len = strlen(bootname);
   
         /* if bdv is NULL, the set can't contain it. exit early. */  
         if (bdv == NULL)  
                 return 0;  
   
         bootname = device_xname(bdv);  
         len = strlen(bootname);  
   
         for (int col = 0; col < r->numCol; col++) {          for (int col = 0; col < r->numCol; col++) {
                 const char *devname = r->Disks[col].devname;                  const char *devname = r->Disks[col].devname;
Line 486  rf_buildroothack(RF_ConfigSet_t *config_
Line 498  rf_buildroothack(RF_ConfigSet_t *config_
         RF_ConfigSet_t *next_cset;          RF_ConfigSet_t *next_cset;
         int num_root;          int num_root;
         struct raid_softc *sc, *rsc;          struct raid_softc *sc, *rsc;
         struct dk_softc *dksc = NULL;   /* XXX gcc -Os: may be used uninit. */          struct dk_softc *dksc;
   
         sc = rsc = NULL;          sc = rsc = NULL;
         num_root = 0;          num_root = 0;
Line 497  rf_buildroothack(RF_ConfigSet_t *config_
Line 509  rf_buildroothack(RF_ConfigSet_t *config_
                     cset->ac->clabel->autoconfigure == 1) {                      cset->ac->clabel->autoconfigure == 1) {
                         sc = rf_auto_config_set(cset);                          sc = rf_auto_config_set(cset);
                         if (sc != NULL) {                          if (sc != NULL) {
                                 aprint_debug("raid%d: configured ok, rootable %d\n",                                  aprint_debug("raid%d: configured ok\n",
                                     sc->sc_unit, cset->rootable);                                      sc->sc_unit);
                                 if (cset->rootable) {                                  if (cset->rootable) {
                                         rsc = sc;                                          rsc = sc;
                                         num_root++;                                          num_root++;
Line 517  rf_buildroothack(RF_ConfigSet_t *config_
Line 529  rf_buildroothack(RF_ConfigSet_t *config_
                 rf_cleanup_config_set(cset);                  rf_cleanup_config_set(cset);
                 cset = next_cset;                  cset = next_cset;
         }          }
           dksc = &rsc->sc_dksc;
   
         /* if the user has specified what the root device should be          /* if the user has specified what the root device should be
            then we don't touch booted_device or boothowto... */             then we don't touch booted_device or boothowto... */
   
         if (rootspec != NULL) {          if (rootspec != NULL)
                 DPRINTF("%s: rootspec %s\n", __func__, rootspec);  
                 return;                  return;
         }  
   
         /* we found something bootable... */          /* we found something bootable... */
   
Line 541  rf_buildroothack(RF_ConfigSet_t *config_
Line 552  rf_buildroothack(RF_ConfigSet_t *config_
          */           */
         if (num_root == 1) {          if (num_root == 1) {
                 device_t candidate_root;                  device_t candidate_root;
                 dksc = &rsc->sc_dksc;  
                 if (dksc->sc_dkdev.dk_nwedges != 0) {                  if (dksc->sc_dkdev.dk_nwedges != 0) {
                         char cname[sizeof(cset->ac->devname)];                          char cname[sizeof(cset->ac->devname)];
                         /* XXX: assume partition 'a' first */                          /* XXX: assume partition 'a' first */
Line 567  rf_buildroothack(RF_ConfigSet_t *config_
Line 577  rf_buildroothack(RF_ConfigSet_t *config_
                         candidate_root = dksc->sc_dev;                          candidate_root = dksc->sc_dev;
                 DPRINTF("%s: candidate root=%p\n", __func__, candidate_root);                  DPRINTF("%s: candidate root=%p\n", __func__, candidate_root);
                 DPRINTF("%s: booted_device=%p root_partition=%d "                  DPRINTF("%s: booted_device=%p root_partition=%d "
                         "contains_boot=%d",                     "contains_boot=%d\n", __func__, booted_device,
                     __func__, booted_device, rsc->sc_r.root_partition,                     rsc->sc_r.root_partition,
                            rf_containsboot(&rsc->sc_r, booted_device));                     rf_containsboot(&rsc->sc_r, booted_device));
                 /* XXX the check for booted_device == NULL can probably be  
                  * dropped, now that rf_containsboot handles that case.  
                  */  
                 if (booted_device == NULL ||                  if (booted_device == NULL ||
                     rsc->sc_r.root_partition == 1 ||                      rsc->sc_r.root_partition == 1 ||
                     rf_containsboot(&rsc->sc_r, booted_device)) {                      rf_containsboot(&rsc->sc_r, booted_device)) {
Line 662  raiddump(dev_t dev, daddr_t blkno, void 
Line 669  raiddump(dev_t dev, daddr_t blkno, void 
         */          */
         blkno += RF_PROTECTED_SECTORS;          blkno += RF_PROTECTED_SECTORS;
   
         return dk_dump(dksc, dev, blkno, va, size, DK_DUMP_RECURSIVE);          return dk_dump(dksc, dev, blkno, va, size);
 }  }
   
 static int  static int
Line 1033  raid_detach_unlocked(struct raid_softc *
Line 1040  raid_detach_unlocked(struct raid_softc *
         return 0;          return 0;
 }  }
   
 static bool  static int
 rf_must_be_initialized(const struct raid_softc *rs, u_long cmd)  raidioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
 {  {
           int     unit = raidunit(dev);
           int     error = 0;
           int     part, pmask;
           struct raid_softc *rs;
           struct dk_softc *dksc;
           RF_Config_t *k_cfg, *u_cfg;
           RF_Raid_t *raidPtr;
           RF_RaidDisk_t *diskPtr;
           RF_AccTotals_t *totals;
           RF_DeviceConfig_t *d_cfg, *ucfgp;
           u_char *specific_buf;
           int retcode = 0;
           int column;
   /*      int raidid; */
           struct rf_recon_req *rr;
           struct rf_recon_req_internal *rrint;
           RF_ComponentLabel_t *clabel;
           RF_ComponentLabel_t *ci_label;
           RF_SingleComponent_t *sparePtr,*componentPtr;
           RF_SingleComponent_t component;
           int d;
   
           if ((rs = raidget(unit, false)) == NULL)
                   return ENXIO;
           dksc = &rs->sc_dksc;
           raidPtr = &rs->sc_r;
   
           db1_printf(("raidioctl: %d %d %d %lu\n", (int) dev,
                   (int) DISKPART(dev), (int) unit, cmd));
   
           /* Must be initialized for these... */
         switch (cmd) {          switch (cmd) {
           case RAIDFRAME_REWRITEPARITY:
           case RAIDFRAME_GET_INFO:
           case RAIDFRAME_RESET_ACCTOTALS:
           case RAIDFRAME_GET_ACCTOTALS:
           case RAIDFRAME_KEEP_ACCTOTALS:
           case RAIDFRAME_GET_SIZE:
           case RAIDFRAME_FAIL_DISK:
           case RAIDFRAME_COPYBACK:
           case RAIDFRAME_CHECK_RECON_STATUS:
           case RAIDFRAME_CHECK_RECON_STATUS_EXT:
           case RAIDFRAME_GET_COMPONENT_LABEL:
           case RAIDFRAME_SET_COMPONENT_LABEL:
         case RAIDFRAME_ADD_HOT_SPARE:          case RAIDFRAME_ADD_HOT_SPARE:
         case RAIDFRAME_CHECK_COPYBACK_STATUS:          case RAIDFRAME_REMOVE_HOT_SPARE:
         case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT:          case RAIDFRAME_INIT_LABELS:
           case RAIDFRAME_REBUILD_IN_PLACE:
         case RAIDFRAME_CHECK_PARITY:          case RAIDFRAME_CHECK_PARITY:
         case RAIDFRAME_CHECK_PARITYREWRITE_STATUS:          case RAIDFRAME_CHECK_PARITYREWRITE_STATUS:
         case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT:          case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT:
         case RAIDFRAME_CHECK_RECON_STATUS:          case RAIDFRAME_CHECK_COPYBACK_STATUS:
         case RAIDFRAME_CHECK_RECON_STATUS_EXT:          case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT:
         case RAIDFRAME_COPYBACK:          case RAIDFRAME_SET_AUTOCONFIG:
           case RAIDFRAME_SET_ROOT:
         case RAIDFRAME_DELETE_COMPONENT:          case RAIDFRAME_DELETE_COMPONENT:
         case RAIDFRAME_FAIL_DISK:  
         case RAIDFRAME_GET_ACCTOTALS:  
         case RAIDFRAME_GET_COMPONENT_LABEL:  
         case RAIDFRAME_GET_INFO:  
         case RAIDFRAME_GET_SIZE:  
         case RAIDFRAME_INCORPORATE_HOT_SPARE:          case RAIDFRAME_INCORPORATE_HOT_SPARE:
         case RAIDFRAME_INIT_LABELS:          case RAIDFRAME_PARITYMAP_STATUS:
         case RAIDFRAME_KEEP_ACCTOTALS:  
         case RAIDFRAME_PARITYMAP_GET_DISABLE:          case RAIDFRAME_PARITYMAP_GET_DISABLE:
         case RAIDFRAME_PARITYMAP_SET_DISABLE:          case RAIDFRAME_PARITYMAP_SET_DISABLE:
         case RAIDFRAME_PARITYMAP_SET_PARAMS:          case RAIDFRAME_PARITYMAP_SET_PARAMS:
         case RAIDFRAME_PARITYMAP_STATUS:  #ifdef COMPAT_50
         case RAIDFRAME_REBUILD_IN_PLACE:          case RAIDFRAME_GET_INFO50:
         case RAIDFRAME_REMOVE_HOT_SPARE:  #endif
         case RAIDFRAME_RESET_ACCTOTALS:  #ifdef COMPAT_80
         case RAIDFRAME_REWRITEPARITY:          case RAIDFRAME_CHECK_RECON_STATUS_EXT80:
         case RAIDFRAME_SET_AUTOCONFIG:          case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT80:
         case RAIDFRAME_SET_COMPONENT_LABEL:          case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT80:
         case RAIDFRAME_SET_ROOT:          case RAIDFRAME_GET_INFO80:
                 return (rs->sc_flags & RAIDF_INITED) == 0;          case RAIDFRAME_GET_COMPONENT_LABEL80:
         }  #endif
         return false;  #ifdef COMPAT_NETBSD32
 }  #ifdef _LP64
           case RAIDFRAME_GET_INFO32:
 int  #endif
 rf_fail_disk(RF_Raid_t *raidPtr, struct rf_recon_req *rr)  #endif
 {                  if ((rs->sc_flags & RAIDF_INITED) == 0)
         struct rf_recon_req_internal *rrint;                          return (ENXIO);
   
         if (raidPtr->Layout.map->faultsTolerated == 0) {  
                 /* Can't do this on a RAID 0!! */  
                 return EINVAL;  
         }          }
   
         if (rr->col < 0 || rr->col >= raidPtr->numCol) {          switch (cmd) {
                 /* bad column */  #ifdef COMPAT_50
                 return EINVAL;          case RAIDFRAME_GET_INFO50:
         }                  return rf_get_info50(raidPtr, data);
   
         rf_lock_mutex2(raidPtr->mutex);          case RAIDFRAME_CONFIGURE50:
         if (raidPtr->status == rf_rs_reconstructing) {                  if ((retcode = rf_config50(raidPtr, unit, data, &k_cfg)) != 0)
                 /* you can't fail a disk while we're reconstructing! */                          return retcode;
                 /* XXX wrong for RAID6 */                  goto config;
                 goto out;  #endif
         }  
         if ((raidPtr->Disks[rr->col].status == rf_ds_optimal) &&  
             (raidPtr->numFailures > 0)) {  
                 /* some other component has failed.  Let's not make  
                    things worse. XXX wrong for RAID6 */  
                 goto out;  
         }  
         if (raidPtr->Disks[rr->col].status == rf_ds_spared) {  
                 /* Can't fail a spared disk! */  
                 goto out;  
         }  
         rf_unlock_mutex2(raidPtr->mutex);  
   
         /* make a copy of the recon request so that we don't rely on  #ifdef COMPAT_80
          * the user's buffer */          case RAIDFRAME_CHECK_RECON_STATUS_EXT80:
         rrint = RF_Malloc(sizeof(*rrint));                  return rf_check_recon_status_ext80(raidPtr, data);
         if (rrint == NULL)  
                 return(ENOMEM);  
         rrint->col = rr->col;  
         rrint->flags = rr->flags;  
         rrint->raidPtr = raidPtr;  
   
         return RF_CREATE_THREAD(raidPtr->recon_thread, rf_ReconThread,          case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT80:
             rrint, "raid_recon");                  return rf_check_parityrewrite_status_ext80(raidPtr, data);
 out:  
         rf_unlock_mutex2(raidPtr->mutex);  
         return EINVAL;  
 }  
   
 static int          case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT80:
 rf_copyinspecificbuf(RF_Config_t *k_cfg)                  return rf_check_copyback_status_ext80(raidPtr, data);
 {  
         /* allocate a buffer for the layout-specific data, and copy it in */  
         if (k_cfg->layoutSpecificSize == 0)  
                 return 0;  
   
         if (k_cfg->layoutSpecificSize > 10000) {          case RAIDFRAME_GET_INFO80:
             /* sanity check */                  return rf_get_info80(raidPtr, data);
             return EINVAL;  
         }  
   
         u_char *specific_buf;          case RAIDFRAME_GET_COMPONENT_LABEL80:
         specific_buf =  RF_Malloc(k_cfg->layoutSpecificSize);                  return rf_get_component_label80(raidPtr, data);
         if (specific_buf == NULL)  
                 return ENOMEM;  
   
         int retcode = copyin(k_cfg->layoutSpecific, specific_buf,          case RAIDFRAME_CONFIGURE80:
             k_cfg->layoutSpecificSize);                  if ((retcode = rf_config80(raidPtr, unit, data, &k_cfg)) != 0)
         if (retcode) {                          return retcode;
                 RF_Free(specific_buf, k_cfg->layoutSpecificSize);                  goto config;
                 db1_printf(("%s: retcode=%d copyin.2\n", __func__, retcode));  #endif
                 return retcode;  
         }  
   
         k_cfg->layoutSpecific = specific_buf;                  /* configure the system */
         return 0;          case RAIDFRAME_CONFIGURE:
 }  #ifdef COMPAT_NETBSD32
   #ifdef _LP64
           case RAIDFRAME_CONFIGURE32:
   #endif
   #endif
   
 static int                  if (raidPtr->valid) {
 rf_getConfiguration(struct raid_softc *rs, void *data, RF_Config_t **k_cfg)                          /* There is a valid RAID set running on this unit! */
 {                          printf("raid%d: Device already configured!\n",unit);
         RF_Config_t *u_cfg = *((RF_Config_t **) data);                          return(EINVAL);
                   }
   
         if (rs->sc_r.valid) {                  /* copy-in the configuration information */
                 /* There is a valid RAID set running on this unit! */                  /* data points to a pointer to the configuration structure */
                 printf("raid%d: Device already configured!\n", rs->sc_unit);  
                 return EINVAL;  
         }  
   
         /* copy-in the configuration information */                  RF_Malloc(k_cfg, sizeof(RF_Config_t), (RF_Config_t *));
         /* data points to a pointer to the configuration structure */                  if (k_cfg == NULL) {
         *k_cfg = RF_Malloc(sizeof(**k_cfg));                          return (ENOMEM);
         if (*k_cfg == NULL) {                  }
                 return ENOMEM;  #ifdef COMPAT_NETBSD32
         }  #ifdef _LP64
         int retcode = copyin(u_cfg, *k_cfg, sizeof(RF_Config_t));                  if (cmd == RAIDFRAME_CONFIGURE32 &&
         if (retcode == 0)                      (l->l_proc->p_flag & PK_32) != 0)
                 return 0;                          retcode = rf_config_netbsd32(data, k_cfg);
         RF_Free(*k_cfg, sizeof(RF_Config_t));                  else
         db1_printf(("%s: retcode=%d copyin.1\n", __func__, retcode));  #endif
         rs->sc_flags |= RAIDF_SHUTDOWN;  #endif
         return retcode;                  {
 }                          u_cfg = *((RF_Config_t **) data);
                           retcode = copyin(u_cfg, k_cfg, sizeof(RF_Config_t));
                   }
                   if (retcode) {
                           RF_Free(k_cfg, sizeof(RF_Config_t));
                           db1_printf(("rf_ioctl: retcode=%d copyin.1\n",
                                   retcode));
                           goto no_config;
                   }
                   goto config;
           config:
                   rs->sc_flags &= ~RAIDF_SHUTDOWN;
   
                   /* allocate a buffer for the layout-specific data, and copy it
                    * in */
                   if (k_cfg->layoutSpecificSize) {
                           if (k_cfg->layoutSpecificSize > 10000) {
                                   /* sanity check */
                                   RF_Free(k_cfg, sizeof(RF_Config_t));
                                   retcode = EINVAL;
                                   goto no_config;
                           }
                           RF_Malloc(specific_buf, k_cfg->layoutSpecificSize,
                               (u_char *));
                           if (specific_buf == NULL) {
                                   RF_Free(k_cfg, sizeof(RF_Config_t));
                                   retcode = ENOMEM;
                                   goto no_config;
                           }
                           retcode = copyin(k_cfg->layoutSpecific, specific_buf,
                               k_cfg->layoutSpecificSize);
                           if (retcode) {
                                   RF_Free(k_cfg, sizeof(RF_Config_t));
                                   RF_Free(specific_buf,
                                           k_cfg->layoutSpecificSize);
                                   db1_printf(("rf_ioctl: retcode=%d copyin.2\n",
                                           retcode));
                                   goto no_config;
                           }
                   } else
                           specific_buf = NULL;
                   k_cfg->layoutSpecific = specific_buf;
   
 int                  /* should do some kind of sanity check on the configuration.
 rf_construct(struct raid_softc *rs, RF_Config_t *k_cfg)                   * Store the sum of all the bytes in the last byte? */
 {  
         int retcode;  
         RF_Raid_t *raidPtr = &rs->sc_r;  
   
         rs->sc_flags &= ~RAIDF_SHUTDOWN;                  /* configure the system */
   
         if ((retcode = rf_copyinspecificbuf(k_cfg)) != 0)                  /*
                 goto out;                   * Clear the entire RAID descriptor, just to make sure
                    *  there is no stale data left in the case of a
                    *  reconfiguration
                    */
                   memset(raidPtr, 0, sizeof(*raidPtr));
                   raidPtr->softc = rs;
                   raidPtr->raidid = unit;
   
         /* should do some kind of sanity check on the configuration.                  retcode = rf_Configure(raidPtr, k_cfg, NULL);
          * Store the sum of all the bytes in the last byte? */  
   
         /* configure the system */                  if (retcode == 0) {
   
         /*                          /* allow this many simultaneous IO's to
          * Clear the entire RAID descriptor, just to make sure                             this RAID device */
          *  there is no stale data left in the case of a                          raidPtr->openings = RAIDOUTSTANDING;
          *  reconfiguration  
          */  
         memset(raidPtr, 0, sizeof(*raidPtr));  
         raidPtr->softc = rs;  
         raidPtr->raidid = rs->sc_unit;  
   
         retcode = rf_Configure(raidPtr, k_cfg, NULL);  
   
         if (retcode == 0) {  
                 /* allow this many simultaneous IO's to  
                    this RAID device */  
                 raidPtr->openings = RAIDOUTSTANDING;  
   
                 raidinit(rs);                          raidinit(rs);
                 raid_wakeup(raidPtr);                          raid_wakeup(raidPtr);
                 rf_markalldirty(raidPtr);                          rf_markalldirty(raidPtr);
         }                  }
                   /* free the buffers.  No return code here. */
                   if (k_cfg->layoutSpecificSize) {
                           RF_Free(specific_buf, k_cfg->layoutSpecificSize);
                   }
                   RF_Free(k_cfg, sizeof(RF_Config_t));
   
         /* free the buffers.  No return code here. */          no_config:
         if (k_cfg->layoutSpecificSize) {  
                 RF_Free(k_cfg->layoutSpecific, k_cfg->layoutSpecificSize);  
         }  
 out:  
         RF_Free(k_cfg, sizeof(RF_Config_t));  
         if (retcode) {  
                 /*                  /*
                  * If configuration failed, set sc_flags so that we                   * If configuration failed, set sc_flags so that we
                  * will detach the device when we close it.                   * will detach the device when we close it.
                  */                   */
                 rs->sc_flags |= RAIDF_SHUTDOWN;                  if (retcode != 0)
         }                          rs->sc_flags |= RAIDF_SHUTDOWN;
         return retcode;                  return (retcode);
 }  
   
 #if RF_DISABLED  
 static int  
 rf_set_component_label(RF_Raid_t *raidPtr, RF_ComponentLabel_t *clabel)  
 {  
   
         /* XXX check the label for valid stuff... */  
         /* Note that some things *should not* get modified --  
            the user should be re-initing the labels instead of  
            trying to patch things.  
            */  
 #ifdef DEBUG  
         int raidid = raidPtr->raidid;  
         printf("raid%d: Got component label:\n", raidid);  
         printf("raid%d: Version: %d\n", raidid, clabel->version);  
         printf("raid%d: Serial Number: %d\n", raidid, clabel->serial_number);  
         printf("raid%d: Mod counter: %d\n", raidid, clabel->mod_counter);  
         printf("raid%d: Column: %d\n", raidid, clabel->column);  
         printf("raid%d: Num Columns: %d\n", raidid, clabel->num_columns);  
         printf("raid%d: Clean: %d\n", raidid, clabel->clean);  
         printf("raid%d: Status: %d\n", raidid, clabel->status);  
 #endif  /* DEBUG */  
         clabel->row = 0;  
         int column = clabel->column;  
   
         if ((column < 0) || (column >= raidPtr->numCol)) {  
                 return(EINVAL);  
         }  
   
         /* XXX this isn't allowed to do anything for now :-) */  
   
         /* XXX and before it is, we need to fill in the rest  
            of the fields!?!?!?! */  
         memcpy(raidget_component_label(raidPtr, column),  
             clabel, sizeof(*clabel));  
         raidflush_component_label(raidPtr, column);  
         return 0;  
 }  
 #endif  
   
 static int  
 rf_init_component_label(RF_Raid_t *raidPtr, RF_ComponentLabel_t *clabel)  
 {  
         /*  
            we only want the serial number from  
            the above.  We get all the rest of the information  
            from the config that was used to create this RAID  
            set.  
            */  
   
         raidPtr->serial_number = clabel->serial_number;  
   
         for (int column = 0; column < raidPtr->numCol; column++) {  
                 RF_RaidDisk_t *diskPtr = &raidPtr->Disks[column];  
                 if (RF_DEAD_DISK(diskPtr->status))  
                         continue;  
                 RF_ComponentLabel_t *ci_label = raidget_component_label(  
                     raidPtr, column);  
                 /* Zeroing this is important. */  
                 memset(ci_label, 0, sizeof(*ci_label));  
                 raid_init_component_label(raidPtr, ci_label);  
                 ci_label->serial_number = raidPtr->serial_number;  
                 ci_label->row = 0; /* we dont' pretend to support more */  
                 rf_component_label_set_partitionsize(ci_label,  
                     diskPtr->partitionSize);  
                 ci_label->column = column;  
                 raidflush_component_label(raidPtr, column);  
                 /* XXXjld what about the spares? */  
         }  
   
         return 0;  
 }  
   
 static int  
 rf_rebuild_in_place(RF_Raid_t *raidPtr, RF_SingleComponent_t *componentPtr)  
 {  
   
         if (raidPtr->Layout.map->faultsTolerated == 0) {  
                 /* Can't do this on a RAID 0!! */  
                 return EINVAL;  
         }  
   
         if (raidPtr->recon_in_progress == 1) {  
                 /* a reconstruct is already in progress! */  
                 return EINVAL;  
         }  
   
         RF_SingleComponent_t component;  
         memcpy(&component, componentPtr, sizeof(RF_SingleComponent_t));  
         component.row = 0; /* we don't support any more */  
         int column = component.column;  
   
         if ((column < 0) || (column >= raidPtr->numCol)) {  
                 return EINVAL;  
         }  
   
         rf_lock_mutex2(raidPtr->mutex);  
         if ((raidPtr->Disks[column].status == rf_ds_optimal) &&  
             (raidPtr->numFailures > 0)) {  
                 /* XXX 0 above shouldn't be constant!!! */  
                 /* some component other than this has failed.  
                    Let's not make things worse than they already  
                    are... */  
                 printf("raid%d: Unable to reconstruct to disk at:\n",  
                        raidPtr->raidid);  
                 printf("raid%d:     Col: %d   Too many failures.\n",  
                        raidPtr->raidid, column);  
                 rf_unlock_mutex2(raidPtr->mutex);  
                 return EINVAL;  
         }  
   
         if (raidPtr->Disks[column].status == rf_ds_reconstructing) {  
                 printf("raid%d: Unable to reconstruct to disk at:\n",  
                        raidPtr->raidid);  
                 printf("raid%d:    Col: %d   "  
                     "Reconstruction already occurring!\n",  
                     raidPtr->raidid, column);  
   
                 rf_unlock_mutex2(raidPtr->mutex);  
                 return EINVAL;  
         }  
   
         if (raidPtr->Disks[column].status == rf_ds_spared) {  
                 rf_unlock_mutex2(raidPtr->mutex);  
                 return EINVAL;  
         }  
   
         rf_unlock_mutex2(raidPtr->mutex);  
   
         struct rf_recon_req_internal *rrint;  
         rrint = RF_Malloc(sizeof(*rrint));  
         if (rrint == NULL)  
                 return ENOMEM;  
   
         rrint->col = column;  
         rrint->raidPtr = raidPtr;  
   
         return RF_CREATE_THREAD(raidPtr->recon_thread,  
             rf_ReconstructInPlaceThread, rrint, "raid_reconip");  
 }  
   
 static int  
 rf_check_recon_status(RF_Raid_t *raidPtr, int *data)  
 {  
         /*  
          * This makes no sense on a RAID 0, or if we are not reconstructing  
          * so tell the user it's done.  
          */  
         if (raidPtr->Layout.map->faultsTolerated == 0 ||  
             raidPtr->status != rf_rs_reconstructing) {  
                 *data = 100;  
                 return 0;  
         }  
         if (raidPtr->reconControl->numRUsTotal == 0) {  
                 *data = 0;  
                 return 0;  
         }  
         *data = (raidPtr->reconControl->numRUsComplete * 100  
             / raidPtr->reconControl->numRUsTotal);  
         return 0;  
 }  
   
 static int  
 raidioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)  
 {  
         int     unit = raidunit(dev);  
         int     part, pmask;  
         struct raid_softc *rs;  
         struct dk_softc *dksc;  
         RF_Config_t *k_cfg;  
         RF_Raid_t *raidPtr;  
         RF_AccTotals_t *totals;  
         RF_SingleComponent_t component;  
         RF_DeviceConfig_t *d_cfg, *ucfgp;  
         int retcode = 0;  
         int column;  
         RF_ComponentLabel_t *clabel;  
         RF_SingleComponent_t *sparePtr,*componentPtr;  
         int d;  
   
         if ((rs = raidget(unit, false)) == NULL)  
                 return ENXIO;  
   
         dksc = &rs->sc_dksc;  
         raidPtr = &rs->sc_r;  
   
         db1_printf(("raidioctl: %d %d %d %lu\n", (int) dev,  
             (int) DISKPART(dev), (int) unit, cmd));  
   
         /* Must be initialized for these... */  
         if (rf_must_be_initialized(rs, cmd))  
                 return ENXIO;  
   
         switch (cmd) {  
                 /* configure the system */  
         case RAIDFRAME_CONFIGURE:  
                 if ((retcode = rf_getConfiguration(rs, data, &k_cfg)) != 0)  
                         return retcode;  
                 return rf_construct(rs, k_cfg);  
   
                 /* shutdown the system */                  /* shutdown the system */
         case RAIDFRAME_SHUTDOWN:          case RAIDFRAME_SHUTDOWN:
Line 1433  raidioctl(dev_t dev, u_long cmd, void *d
Line 1276  raidioctl(dev_t dev, u_long cmd, void *d
                 part = DISKPART(dev);                  part = DISKPART(dev);
                 pmask = (1 << part);                  pmask = (1 << part);
   
                 if ((retcode = raidlock(rs)) != 0)                  if ((error = raidlock(rs)) != 0)
                         return retcode;                          return (error);
   
                 if (DK_BUSY(dksc, pmask) ||                  if (DK_BUSY(dksc, pmask) ||
                     raidPtr->recon_in_progress != 0 ||                      raidPtr->recon_in_progress != 0 ||
Line 1449  raidioctl(dev_t dev, u_long cmd, void *d
Line 1292  raidioctl(dev_t dev, u_long cmd, void *d
   
                 raidunlock(rs);                  raidunlock(rs);
   
                 return retcode;                  return (retcode);
         case RAIDFRAME_GET_COMPONENT_LABEL:          case RAIDFRAME_GET_COMPONENT_LABEL:
                 return rf_get_component_label(raidPtr, data);                  return rf_get_component_label(raidPtr, data);
   
 #if RF_DISABLED  #if 0
         case RAIDFRAME_SET_COMPONENT_LABEL:          case RAIDFRAME_SET_COMPONENT_LABEL:
                 return rf_set_component_label(raidPtr, data);                  clabel = (RF_ComponentLabel_t *) data;
   
                   /* XXX check the label for valid stuff... */
                   /* Note that some things *should not* get modified --
                      the user should be re-initing the labels instead of
                      trying to patch things.
                      */
   
                   raidid = raidPtr->raidid;
   #ifdef DEBUG
                   printf("raid%d: Got component label:\n", raidid);
                   printf("raid%d: Version: %d\n", raidid, clabel->version);
                   printf("raid%d: Serial Number: %d\n", raidid, clabel->serial_number);
                   printf("raid%d: Mod counter: %d\n", raidid, clabel->mod_counter);
                   printf("raid%d: Column: %d\n", raidid, clabel->column);
                   printf("raid%d: Num Columns: %d\n", raidid, clabel->num_columns);
                   printf("raid%d: Clean: %d\n", raidid, clabel->clean);
                   printf("raid%d: Status: %d\n", raidid, clabel->status);
   #endif
                   clabel->row = 0;
                   column = clabel->column;
   
                   if ((column < 0) || (column >= raidPtr->numCol)) {
                           return(EINVAL);
                   }
   
                   /* XXX this isn't allowed to do anything for now :-) */
   
                   /* XXX and before it is, we need to fill in the rest
                      of the fields!?!?!?! */
                   memcpy(raidget_component_label(raidPtr, column),
                       clabel, sizeof(*clabel));
                   raidflush_component_label(raidPtr, column);
                   return (0);
 #endif  #endif
   
         case RAIDFRAME_INIT_LABELS:          case RAIDFRAME_INIT_LABELS:
                 return rf_init_component_label(raidPtr, data);                  clabel = (RF_ComponentLabel_t *) data;
                   /*
                      we only want the serial number from
                      the above.  We get all the rest of the information
                      from the config that was used to create this RAID
                      set.
                      */
   
                   raidPtr->serial_number = clabel->serial_number;
   
                   for(column=0;column<raidPtr->numCol;column++) {
                           diskPtr = &raidPtr->Disks[column];
                           if (!RF_DEAD_DISK(diskPtr->status)) {
                                   ci_label = raidget_component_label(raidPtr,
                                       column);
                                   /* Zeroing this is important. */
                                   memset(ci_label, 0, sizeof(*ci_label));
                                   raid_init_component_label(raidPtr, ci_label);
                                   ci_label->serial_number =
                                       raidPtr->serial_number;
                                   ci_label->row = 0; /* we dont' pretend to support more */
                                   rf_component_label_set_partitionsize(ci_label,
                                       diskPtr->partitionSize);
                                   ci_label->column = column;
                                   raidflush_component_label(raidPtr, column);
                           }
                           /* XXXjld what about the spares? */
                   }
   
                   return (retcode);
         case RAIDFRAME_SET_AUTOCONFIG:          case RAIDFRAME_SET_AUTOCONFIG:
                 d = rf_set_autoconfig(raidPtr, *(int *) data);                  d = rf_set_autoconfig(raidPtr, *(int *) data);
                 printf("raid%d: New autoconfig value is: %d\n",                  printf("raid%d: New autoconfig value is: %d\n",
                        raidPtr->raidid, d);                         raidPtr->raidid, d);
                 *(int *) data = d;                  *(int *) data = d;
                 return retcode;                  return (retcode);
   
         case RAIDFRAME_SET_ROOT:          case RAIDFRAME_SET_ROOT:
                 d = rf_set_rootpartition(raidPtr, *(int *) data);                  d = rf_set_rootpartition(raidPtr, *(int *) data);
                 printf("raid%d: New rootpartition value is: %d\n",                  printf("raid%d: New rootpartition value is: %d\n",
                        raidPtr->raidid, d);                         raidPtr->raidid, d);
                 *(int *) data = d;                  *(int *) data = d;
                 return retcode;                  return (retcode);
   
                 /* initialize all parity */                  /* initialize all parity */
         case RAIDFRAME_REWRITEPARITY:          case RAIDFRAME_REWRITEPARITY:
Line 1481  raidioctl(dev_t dev, u_long cmd, void *d
Line 1385  raidioctl(dev_t dev, u_long cmd, void *d
                 if (raidPtr->Layout.map->faultsTolerated == 0) {                  if (raidPtr->Layout.map->faultsTolerated == 0) {
                         /* Parity for RAID 0 is trivially correct */                          /* Parity for RAID 0 is trivially correct */
                         raidPtr->parity_good = RF_RAID_CLEAN;                          raidPtr->parity_good = RF_RAID_CLEAN;
                         return 0;                          return(0);
                 }                  }
   
                 if (raidPtr->parity_rewrite_in_progress == 1) {                  if (raidPtr->parity_rewrite_in_progress == 1) {
                         /* Re-write is already in progress! */                          /* Re-write is already in progress! */
                         return EINVAL;                          return(EINVAL);
                 }                  }
   
                 return RF_CREATE_THREAD(raidPtr->parity_rewrite_thread,                  retcode = RF_CREATE_THREAD(raidPtr->parity_rewrite_thread,
                     rf_RewriteParityThread, raidPtr,"raid_parity");                                             rf_RewriteParityThread,
                                              raidPtr,"raid_parity");
                   return (retcode);
   
   
         case RAIDFRAME_ADD_HOT_SPARE:          case RAIDFRAME_ADD_HOT_SPARE:
                 sparePtr = (RF_SingleComponent_t *) data;                  sparePtr = (RF_SingleComponent_t *) data;
                 memcpy(&component, sparePtr, sizeof(RF_SingleComponent_t));                  memcpy( &component, sparePtr, sizeof(RF_SingleComponent_t));
                 return rf_add_hot_spare(raidPtr, &component);                  retcode = rf_add_hot_spare(raidPtr, &component);
                   return(retcode);
   
         case RAIDFRAME_REMOVE_HOT_SPARE:          case RAIDFRAME_REMOVE_HOT_SPARE:
                 return retcode;                  return(retcode);
   
         case RAIDFRAME_DELETE_COMPONENT:          case RAIDFRAME_DELETE_COMPONENT:
                 componentPtr = (RF_SingleComponent_t *)data;                  componentPtr = (RF_SingleComponent_t *)data;
                 memcpy(&component, componentPtr, sizeof(RF_SingleComponent_t));                  memcpy( &component, componentPtr,
                 return rf_delete_component(raidPtr, &component);                          sizeof(RF_SingleComponent_t));
                   retcode = rf_delete_component(raidPtr, &component);
                   return(retcode);
   
         case RAIDFRAME_INCORPORATE_HOT_SPARE:          case RAIDFRAME_INCORPORATE_HOT_SPARE:
                 componentPtr = (RF_SingleComponent_t *)data;                  componentPtr = (RF_SingleComponent_t *)data;
                 memcpy(&component, componentPtr, sizeof(RF_SingleComponent_t));                  memcpy( &component, componentPtr,
                 return rf_incorporate_hot_spare(raidPtr, &component);                          sizeof(RF_SingleComponent_t));
                   retcode = rf_incorporate_hot_spare(raidPtr, &component);
                   return(retcode);
   
         case RAIDFRAME_REBUILD_IN_PLACE:          case RAIDFRAME_REBUILD_IN_PLACE:
                 return rf_rebuild_in_place(raidPtr, data);  
                   if (raidPtr->Layout.map->faultsTolerated == 0) {
                           /* Can't do this on a RAID 0!! */
                           return(EINVAL);
                   }
   
                   if (raidPtr->recon_in_progress == 1) {
                           /* a reconstruct is already in progress! */
                           return(EINVAL);
                   }
   
                   componentPtr = (RF_SingleComponent_t *) data;
                   memcpy( &component, componentPtr,
                           sizeof(RF_SingleComponent_t));
                   component.row = 0; /* we don't support any more */
                   column = component.column;
   
                   if ((column < 0) || (column >= raidPtr->numCol)) {
                           return(EINVAL);
                   }
   
                   rf_lock_mutex2(raidPtr->mutex);
                   if ((raidPtr->Disks[column].status == rf_ds_optimal) &&
                       (raidPtr->numFailures > 0)) {
                           /* XXX 0 above shouldn't be constant!!! */
                           /* some component other than this has failed.
                              Let's not make things worse than they already
                              are... */
                           printf("raid%d: Unable to reconstruct to disk at:\n",
                                  raidPtr->raidid);
                           printf("raid%d:     Col: %d   Too many failures.\n",
                                  raidPtr->raidid, column);
                           rf_unlock_mutex2(raidPtr->mutex);
                           return (EINVAL);
                   }
                   if (raidPtr->Disks[column].status ==
                       rf_ds_reconstructing) {
                           printf("raid%d: Unable to reconstruct to disk at:\n",
                                  raidPtr->raidid);
                           printf("raid%d:    Col: %d   Reconstruction already occurring!\n", raidPtr->raidid, column);
   
                           rf_unlock_mutex2(raidPtr->mutex);
                           return (EINVAL);
                   }
                   if (raidPtr->Disks[column].status == rf_ds_spared) {
                           rf_unlock_mutex2(raidPtr->mutex);
                           return (EINVAL);
                   }
                   rf_unlock_mutex2(raidPtr->mutex);
   
                   RF_Malloc(rrint, sizeof(*rrint), (struct rf_recon_req_internal *));
                   if (rrint == NULL)
                           return(ENOMEM);
   
                   rrint->col = column;
                   rrint->raidPtr = raidPtr;
   
                   retcode = RF_CREATE_THREAD(raidPtr->recon_thread,
                                              rf_ReconstructInPlaceThread,
                                              rrint, "raid_reconip");
                   return(retcode);
   
         case RAIDFRAME_GET_INFO:          case RAIDFRAME_GET_INFO:
                 ucfgp = *(RF_DeviceConfig_t **)data;  #ifdef COMPAT_NETBSD32
                 d_cfg = RF_Malloc(sizeof(*d_cfg));  #ifdef _LP64
           case RAIDFRAME_GET_INFO32:
   #endif
   #endif
                   RF_Malloc(d_cfg, sizeof(RF_DeviceConfig_t),
                             (RF_DeviceConfig_t *));
                 if (d_cfg == NULL)                  if (d_cfg == NULL)
                         return ENOMEM;                          return (ENOMEM);
                 retcode = rf_get_info(raidPtr, d_cfg);                  retcode = rf_get_info(raidPtr, d_cfg);
                 if (retcode == 0) {                  if (retcode == 0) {
                         retcode = copyout(d_cfg, ucfgp, sizeof(*d_cfg));  #ifdef COMPAT_NETBSD32
   #ifdef _LP64
                           if (cmd == RAIDFRAME_GET_INFO32)
                                   ucfgp = NETBSD32PTR64(*(netbsd32_pointer_t *)data);
                           else
   #endif
   #endif
                                   ucfgp = *(RF_DeviceConfig_t **)data;
                           retcode = copyout(d_cfg, ucfgp, sizeof(RF_DeviceConfig_t));
                 }                  }
                 RF_Free(d_cfg, sizeof(RF_DeviceConfig_t));                  RF_Free(d_cfg, sizeof(RF_DeviceConfig_t));
                 return retcode;  
                   return (retcode);
   
         case RAIDFRAME_CHECK_PARITY:          case RAIDFRAME_CHECK_PARITY:
                 *(int *) data = raidPtr->parity_good;                  *(int *) data = raidPtr->parity_good;
                 return 0;                  return (0);
   
         case RAIDFRAME_PARITYMAP_STATUS:          case RAIDFRAME_PARITYMAP_STATUS:
                 if (rf_paritymap_ineligible(raidPtr))                  if (rf_paritymap_ineligible(raidPtr))
                         return EINVAL;                          return EINVAL;
                 rf_paritymap_status(raidPtr->parity_map, data);                  rf_paritymap_status(raidPtr->parity_map,
                       (struct rf_pmstat *)data);
                 return 0;                  return 0;
   
         case RAIDFRAME_PARITYMAP_SET_PARAMS:          case RAIDFRAME_PARITYMAP_SET_PARAMS:
Line 1540  raidioctl(dev_t dev, u_long cmd, void *d
Line 1527  raidioctl(dev_t dev, u_long cmd, void *d
                         return EINVAL;                          return EINVAL;
                 if (raidPtr->parity_map == NULL)                  if (raidPtr->parity_map == NULL)
                         return ENOENT; /* ??? */                          return ENOENT; /* ??? */
                 if (rf_paritymap_set_params(raidPtr->parity_map, data, 1) != 0)                  if (0 != rf_paritymap_set_params(raidPtr->parity_map,
                           (struct rf_pmparams *)data, 1))
                         return EINVAL;                          return EINVAL;
                 return 0;                  return 0;
   
Line 1559  raidioctl(dev_t dev, u_long cmd, void *d
Line 1547  raidioctl(dev_t dev, u_long cmd, void *d
   
         case RAIDFRAME_RESET_ACCTOTALS:          case RAIDFRAME_RESET_ACCTOTALS:
                 memset(&raidPtr->acc_totals, 0, sizeof(raidPtr->acc_totals));                  memset(&raidPtr->acc_totals, 0, sizeof(raidPtr->acc_totals));
                 return 0;                  return (0);
   
         case RAIDFRAME_GET_ACCTOTALS:          case RAIDFRAME_GET_ACCTOTALS:
                 totals = (RF_AccTotals_t *) data;                  totals = (RF_AccTotals_t *) data;
                 *totals = raidPtr->acc_totals;                  *totals = raidPtr->acc_totals;
                 return 0;                  return (0);
   
         case RAIDFRAME_KEEP_ACCTOTALS:          case RAIDFRAME_KEEP_ACCTOTALS:
                 raidPtr->keep_acc_totals = *(int *)data;                  raidPtr->keep_acc_totals = *(int *)data;
                 return 0;                  return (0);
   
         case RAIDFRAME_GET_SIZE:          case RAIDFRAME_GET_SIZE:
                 *(int *) data = raidPtr->totalSectors;                  *(int *) data = raidPtr->totalSectors;
                 return 0;                  return (0);
   
                   /* fail a disk & optionally start reconstruction */
         case RAIDFRAME_FAIL_DISK:          case RAIDFRAME_FAIL_DISK:
                 return rf_fail_disk(raidPtr, data);  #ifdef COMPAT_80
           case RAIDFRAME_FAIL_DISK80:
   #endif
   
                   if (raidPtr->Layout.map->faultsTolerated == 0) {
                           /* Can't do this on a RAID 0!! */
                           return(EINVAL);
                   }
   
                   rr = (struct rf_recon_req *) data;
                   if (rr->col < 0 || rr->col >= raidPtr->numCol)
                           return (EINVAL);
   
                   rf_lock_mutex2(raidPtr->mutex);
                   if (raidPtr->status == rf_rs_reconstructing) {
                           /* you can't fail a disk while we're reconstructing! */
                           /* XXX wrong for RAID6 */
                           rf_unlock_mutex2(raidPtr->mutex);
                           return (EINVAL);
                   }
                   if ((raidPtr->Disks[rr->col].status ==
                        rf_ds_optimal) && (raidPtr->numFailures > 0)) {
                           /* some other component has failed.  Let's not make
                              things worse. XXX wrong for RAID6 */
                           rf_unlock_mutex2(raidPtr->mutex);
                           return (EINVAL);
                   }
                   if (raidPtr->Disks[rr->col].status == rf_ds_spared) {
                           /* Can't fail a spared disk! */
                           rf_unlock_mutex2(raidPtr->mutex);
                           return (EINVAL);
                   }
                   rf_unlock_mutex2(raidPtr->mutex);
   
                   /* make a copy of the recon request so that we don't rely on
                    * the user's buffer */
                   RF_Malloc(rrint, sizeof(*rrint), (struct rf_recon_req_internal *));
                   if (rrint == NULL)
                           return(ENOMEM);
                   rrint->col = rr->col;
                   rrint->flags = rr->flags;
                   rrint->raidPtr = raidPtr;
   
                   retcode = RF_CREATE_THREAD(raidPtr->recon_thread,
                                              rf_ReconThread,
                                              rrint, "raid_recon");
                   return (0);
   
                 /* invoke a copyback operation after recon on whatever disk                  /* invoke a copyback operation after recon on whatever disk
                  * needs it, if any */                   * needs it, if any */
Line 1583  raidioctl(dev_t dev, u_long cmd, void *d
Line 1618  raidioctl(dev_t dev, u_long cmd, void *d
   
                 if (raidPtr->Layout.map->faultsTolerated == 0) {                  if (raidPtr->Layout.map->faultsTolerated == 0) {
                         /* This makes no sense on a RAID 0!! */                          /* This makes no sense on a RAID 0!! */
                         return EINVAL;                          return(EINVAL);
                 }                  }
   
                 if (raidPtr->copyback_in_progress == 1) {                  if (raidPtr->copyback_in_progress == 1) {
                         /* Copyback is already in progress! */                          /* Copyback is already in progress! */
                         return EINVAL;                          return(EINVAL);
                 }                  }
   
                 return RF_CREATE_THREAD(raidPtr->copyback_thread,                  retcode = RF_CREATE_THREAD(raidPtr->copyback_thread,
                     rf_CopybackThread, raidPtr, "raid_copyback");                                             rf_CopybackThread,
                                              raidPtr,"raid_copyback");
                   return (retcode);
   
                 /* return the percentage completion of reconstruction */                  /* return the percentage completion of reconstruction */
         case RAIDFRAME_CHECK_RECON_STATUS:          case RAIDFRAME_CHECK_RECON_STATUS:
                 return rf_check_recon_status(raidPtr, data);                  if (raidPtr->Layout.map->faultsTolerated == 0) {
                           /* This makes no sense on a RAID 0, so tell the
                              user it's done. */
                           *(int *) data = 100;
                           return(0);
                   }
                   if (raidPtr->status != rf_rs_reconstructing)
                           *(int *) data = 100;
                   else {
                           if (raidPtr->reconControl->numRUsTotal > 0) {
                                   *(int *) data = (raidPtr->reconControl->numRUsComplete * 100 / raidPtr->reconControl->numRUsTotal);
                           } else {
                                   *(int *) data = 0;
                           }
                   }
                   return (0);
         case RAIDFRAME_CHECK_RECON_STATUS_EXT:          case RAIDFRAME_CHECK_RECON_STATUS_EXT:
                 rf_check_recon_status_ext(raidPtr, data);                  rf_check_recon_status_ext(raidPtr, data);
                 return 0;                  return (0);
   
         case RAIDFRAME_CHECK_PARITYREWRITE_STATUS:          case RAIDFRAME_CHECK_PARITYREWRITE_STATUS:
                 if (raidPtr->Layout.map->faultsTolerated == 0) {                  if (raidPtr->Layout.map->faultsTolerated == 0) {
                         /* This makes no sense on a RAID 0, so tell the                          /* This makes no sense on a RAID 0, so tell the
                            user it's done. */                             user it's done. */
                         *(int *) data = 100;                          *(int *) data = 100;
                         return 0;                          return(0);
                 }                  }
                 if (raidPtr->parity_rewrite_in_progress == 1) {                  if (raidPtr->parity_rewrite_in_progress == 1) {
                         *(int *) data = 100 *                          *(int *) data = 100 *
Line 1616  raidioctl(dev_t dev, u_long cmd, void *d
Line 1667  raidioctl(dev_t dev, u_long cmd, void *d
                 } else {                  } else {
                         *(int *) data = 100;                          *(int *) data = 100;
                 }                  }
                 return 0;                  return (0);
   
         case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT:          case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT:
                 rf_check_parityrewrite_status_ext(raidPtr, data);                  rf_check_parityrewrite_status_ext(raidPtr, data);
                 return 0;                  return (0);
   
         case RAIDFRAME_CHECK_COPYBACK_STATUS:          case RAIDFRAME_CHECK_COPYBACK_STATUS:
                 if (raidPtr->Layout.map->faultsTolerated == 0) {                  if (raidPtr->Layout.map->faultsTolerated == 0) {
                         /* This makes no sense on a RAID 0 */                          /* This makes no sense on a RAID 0 */
                         *(int *) data = 100;                          *(int *) data = 100;
                         return 0;                          return(0);
                 }                  }
                 if (raidPtr->copyback_in_progress == 1) {                  if (raidPtr->copyback_in_progress == 1) {
                         *(int *) data = 100 * raidPtr->copyback_stripes_done /                          *(int *) data = 100 * raidPtr->copyback_stripes_done /
Line 1634  raidioctl(dev_t dev, u_long cmd, void *d
Line 1685  raidioctl(dev_t dev, u_long cmd, void *d
                 } else {                  } else {
                         *(int *) data = 100;                          *(int *) data = 100;
                 }                  }
                 return 0;                  return (0);
   
         case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT:          case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT:
                 rf_check_copyback_status_ext(raidPtr, data);                  rf_check_copyback_status_ext(raidPtr, data);
Line 1660  raidioctl(dev_t dev, u_long cmd, void *d
Line 1711  raidioctl(dev_t dev, u_long cmd, void *d
                  * -- I should either compute the spare table in the kernel,                   * -- I should either compute the spare table in the kernel,
                  * or have a different -- XXX XXX -- interface (a different                   * or have a different -- XXX XXX -- interface (a different
                  * character device) for delivering the table     -- XXX */                   * character device) for delivering the table     -- XXX */
 #if RF_DISABLED  #if 0
         case RAIDFRAME_SPARET_WAIT:          case RAIDFRAME_SPARET_WAIT:
                 rf_lock_mutex2(rf_sparet_wait_mutex);                  rf_lock_mutex2(rf_sparet_wait_mutex);
                 while (!rf_sparet_wait_queue)                  while (!rf_sparet_wait_queue)
                         rf_wait_cond2(rf_sparet_wait_cv, rf_sparet_wait_mutex);                          rf_wait_cond2(rf_sparet_wait_cv, rf_sparet_wait_mutex);
                 RF_SparetWait_t *waitreq = rf_sparet_wait_queue;                  waitreq = rf_sparet_wait_queue;
                 rf_sparet_wait_queue = rf_sparet_wait_queue->next;                  rf_sparet_wait_queue = rf_sparet_wait_queue->next;
                 rf_unlock_mutex2(rf_sparet_wait_mutex);                  rf_unlock_mutex2(rf_sparet_wait_mutex);
   
Line 1673  raidioctl(dev_t dev, u_long cmd, void *d
Line 1724  raidioctl(dev_t dev, u_long cmd, void *d
                 *((RF_SparetWait_t *) data) = *waitreq;                  *((RF_SparetWait_t *) data) = *waitreq;
   
                 RF_Free(waitreq, sizeof(*waitreq));                  RF_Free(waitreq, sizeof(*waitreq));
                 return 0;                  return (0);
   
                 /* wakes up a process waiting on SPARET_WAIT and puts an error                  /* wakes up a process waiting on SPARET_WAIT and puts an error
                  * code in it that will cause the dameon to exit */                   * code in it that will cause the dameon to exit */
         case RAIDFRAME_ABORT_SPARET_WAIT:          case RAIDFRAME_ABORT_SPARET_WAIT:
                 waitreq = RF_Malloc(sizeof(*waitreq));                  RF_Malloc(waitreq, sizeof(*waitreq), (RF_SparetWait_t *));
                 waitreq->fcol = -1;                  waitreq->fcol = -1;
                 rf_lock_mutex2(rf_sparet_wait_mutex);                  rf_lock_mutex2(rf_sparet_wait_mutex);
                 waitreq->next = rf_sparet_wait_queue;                  waitreq->next = rf_sparet_wait_queue;
                 rf_sparet_wait_queue = waitreq;                  rf_sparet_wait_queue = waitreq;
                 rf_broadcast_cond2(rf_sparet_wait_cv);                  rf_broadcast_conf2(rf_sparet_wait_cv);
                 rf_unlock_mutex2(rf_sparet_wait_mutex);                  rf_unlock_mutex2(rf_sparet_wait_mutex);
                 return 0;                  return (0);
   
                 /* used by the spare table daemon to deliver a spare table                  /* used by the spare table daemon to deliver a spare table
                  * into the kernel */                   * into the kernel */
Line 1696  raidioctl(dev_t dev, u_long cmd, void *d
Line 1747  raidioctl(dev_t dev, u_long cmd, void *d
   
                 /* respond to the requestor.  the return status of the spare                  /* respond to the requestor.  the return status of the spare
                  * table installation is passed in the "fcol" field */                   * table installation is passed in the "fcol" field */
                 waitred = RF_Malloc(sizeof(*waitreq));                  RF_Malloc(waitreq, sizeof(*waitreq), (RF_SparetWait_t *));
                 waitreq->fcol = retcode;                  waitreq->fcol = retcode;
                 rf_lock_mutex2(rf_sparet_wait_mutex);                  rf_lock_mutex2(rf_sparet_wait_mutex);
                 waitreq->next = rf_sparet_resp_queue;                  waitreq->next = rf_sparet_resp_queue;
Line 1704  raidioctl(dev_t dev, u_long cmd, void *d
Line 1755  raidioctl(dev_t dev, u_long cmd, void *d
                 rf_broadcast_cond2(rf_sparet_resp_cv);                  rf_broadcast_cond2(rf_sparet_resp_cv);
                 rf_unlock_mutex2(rf_sparet_wait_mutex);                  rf_unlock_mutex2(rf_sparet_wait_mutex);
   
                 return retcode;                  return (retcode);
 #endif  
         default:  
                 /*  
                  * Don't bother trying to load compat modules  
                  * if it is not our ioctl. This is more efficient  
                  * and makes rump tests not depend on compat code  
                  */  
                 if (IOCGROUP(cmd) != 'r')  
                         break;  
 #ifdef _LP64  
                 if ((l->l_proc->p_flag & PK_32) != 0) {  
                         module_autoload("compat_netbsd32_raid",  
                             MODULE_CLASS_EXEC);  
                         MODULE_HOOK_CALL(raidframe_netbsd32_ioctl_hook,  
                             (rs, cmd, data), enosys(), retcode);  
                         if (retcode != EPASSTHROUGH)  
                                 return retcode;  
                 }  
 #endif  #endif
                 module_autoload("compat_raid_80", MODULE_CLASS_EXEC);  
                 MODULE_HOOK_CALL(raidframe_ioctl_80_hook,  
                     (rs, cmd, data), enosys(), retcode);  
                 if (retcode != EPASSTHROUGH)  
                         return retcode;  
   
                 module_autoload("compat_raid_50", MODULE_CLASS_EXEC);          default:
                 MODULE_HOOK_CALL(raidframe_ioctl_50_hook,  
                     (rs, cmd, data), enosys(), retcode);  
                 if (retcode != EPASSTHROUGH)  
                         return retcode;  
                 break; /* fall through to the os-specific code below */                  break; /* fall through to the os-specific code below */
   
         }          }
Line 2712  rf_get_component(RF_AutoConfig_t *ac_lis
Line 2736  rf_get_component(RF_AutoConfig_t *ac_lis
         RF_ComponentLabel_t *clabel;          RF_ComponentLabel_t *clabel;
         RF_AutoConfig_t *ac;          RF_AutoConfig_t *ac;
   
         clabel = malloc(sizeof(RF_ComponentLabel_t), M_RAIDFRAME, M_WAITOK);          clabel = malloc(sizeof(RF_ComponentLabel_t), M_RAIDFRAME, M_NOWAIT);
           if (clabel == NULL) {
   oomem:
                       while(ac_list) {
                               ac = ac_list;
                               if (ac->clabel)
                                       free(ac->clabel, M_RAIDFRAME);
                               ac_list = ac_list->next;
                               free(ac, M_RAIDFRAME);
                       }
                       printf("RAID auto config: out of memory!\n");
                       return NULL; /* XXX probably should panic? */
           }
   
         if (!raidread_component_label(secsize, dev, vp, clabel)) {          if (!raidread_component_label(secsize, dev, vp, clabel)) {
                 /* Got the label.  Does it look reasonable? */                  /* Got the label.  Does it look reasonable? */
Line 2725  rf_get_component(RF_AutoConfig_t *ac_lis
Line 2761  rf_get_component(RF_AutoConfig_t *ac_lis
 #endif  #endif
                         /* if it's reasonable, add it, else ignore it. */                          /* if it's reasonable, add it, else ignore it. */
                         ac = malloc(sizeof(RF_AutoConfig_t), M_RAIDFRAME,                          ac = malloc(sizeof(RF_AutoConfig_t), M_RAIDFRAME,
                                 M_WAITOK);                                  M_NOWAIT);
                           if (ac == NULL) {
                                   free(clabel, M_RAIDFRAME);
                                   goto oomem;
                           }
                         strlcpy(ac->devname, cname, sizeof(ac->devname));                          strlcpy(ac->devname, cname, sizeof(ac->devname));
                         ac->dev = dev;                          ac->dev = dev;
                         ac->vp = vp;                          ac->vp = vp;
Line 2821  rf_find_raid_components(void)
Line 2861  rf_find_raid_components(void)
                         if (bdevvp(dev, &vp))                          if (bdevvp(dev, &vp))
                                 panic("RAID can't alloc vnode");                                  panic("RAID can't alloc vnode");
   
                         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);  
                         error = VOP_OPEN(vp, FREAD | FSILENT, NOCRED);                          error = VOP_OPEN(vp, FREAD | FSILENT, NOCRED);
   
                         if (error) {                          if (error) {
Line 2842  rf_find_raid_components(void)
Line 2881  rf_find_raid_components(void)
                                         printf("RAIDframe: can't get disk size"                                          printf("RAIDframe: can't get disk size"
                                             " for dev %s (%d)\n",                                              " for dev %s (%d)\n",
                                             device_xname(dv), error);                                              device_xname(dv), error);
                                   vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                                 VOP_CLOSE(vp, FREAD | FWRITE, NOCRED);                                  VOP_CLOSE(vp, FREAD | FWRITE, NOCRED);
                                 vput(vp);                                  vput(vp);
                                 continue;                                  continue;
Line 2853  rf_find_raid_components(void)
Line 2893  rf_find_raid_components(void)
                                 if (error) {                                  if (error) {
                                         printf("RAIDframe: can't get wedge info for "                                          printf("RAIDframe: can't get wedge info for "
                                             "dev %s (%d)\n", device_xname(dv), error);                                              "dev %s (%d)\n", device_xname(dv), error);
                                           vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                                         VOP_CLOSE(vp, FREAD | FWRITE, NOCRED);                                          VOP_CLOSE(vp, FREAD | FWRITE, NOCRED);
                                         vput(vp);                                          vput(vp);
                                         continue;                                          continue;
                                 }                                  }
   
                                 if (strcmp(dkw.dkw_ptype, DKW_PTYPE_RAIDFRAME) != 0) {                                  if (strcmp(dkw.dkw_ptype, DKW_PTYPE_RAIDFRAME) != 0) {
                                           vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                                         VOP_CLOSE(vp, FREAD | FWRITE, NOCRED);                                          VOP_CLOSE(vp, FREAD | FWRITE, NOCRED);
                                         vput(vp);                                          vput(vp);
                                         continue;                                          continue;
                                 }                                  }
   
                                 VOP_UNLOCK(vp);  
                                 ac_list = rf_get_component(ac_list, dev, vp,                                  ac_list = rf_get_component(ac_list, dev, vp,
                                     device_xname(dv), dkw.dkw_size, numsecs, secsize);                                      device_xname(dv), dkw.dkw_size, numsecs, secsize);
                                 rf_part_found = 1; /*There is a raid component on this disk*/                                  rf_part_found = 1; /*There is a raid component on this disk*/
Line 2885  rf_find_raid_components(void)
Line 2926  rf_find_raid_components(void)
   
                         /* don't need this any more.  We'll allocate it again                          /* don't need this any more.  We'll allocate it again
                            a little later if we really do... */                             a little later if we really do... */
                           vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                         VOP_CLOSE(vp, FREAD | FWRITE, NOCRED);                          VOP_CLOSE(vp, FREAD | FWRITE, NOCRED);
                         vput(vp);                          vput(vp);
   
Line 2903  rf_find_raid_components(void)
Line 2945  rf_find_raid_components(void)
                                 if (bdevvp(dev, &vp))                                  if (bdevvp(dev, &vp))
                                         panic("RAID can't alloc vnode");                                          panic("RAID can't alloc vnode");
   
                                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);  
                                 error = VOP_OPEN(vp, FREAD, NOCRED);                                  error = VOP_OPEN(vp, FREAD, NOCRED);
                                 if (error) {                                  if (error) {
                                         /* Whatever... */                                          /* Whatever... */
                                         vput(vp);                                          vput(vp);
                                         continue;                                          continue;
                                 }                                  }
                                 VOP_UNLOCK(vp);  
                                 snprintf(cname, sizeof(cname), "%s%c",                                  snprintf(cname, sizeof(cname), "%s%c",
                                     device_xname(dv), 'a' + i);                                      device_xname(dv), 'a' + i);
                                 ac_list = rf_get_component(ac_list, dev, vp, cname,                                  ac_list = rf_get_component(ac_list, dev, vp, cname,
Line 2932  rf_find_raid_components(void)
Line 2972  rf_find_raid_components(void)
                                 if (bdevvp(dev, &vp))                                  if (bdevvp(dev, &vp))
                                         panic("RAID can't alloc vnode");                                          panic("RAID can't alloc vnode");
   
                                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);  
   
                                 error = VOP_OPEN(vp, FREAD, NOCRED);                                  error = VOP_OPEN(vp, FREAD, NOCRED);
                                 if (error) {                                  if (error) {
                                         /* Whatever... */                                          /* Whatever... */
                                         vput(vp);                                          vput(vp);
                                         continue;                                          continue;
                                 }                                  }
                                 VOP_UNLOCK(vp);  
                                 snprintf(cname, sizeof(cname), "%s%c",                                  snprintf(cname, sizeof(cname), "%s%c",
                                     device_xname(dv), 'a' + RAW_PART);                                      device_xname(dv), 'a' + RAW_PART);
                                 ac_list = rf_get_component(ac_list, dev, vp, cname,                                  ac_list = rf_get_component(ac_list, dev, vp, cname,
Line 3072  rf_create_auto_sets(RF_AutoConfig_t *ac_
Line 3109  rf_create_auto_sets(RF_AutoConfig_t *ac_
   
                 if (config_sets == NULL) {                  if (config_sets == NULL) {
                         /* will need at least this one... */                          /* will need at least this one... */
                         config_sets = malloc(sizeof(RF_ConfigSet_t),                          config_sets = (RF_ConfigSet_t *)
                                        M_RAIDFRAME, M_WAITOK);                                  malloc(sizeof(RF_ConfigSet_t),
                                          M_RAIDFRAME, M_NOWAIT);
                           if (config_sets == NULL) {
                                   panic("rf_create_auto_sets: No memory!");
                           }
                         /* this one is easy :) */                          /* this one is easy :) */
                         config_sets->ac = ac;                          config_sets->ac = ac;
                         config_sets->next = NULL;                          config_sets->next = NULL;
Line 3093  rf_create_auto_sets(RF_AutoConfig_t *ac_
Line 3134  rf_create_auto_sets(RF_AutoConfig_t *ac_
                         }                          }
                         if (cset==NULL) {                          if (cset==NULL) {
                                 /* didn't find a match above... new set..*/                                  /* didn't find a match above... new set..*/
                                 cset = malloc(sizeof(RF_ConfigSet_t),                                  cset = (RF_ConfigSet_t *)
                                                M_RAIDFRAME, M_WAITOK);                                          malloc(sizeof(RF_ConfigSet_t),
                                                  M_RAIDFRAME, M_NOWAIT);
                                   if (cset == NULL) {
                                           panic("rf_create_auto_sets: No memory!");
                                   }
                                 cset->ac = ac;                                  cset->ac = ac;
                                 ac->next = NULL;                                  ac->next = NULL;
                                 cset->next = config_sets;                                  cset->next = config_sets;
Line 3443  rf_auto_config_set(RF_ConfigSet_t *cset)
Line 3488  rf_auto_config_set(RF_ConfigSet_t *cset)
 #endif  #endif
   
         /* 1. Create a config structure */          /* 1. Create a config structure */
         config = malloc(sizeof(*config), M_RAIDFRAME, M_WAITOK|M_ZERO);          config = malloc(sizeof(*config), M_RAIDFRAME, M_NOWAIT|M_ZERO);
           if (config == NULL) {
                   printf("%s: Out of mem - config!?!?\n", __func__);
                                   /* XXX do something more intelligent here. */
                   return NULL;
           }
   
         /*          /*
            2. Figure out what RAID ID this one is supposed to live at             2. Figure out what RAID ID this one is supposed to live at
Line 3461  rf_auto_config_set(RF_ConfigSet_t *cset)
Line 3511  rf_auto_config_set(RF_ConfigSet_t *cset)
   
         if (sc == NULL)          if (sc == NULL)
                 sc = raidget(raidID, true);                  sc = raidget(raidID, true);
           if (sc == NULL) {
                   printf("%s: Out of mem - softc!?!?\n", __func__);
                                   /* XXX do something more intelligent here. */
                   free(config, M_RAIDFRAME);
                   return NULL;
           }
   
         raidPtr = &sc->sc_r;          raidPtr = &sc->sc_r;
   
         /* XXX all this stuff should be done SOMEWHERE ELSE! */          /* XXX all this stuff should be done SOMEWHERE ELSE! */
Line 3506  void
Line 3563  void
 rf_pool_init(struct pool *p, size_t size, const char *w_chan,  rf_pool_init(struct pool *p, size_t size, const char *w_chan,
              size_t xmin, size_t xmax)               size_t xmin, size_t xmax)
 {  {
           int error;
   
         pool_init(p, size, 0, 0, 0, w_chan, NULL, IPL_BIO);          pool_init(p, size, 0, 0, 0, w_chan, NULL, IPL_BIO);
         pool_sethiwat(p, xmax);          pool_sethiwat(p, xmax);
         pool_prime(p, xmin);          if ((error = pool_prime(p, xmin)) != 0)
                   panic("%s: failed to prime pool: %d", __func__, error);
           pool_setlowat(p, xmin);
 }  }
   
 /*  /*

Legend:
Removed from v.1.356.4.4  
changed lines
  Added in v.1.357

CVSweb <webmaster@jp.NetBSD.org>