⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rf_kintf.c

📁 RAIDFrame是个非常好的磁盘阵列RAID仿真工具
💻 C
📖 第 1 页 / 共 3 页
字号:
    /* make a copy of the recon request so that we don't rely on the user's buffer */    RF_Malloc(rrcopy, sizeof(*rrcopy), (struct rf_recon_req *));    bcopy(rr, rrcopy, sizeof(*rr));    rrcopy->raidPtr = (void *) raidPtrs[raidID];    LOCK_RECON_Q_MUTEX();    rrcopy->next = recon_queue;    recon_queue = rrcopy;    wakeup(&recon_queue);    UNLOCK_RECON_Q_MUTEX();        return(0);  /* invoke a copyback operation after recon on whatever disk needs it, if any */  case RAIDFRAME_COPYBACK:    /* borrow the current thread to get this done */    rf_CopybackReconstructedData(raidPtrs[raidID]);    return(0);  /* return the percentage completion of reconstruction */  case RAIDFRAME_CHECKRECON:    row = *(int *) data;    if (row < 0 || row >= raidPtrs[raidID]->numRow)      return(EINVAL);    if (raidPtrs[raidID]->status[row] != rf_rs_reconstructing) *(int *) data = 100;    else *(int *) data = raidPtrs[raidID]->reconControl[row]->percentComplete;    return(0);  /* the sparetable daemon calls this to wait for the kernel to need a spare table.   * this ioctl does not return until a spare table is needed.   * XXX -- calling mpsleep here in the ioctl code is almost certainly wrong and evil. -- XXX   * XXX -- I should either compute the spare table in the kernel, or have a different -- XXX   * XXX -- interface (a different character device) for delivering the table          -- XXX   */  case RAIDFRAME_SPARET_WAIT:    RF_LOCK_MUTEX(rf_sparet_wait_mutex);    while (!rf_sparet_wait_queue) mpsleep(&rf_sparet_wait_queue, (PZERO+1)|PCATCH, "sparet wait", 0, (void *) simple_lock_addr(rf_sparet_wait_mutex), MS_LOCK_SIMPLE);    waitreq = rf_sparet_wait_queue;    rf_sparet_wait_queue = rf_sparet_wait_queue->next;    RF_UNLOCK_MUTEX(rf_sparet_wait_mutex);    *((RF_SparetWait_t *) data) = *waitreq;              /* structure assignment */    RF_Free(waitreq, sizeof(*waitreq));    return(0);  /* wakes up a process waiting on SPARET_WAIT and puts an error code in it that will cause the dameon to exit */  case RAIDFRAME_ABORT_SPARET_WAIT:    RF_Malloc(waitreq, sizeof(*waitreq), (RF_SparetWait_t *));    waitreq->fcol = -1;    RF_LOCK_MUTEX(rf_sparet_wait_mutex);    waitreq->next = rf_sparet_wait_queue;    rf_sparet_wait_queue = waitreq;    RF_UNLOCK_MUTEX(rf_sparet_wait_mutex);    wakeup(&rf_sparet_wait_queue);    return(0);  /* used by the spare table daemon to deliver a spare table into the kernel */  case RAIDFRAME_SEND_SPARET:    /* install the spare table */    retcode = rf_SetSpareTable(raidPtrs[raidID],*(void **) data);    /* respond to the requestor.  the return status of the spare table installation is passed in the "fcol" field */    RF_Malloc(waitreq, sizeof(*waitreq), (RF_SparetWait_t *));    waitreq->fcol = retcode;    RF_LOCK_MUTEX(rf_sparet_wait_mutex);    waitreq->next = rf_sparet_resp_queue;    rf_sparet_resp_queue = waitreq;    wakeup(&rf_sparet_resp_queue);    RF_UNLOCK_MUTEX(rf_sparet_wait_mutex);        return(retcode);#endif   /* RAIDFRAME_RECON > 0 */  default:  break;               /* fall through to the os-specific code below */  }  	if (!raidPtrs[raidID]->valid)		return(EINVAL);	/*	 * Add support for "regular" device ioctls here.	 * Eventually, this may include disk label stuff.	 */  	switch (cmd) {		default:			retcode = EINVAL; break;	}	return(retcode);}/********************************************************* * * support code * ********************************************************/static int rf_WrapUpTestAcc(ta, raidPtr)  struct rf_test_acc   *ta;  RF_Raid_t            *raidPtr;{  struct buf *bp = (struct buf *)ta->bp;  int nbytes = ta->numSector << raidPtr->logBytesPerSector;  /* unwire memory */  vm_map_pageable(proc_to_task(bp->b_proc)->map, trunc_page(ta->buf),      round_page(ta->buf+nbytes), VM_PROT_NONE);  /* release the buf structure */  ubc_buffree(bp);  return(0);}/* allocate a new testacc descriptor & copy the input into it */static struct rf_test_acc *rf_DupTestAccDesc(ta)  struct rf_test_acc  *ta;{	struct rf_test_acc *new;	RF_Malloc(new,sizeof(struct rf_test_acc),(struct rf_test_acc *));	if (new == NULL)		return(NULL);	bcopy(ta, new, sizeof(*ta));	return(new);}/* the callback that gets invoked when an async test acc completes */static void rf_AsyncTestAccCallbackFunc(ta)  struct rf_test_acc   *ta;{  if (rf_debugKernelAccess) {    printf("completed async test acc %lx\n", ta);  }  /* place the testacc descriptor on the "done" list */  RF_LOCK_MUTEX(rf_async_done_q_mutex);  ta->next = NULL;  if (!rf_async_done_qt) rf_async_done_qt = rf_async_done_qh = ta;  else {rf_async_done_qt->next = ta; rf_async_done_qt = ta;}  RF_UNLOCK_MUTEX(rf_async_done_q_mutex);}/* the thread that does reconstruction in the kernel */void rf_ReconKernelThread(){  struct rf_recon_req *req;  RF_Thread_t thread;  thread = current_thread();  thread_swappable(thread, FALSE);  /* this is one priority level _lower_ than regular system threads */  thread->priority = thread->sched_pri = BASEPRI_SYSTEM+1;     spl0();  while (1) {    /* grab the next reconstruction request from the queue */    LOCK_RECON_Q_MUTEX();    while (!recon_queue) {      mpsleep(&recon_queue, PZERO, "recon q", 0,          (void *)simple_lock_addr(recon_queue_mutex), MS_LOCK_SIMPLE);    }    req = recon_queue;    recon_queue = recon_queue->next;    UNLOCK_RECON_Q_MUTEX();    /*     * If flags specifies that we should start recon, this call     * will not return until reconstruction completes, fails, or is aborted.     */    rf_FailDisk((RF_Raid_t *) req->raidPtr, req->row, req->col,        ((req->flags&RF_FDFLAGS_RECON) ? 1 : 0));    RF_Free(req, sizeof(*req));  }}/* wake up the daemon & tell it to get us a spare table * XXX * the entries in the queues should be tagged with the raidPtr  * so that in the extremely rare case that two recons happen at once, we know for * which device were requesting a spare table * XXX */int rf_GetSpareTableFromDaemon(req)  RF_SparetWait_t  *req;{  int retcode;  RF_LOCK_MUTEX(rf_sparet_wait_mutex);  req->next = rf_sparet_wait_queue;  rf_sparet_wait_queue = req;  wakeup(&rf_sparet_wait_queue);  /* mpsleep unlocks the mutex */  while (!rf_sparet_resp_queue) mpsleep(&rf_sparet_resp_queue, PZERO, "sparet resp", 0, (void *) simple_lock_addr(rf_sparet_wait_mutex), MS_LOCK_SIMPLE);  req = rf_sparet_resp_queue;  rf_sparet_resp_queue = req->next;  RF_UNLOCK_MUTEX(rf_sparet_wait_mutex);  retcode = req->fcol;  RF_Free(req, sizeof(*req));            /* this is not the same req as we alloc'd */  return(retcode);}/* map a page from user space to kernel space */caddr_t rf_MapToKernelSpace(bp, addr)  struct buf  *bp;  caddr_t      addr;{  vm_offset_t phys;  phys = pmap_extract(proc_to_task(bp->b_proc)->map->vm_pmap, addr);  if (!phys)    return(NULL);  return((caddr_t)PHYS_TO_KSEG(phys));}/* this does a bzero, remapping pages from user space to kernel space. * the caller must check to see if buf is already a kernel buffer, * and not invoke this if it is.  See the RF_BZERO macro in rf_degdags.c. * * rather stupid to muck around casting to/from caddr_t here. * I should really unify all this. */int rf_BzeroWithRemap(bp, databuf, len)  struct buf  *bp;  char        *databuf;  int          len;{  caddr_t kptr;  int len_this_time;    while (len > 0) {    len_this_time = RF_MIN(len, RF_BLIP(databuf));    kptr = (char *) rf_MapToKernelSpace(bp, (caddr_t) databuf);        /* XXX -- this condition is currently ignored & will cause a panic -- XXX */    if (!kptr)      return(EFAULT);        bzero(kptr, len_this_time);    len -= len_this_time;  }  return(0);}/* a wrapper around rf_DoAccess that extracts appropriate info from the bp & passes it down. * any calls originating in the kernel must use non-blocking I/O * do some extra sanity checking to return "appropriate" error values for * certain conditions (to make some standard utilities work) */int rf_DoAccessKernel(raidPtr, bp, flags, cbFunc, cbArg)  RF_Raid_t              *raidPtr;  struct buf             *bp;  RF_RaidAccessFlags_t    flags;  void                  (*cbFunc)();  void                   *cbArg;{	RF_SectorCount_t num_blocks, pb, sum;	RF_RaidAddr_t raid_addr;	int retcode;	raid_addr = bp->b_blkno;	num_blocks = bp->b_bcount >> raidPtr->logBytesPerSector;	pb = (bp->b_bcount&raidPtr->sectorMask) ? 1 : 0;	sum = raid_addr + num_blocks + pb;	if (rf_debugKernelAccess) {		printf("raid_addr=%ld sum=%ld\n", (long)raid_addr, (long)sum);	}	if ((sum >= raidPtr->totalSectors) || (sum < raid_addr)			|| (sum < num_blocks) || (sum < pb))	{		bp->b_error = ENOSPC;		bp->b_flags |= B_ERROR;		bp->b_resid = bp->b_bcount;		biodone(bp);		return(bp->b_error);	}	/*	 * XXX rf_DoAccess() should do this, not just DoAccessKernel()	 */	if (bp->b_bcount & raidPtr->sectorMask) {		bp->b_error = EINVAL;		bp->b_flags |= B_ERROR;		bp->b_resid = bp->b_bcount;		biodone(bp);		return(bp->b_error);	}	/* don't ever condition on bp->b_flags & B_WRITE.  always condition on B_READ instead */	retcode = rf_DoAccess(raidPtr, (bp->b_flags & B_READ) ? RF_IO_TYPE_READ : RF_IO_TYPE_WRITE,			0, raid_addr, num_blocks, bp->b_un.b_addr, bp, NULL, NULL,			RF_DAG_NONBLOCKING_IO|flags, NULL, cbFunc, cbArg);	return(retcode);}/* invoke an I/O from kernel mode.  Disk queue should be locked upon entry */int rf_DispatchKernelIO(queue, req)  RF_DiskQueue_t      *queue;  RF_DiskQueueData_t  *req;{  int retcode, op = (req->type == RF_IO_TYPE_READ) ? B_READ : B_WRITE;  struct buf *bp;  req->queue = queue;  switch (req->type) {  case RF_IO_TYPE_NOP:            /* used primarily to unlock a locked queue */    Dprintf2("rf_DispatchKernelIO: NOP to r %d c %d\n",queue->row,queue->col);    req->bp->b_driver_un_1.pointvalue = (void *) req;    queue->numOutstanding++;    KernelWakeupFunc(req->bp);    break;      case RF_IO_TYPE_READ:  case RF_IO_TYPE_WRITE:    if (req->tracerec) {      RF_ETIMER_START(req->tracerec->timer);    }    bp = req->bp;    InitBP(bp, op, queue->dev, req->sectorOffset, req->numSector, req->buf,      KernelWakeupFunc, (void *) req,  queue->raidPtr->logBytesPerSector,      req->b_proc);    if (rf_debugKernelAccess) {      printf("dispatch: bp->b_blkno = %ld\n", bp->b_blkno);    }    queue->numOutstanding++;    queue->last_deq_sector = req->sectorOffset;    /* acc wouldn't have been let in if there were any pending reqs at any other priority */    queue->curPriority = req->priority;    Dprintf3("rf_DispatchKernelIO: %c to row %d col %d\n", req->type, queue->row, queue->col);    BDEVSW_STRATEGY(major(bp->b_dev), bp, retcode);     /* no actual retcode here: cdisk_strategy has type void */    break;      default:    panic("bad req->type in rf_DispatchKernelIO");  }  return(0);}/* this is the callback function associated with a I/O invoked from kernel code. */static void KernelWakeupFunc(bp)  struct buf  *bp;{  RF_DiskQueueData_t *req = (RF_DiskQueueData_t *) bp->b_driver_un_1.pointvalue;  RF_DiskQueue_t *queue = (RF_DiskQueue_t *) req->queue;  if (req->tracerec) {	RF_ETIMER_STOP(req->tracerec->timer);	RF_ETIMER_EVAL(req->tracerec->timer);    RF_LOCK_MUTEX(rf_tracing_mutex);    req->tracerec->diskwait_us += RF_ETIMER_VAL_US(req->tracerec->timer);    req->tracerec->phys_io_us += RF_ETIMER_VAL_US(req->tracerec->timer);    req->tracerec->num_phys_ios++;    RF_UNLOCK_MUTEX(rf_tracing_mutex);  }  rf_DiskIOComplete(queue, req, (bp->b_flags & B_ERROR) ? 1 : 0);  (req->CompleteFunc)(req->argument, (bp->b_flags & B_ERROR) ? 1 : 0);}/* * creates a buf structure for doing an I/O in the kernel. */static void InitBP(  struct buf         *bp,  unsigned            rw_flag,  dev_t               dev,  RF_SectorNum_t      startSect,  RF_SectorCount_t    numSect,  caddr_t             buf,  void              (*cbFunc)(),  void               *cbArg,  int                 logBytesPerSector,  struct proc        *b_proc){  bp->b_flags       = B_PHYS | rw_flag;  bp->b_bcount      = numSect << logBytesPerSector;  bp->b_bufsize     = bp->b_bcount;  bp->b_error       = 0;  bp->b_dev         = dev;  bp->b_un.b_addr   = buf;  bp->b_blkno       = startSect;  bp->b_resid       = 0;  bp->b_proc        = b_proc;  bp->b_iodone      = cbFunc;  bp->b_driver_un_1.pointvalue = cbArg;             /* used as the argument to the callback */  bp->b_vp          = NULL;}#endif /* KERNEL */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -