📄 mscp_disk.c
字号:
int cmd; caddr_t data; int flag;{ register UNITB *up; /* If there is no known unit corresponding to the device * number, return an error. */ if(( up = Dev_to_unitb( dev )) == NULL ) { return( ENXIO ); } switch( cmd ) { /* Get the current or default partition table values for the device * 'dev' and store them in the buffer pointed to by 'data'. */ case DIOCGETPT: case DIOCDGTPT: { register struct pt *ptp = ( struct pt * )data; register int i; /* If the current partition table values are wanted, use a structure * copy to get them into the user buffer. */ if( cmd == DIOCGETPT ) { *ptp = up->part_info; } /* Get the default partition table values based on the storage * medium currently loaded in the device. */ else { mscp_getdefpt( up->media_id, ptp ); } /* Go through the user buffer, changing any partition sizes that * were specified as -1 to the actual partition size, calculated as * the size of the user-accessible portion of the disk minus the * starting LBN of the partition. */ for( i = 0; i <= 7; i++ ) if( ptp->pt_part[ i ].pi_nblocks == -1 ) ptp->pt_part[ i ].pi_nblocks = up->unt_size - ptp->pt_part[ i ].pi_blkoff; return( 0 ); } /* Replace the current partition table for the device with the contents * of the user supplied buffer (after appropriate checking). */ case DIOCSETPT: { register struct pt *ptp = ( struct pt * )data; int error; /* If the caller is not the super-user, return a permission * denied (EACCES) error. */ if( !suser() ) return( EACCES ); /* If the user-supplied partition values conflict with the * active partition table, return an error. */ if( ( error = ptcmp( dev, &up->part_info, ptp )) != 0 ) return( error ); /* Set the partition tables in the UNITB using the data in the * user's buffer, update the superblock in the 'a' partition * if necessary, set the partition table valid bit, and return * success to the caller. */ up->part_info = *ptp; ( void )ssblk( dev, ptp ); up->part_info.pt_valid = PT_VALID; return( 0 ); } case DEVIOCGET: { register struct devget *dp = ( struct devget * )data; register struct uba_device *ui = up->ubdev; register CONNB *cp = up->connb; bzero( dp, sizeof( struct devget )); dp->category = DEV_DISK; dp->bus = cp->bus_type; bcopy( cp->model_name, dp->interface, strlen( cp->model_name )); mscp_media_to_ascii( up->media_id, dp->device ); dp->adpt_num = ui->ui_adpt; dp->nexus_num = ui->ui_nexus; dp->bus_num = ui->ui_ubanum; dp->rctlr_num = ui->ui_rctlr; dp->ctlr_num = ui->ui_ctlr; dp->slave_num = up->unit; bcopy( ui->ui_devname, dp->dev_name, strlen( ui->ui_devname )); dp->unit_num = ui->ui_unit; dp->soft_count = 0; dp->hard_count = 0; dp->stat = 0; if( up->flags.online == 0 ) dp->stat |= DEV_OFFLINE; if( up->flags.wrtp == 1 ) dp->stat |= DEV_WRTLCK; dp->category_stat = DEV_DISKPART; return( 0 ); } /* Ioctl to obtain device geometry information. */ case DEVGETGEOM: { DEVGEOMST *devgeom = ( DEVGEOMST * )data; register int calcs, ncyl; bzero( devgeom, sizeof( DEVGEOMST )); calcs = up->group * up->cylinder; devgeom->geom_info.dev_size = up->unt_size; devgeom->geom_info.ntracks = calcs; devgeom->geom_info.nsectors = up->track; calcs *= up->track; if (calcs > 0) { ncyl = up->unt_size / calcs; if (up->unt_size % calcs) ncyl++; /* round up */ } else { ncyl = 0; } devgeom->geom_info.ncylinders = ncyl; if (up->unt_flgs & MSCP_UF_RMVBL) devgeom->geom_info.attributes |= DEVGEOM_REMOVE; return( 0 ); } /* Ioctl used by radisk(8) to scan the disk or force a replacement */ case DKIOCACC: { struct dkacc *dkacc = (struct dkacc *)data; register REQB *rp; long totbytes; long length; long lbn; /* Only super users can beat on the pack */ if ( !suser() ) return(EACCES); switch (dkacc->dk_opcode){ case ACC_REVEC: /* Return if the controller does the work */ if(( up->unt_flgs & MSCP_UF_REPLC || up->flags.wrtp )) { return(0); } if (up->flags.force_scan_ip == 1) return(EBUSY); up->flags.force_scan_ip = 1; /* Force LBN to be re-vectored */ rp = (REQB *)mscp_alloc_reqb( up, NULL, mscp_repl_states, dkacc->dk_lbn, 0 ); while( up->flags.force_scan_ip ) { timeout( wakeup, ( caddr_t )rp, 5 * hz ); ( void )sleep(( caddr_t )rp, PSWP+1 ); untimeout( wakeup, ( caddr_t )rp ); } dkacc->dk_status = 0; break; case ACC_SCAN: if (dkacc->dk_lbn > up->unt_size) return(EINVAL); lbn = dkacc->dk_lbn; totbytes = 0; if (up->connb->max_bcnt == 0) up->connb->max_bcnt = 16777216; if (up->flags.force_scan_ip == 1) return(EBUSY); while (dkacc->dk_length ) { up->flags.force_scan_ip = 1; length = (dkacc->dk_length > up->connb->max_bcnt) ? up->connb->max_bcnt : dkacc->dk_length; rp = (REQB *)mscp_alloc_reqb( up, NULL, mscp_accscan_states, lbn, length); while( up->flags.force_scan_ip ) { timeout( wakeup, ( caddr_t )rp, 5 * hz ); ( void )sleep(( caddr_t )rp, PSWP+1 ); untimeout( wakeup, ( caddr_t )rp ); } totbytes += up->acc_bytecnt; if (up->acc_status != MSCP_ST_SUCC) break; lbn += btodb(up->acc_bytecnt); dkacc->dk_length -= up->acc_bytecnt; } dkacc->dk_status = up->acc_status; dkacc->dk_flags = up->acc_flags; dkacc->dk_lbn = up->acc_badlbn; dkacc->dk_length = totbytes; break; default: break; } return( 0 ); } /* Ioctl used by radisk(8) to control the exclusive access attribute. */ case DKIOCEXCL: { int *action = (int *)data; register REQB *rp; /* Only super users can modify this attribute. */ if ( !suser() ) { return(EACCES); } /* Set the up->flags.excl_acc flag to be the specified mode of * exclusive access. Next call the set unit characteristics state * table. When that completes if the value of excl_acc changes it * means that the operation failed. */ if ( *data == 0 ) { /* clear */ if ( up->flags.excl_acc == 0 ) { return(EIO); } up->flags.excl_acc = 0; } else { /* set */ up->flags.excl_acc = 1; } /* Force a set unit characteristics to set exclusive mode. */ if ( up->flags.mscp_wait == 1 ) return(EBUSY); up->flags.mscp_wait = 1; rp = (REQB *)mscp_alloc_reqb( up, NULL, mscp_stu_states, 0, 0); while( up->flags.mscp_wait ) { timeout( wakeup, ( caddr_t )rp, 5 * hz ); ( void )sleep(( caddr_t )rp, PSWP+1 ); untimeout( wakeup, ( caddr_t )rp ); } if ( *data == 0 ) { /* clear failed */ if ( up->flags.excl_acc ) { return(EIO); } } else { if ( up->flags.excl_acc == 0 ) { return(EIO); } } return( 0 ); } default: return( 0 ); }}/**//* * * Name: mscp_forcecm - Start a forced replace * * Abstract: This function calls the bbr_force() routine * to force a replacement. This function is entered * as a result of an radisk(8) request. * * * Inputs: event Event code. * rp Request block pointer. * * Outputs: NONE * * * Return NONE. * Values: */u_longmscp_forcecm( event, rp ) u_long event; register REQB *rp;{ register MSCP *mp = rp->msgptr; mp->mscp_lbn = rp->p1; mp->mscp_status = 0; return( mscp_bbr_force( rp ) );}/**//* * * Name: mscp_forceem - Cleanup afer a forced replace * * Abstract: This function deallocates the resources allocated for * the replacement and clears the force_scan_ip bit to indicate * the replacement is complete. The ioctl() function is * spinning on this bit. The access scan function is also * spinning on this bit after a bad block replace. * * * Inputs: event Event code. * rp Request block pointer. * * Outputs: NONE * * * Return NONE. * Values: */u_longmscp_forceem( event, rp ) u_long event; register REQB *rp;{ register UNITB *up = rp->unitb; up->flags.force_scan_ip = 0; mscp_dealloc_reqb( rp ); return( EV_NULL); }/**//* * * Name: mscp_size - Find the size of a partition. * * Abstract: This routine returns the size of the partition specified * by a given device number. * * Inputs: dev Device number. * * Outputs: NONE * * * Return Size of partition specified by dev. * Values: */int mscp_size( dev ) dev_t dev;{ register int part_size; register UNITB *up; register int px = Px( dev ); /* If the unit index is greater than the assembled-in maximum, * or if there is no unit in the configuration corresponding to * the unit index, return -1. */ up = Dev_to_unitb( dev ); if( up == NULL || !up->flags.online ) return( -1 ); /* As a sanity check, panic if the partition table information * is not marked valid. */ if( up->part_info.pt_valid != PT_VALID ) panic( "mscp_size: invalid partition table\n" ); /* If the actual size of the partition is specified (not -1), return it * to the caller. Otherwise, calculate the partition size as the size of * the user-accessible area of the disk minus the starting LBN of the * partition, and return it to the caller. */ if(( part_size = up->part_info.pt_part[ px ].pi_nblocks ) != -1 ) return( part_size ); else return( up->unt_size - up->part_info.pt_part[ px ].pi_blkoff );}/**//* * * Name: mscp_getdefpt - get default partition information. * * Abstract: Find the partition information corresponding to the * input media ID and store it in a user-provided * partition structure. * * Inputs: * * Outputs: * * * Return NONE * Values: */void mscp_getdefpt( media_id, ptp ) u_long media_id; struct pt *ptp;{ register int i; register PART_SIZE *psp; /* Look up the media ID in the disk media table. If it isn't found, use * reserved entry 0 as the default media type. */ for( i = dmscp_media_ct - 1; i > 0 && dmscp_media[ i ].media_id != media_id; i-- ) ; /* Move the default partition values for the device (medium) into * the user's partition structure. */ psp = dmscp_media[ i ].part_sizes; for( i = 0; i <= 7; i++, psp++ ) { ptp->pt_part[ i ].pi_nblocks = psp->p_nblocks; ptp->pt_part[ i ].pi_blkoff = psp->p_blkoff; } return;}/**//* * * Name: mscp_check_sysdev - check/wait for system device availability. * * Abstract: A requested device has been found to be unconfigured. * Check to see if the device is the root, swap or dump * device specified in the configuration file and if so, * wait for the device to become available. If the device * is none of the foregoing, return an ENXIO error. * * Inputs: * * Outputs: * * * Return NONE * Values: */UNITB *mscp_check_sysdev( dev ) dev_t dev;{ register UNITB *up = NULL; register struct swdevt *sp; register int retries = 120; dev_t dev_min,dev_maj; /* If the given device is one of the swap devices or is * the root or dump device, wait for it to be configured. */ for( sp = &swdevt[ 0 ]; ( dev_t )sp->sw_dev != 0 && ( dev_t )dev != ( dev_t )sp->sw_dev; sp++ ) ; if( ( dev_t )dev == ( dev_t )sp->sw_dev || ( dev_t )dev == ( dev_t )rootdev || ( dev_t )dev == ( dev_t )dumpdev ) while(( up = Dev_to_unitb( dev )) == NULL && ( --retries >= 0 )) { /* if we're half way through the wait give some status */ if( retries == 60 ) { dev_maj = major(dev); dev_min = minor(dev); if( ( dev_t )dev == ( dev_t )sp->sw_dev ) printf("Waiting up to 1 more minute for swap device \(%d,%d\) to become available\n", dev_maj,dev_min); else if( ( dev_t )dev == ( dev_t )rootdev ) printf("Waiting up to 1 more minute for root device \(%d,%d\) to become available\n", dev_maj,dev_min); else if( ( dev_t )dev == ( dev_t )dumpdev ) printf("Waiting up to 1 more minute for dump device \(%d,%d\) to become available\n", dev_maj,dev_min); } timeout( wakeup, ( caddr_t )dev, 1*hz ); ( void )sleep(( caddr_t )dev, PSWP+1 ); } return( up );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -