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

📄 rf_diskqueue.c

📁 RAIDFrame是个非常好的磁盘阵列RAID仿真工具
💻 C
📖 第 1 页 / 共 3 页
字号:
	rf_SstfPromote},	{"scan", /* SCAN (two-way elevator) */	rf_ScanCreate,	rf_SstfEnqueue,	rf_ScanDequeue,	rf_ScanPeek,	rf_SstfPromote},	{"cscan", /* CSCAN (one-way elevator) */	rf_CscanCreate,	rf_SstfEnqueue,	rf_CscanDequeue,	rf_CscanPeek,	rf_SstfPromote},#if !defined(KERNEL) && RF_INCLUDE_QUEUE_RANDOM > 0	/* to make a point to Chris :-> */	{"random", /* random */	rf_FifoCreate,	rf_FifoEnqueue,	rf_RandomDequeue,	rf_RandomPeek,	rf_FifoPromote},#endif /* !KERNEL && RF_INCLUDE_QUEUE_RANDOM > 0 */};#define NUM_DISK_QUEUE_TYPES (sizeof(diskqueuesw)/sizeof(RF_DiskQueueSW_t))static RF_FreeList_t *rf_dqd_freelist;#define RF_MAX_FREE_DQD 256#define RF_DQD_INC       16#define RF_DQD_INITIAL   64static int init_dqd(dqd)  RF_DiskQueueData_t  *dqd;{#ifdef KERNEL	dqd->bp = ubc_bufget();	if (dqd->bp == NULL) {		return(ENOMEM);	}#endif /* KERNEL */	return(0);}static void clean_dqd(dqd)  RF_DiskQueueData_t  *dqd;{#ifdef KERNEL    ubc_buffree(dqd->bp);#endif /* KERNEL */}/* configures a single disk queue */static int config_disk_queue(  RF_Raid_t            *raidPtr,  RF_DiskQueue_t       *diskqueue,  RF_RowCol_t           r, /* row & col -- debug only */  RF_RowCol_t           c,  RF_DiskQueueSW_t     *p,  RF_SectorCount_t      sectPerDisk,  dev_t                 dev,  int                   maxOutstanding,  RF_ShutdownList_t   **listp,  RF_AllocListElem_t   *clList){  int rc;  diskqueue->row = r;  diskqueue->col = c;  diskqueue->qPtr = p;  diskqueue->qHdr = (p->Create)(sectPerDisk, clList, listp);  diskqueue->dev  = dev;  diskqueue->numOutstanding = 0;  diskqueue->queueLength = 0;  diskqueue->maxOutstanding = maxOutstanding;  diskqueue->curPriority    = RF_IO_NORMAL_PRIORITY;  diskqueue->nextLockingOp  = NULL;  diskqueue->unlockingOp    = NULL;  diskqueue->numWaiting=0;  diskqueue->flags = 0;  diskqueue->raidPtr = raidPtr;  rc = rf_create_managed_mutex(listp, &diskqueue->mutex);  if (rc) {    RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n", __FILE__,      __LINE__, rc);    return(rc);  }  rc = rf_create_managed_cond(listp, &diskqueue->cond);  if (rc) {    RF_ERRORMSG3("Unable to init cond file %s line %d rc=%d\n", __FILE__,      __LINE__, rc);    return(rc);  }  return(0);}static void rf_ShutdownDiskQueueSystem(ignored)  void  *ignored;{  RF_FREELIST_DESTROY_CLEAN(rf_dqd_freelist,next,(RF_DiskQueueData_t *),clean_dqd);}int rf_ConfigureDiskQueueSystem(listp)  RF_ShutdownList_t  **listp;{  int rc;  RF_FREELIST_CREATE(rf_dqd_freelist, RF_MAX_FREE_DQD,    RF_DQD_INC, sizeof(RF_DiskQueueData_t));  if (rf_dqd_freelist == NULL)    return(ENOMEM);  rc = rf_ShutdownCreate(listp, rf_ShutdownDiskQueueSystem, NULL);  if (rc) {    RF_ERRORMSG3("Unable to add to shutdown list file %s line %d rc=%d\n",      __FILE__, __LINE__, rc);    rf_ShutdownDiskQueueSystem(NULL);    return(rc);  }  RF_FREELIST_PRIME_INIT(rf_dqd_freelist, RF_DQD_INITIAL,next,    (RF_DiskQueueData_t *),init_dqd);  return(0);}#ifndef KERNEL/* this is called prior to shutdown to wakeup everyone waiting on a disk queue * and tell them to exit */void rf_TerminateDiskQueues(raidPtr)  RF_Raid_t  *raidPtr;{  RF_RowCol_t r, c;  raidPtr->terminate_disk_queues = 1;  for (r=0; r<raidPtr->numRow; r++) {    for (c=0; c<raidPtr->numCol + ((r==0) ? raidPtr->numSpare : 0); c++) {      RF_LOCK_QUEUE_MUTEX(&raidPtr->Queues[r][c], "TerminateDiskQueues");      RF_BROADCAST_COND(raidPtr->Queues[r][c].cond);      RF_UNLOCK_QUEUE_MUTEX(&raidPtr->Queues[r][c], "TerminateDiskQueues");    }  }}#endif /* !KERNEL */int rf_ConfigureDiskQueues(  RF_ShutdownList_t  **listp,  RF_Raid_t           *raidPtr,  RF_Config_t         *cfgPtr){  RF_DiskQueue_t **diskQueues, *spareQueues;  RF_DiskQueueSW_t *p;  RF_RowCol_t r, c;  int rc, i;  raidPtr->maxQueueDepth = cfgPtr->maxOutstandingDiskReqs;  for(p=NULL,i=0;i<NUM_DISK_QUEUE_TYPES;i++) {    if (!strcmp(diskqueuesw[i].queueType, cfgPtr->diskQueueType)) {      p = &diskqueuesw[i];      break;    }  }  if (p == NULL) {    RF_ERRORMSG2("Unknown queue type \"%s\".  Using %s\n",cfgPtr->diskQueueType, diskqueuesw[0].queueType);    p = &diskqueuesw[0];  }  RF_CallocAndAdd(diskQueues, raidPtr->numRow, sizeof(RF_DiskQueue_t *), (RF_DiskQueue_t **), raidPtr->cleanupList);  if (diskQueues == NULL) {    return(ENOMEM);  }  raidPtr->Queues = diskQueues;  for (r=0; r<raidPtr->numRow; r++) {    RF_CallocAndAdd(diskQueues[r], raidPtr->numCol + ((r==0) ? raidPtr->numSpare : 0), sizeof(RF_DiskQueue_t), (RF_DiskQueue_t *), raidPtr->cleanupList);    if (diskQueues[r] == NULL)      return(ENOMEM);    for (c=0; c<raidPtr->numCol; c++) {      rc = config_disk_queue(raidPtr, &diskQueues[r][c], r, c, p,        raidPtr->sectorsPerDisk, raidPtr->Disks[r][c].dev,        cfgPtr->maxOutstandingDiskReqs, listp, raidPtr->cleanupList);      if (rc)        return(rc);    }  }  spareQueues = &raidPtr->Queues[0][raidPtr->numCol];  for (r=0; r<raidPtr->numSpare; r++) {    rc = config_disk_queue(raidPtr, &spareQueues[r], 0, r, p,      raidPtr->sectorsPerDisk, raidPtr->Disks[0][raidPtr->numCol+r].dev,      cfgPtr->maxOutstandingDiskReqs, listp, raidPtr->cleanupList);    if (rc)      return(rc);  }  return(0);}/* Enqueue a disk I/O * * Unfortunately, we have to do things differently in the different * environments (simulator, user-level, kernel). * At user level, all I/O is blocking, so we have 1 or more threads/disk * and the thread that enqueues is different from the thread that dequeues. * In the kernel, I/O is non-blocking and so we'd like to have multiple * I/Os outstanding on the physical disks when possible. * * when any request arrives at a queue, we have two choices: *    dispatch it to the lower levels *    queue it up * * kernel rules for when to do what: *    locking request:  queue empty => dispatch and lock queue, *                      else queue it *    unlocking req  :  always dispatch it *    normal req     :  queue empty => dispatch it & set priority *                      queue not full & priority is ok => dispatch it *                      else queue it * * user-level rules: *    always enqueue.  In the special case of an unlocking op, enqueue *    in a special way that will cause the unlocking op to be the next *    thing dequeued. * * simulator rules: *    Do the same as at user level, with the sleeps and wakeups suppressed. */void rf_DiskIOEnqueue(queue, req, pri)  RF_DiskQueue_t      *queue;  RF_DiskQueueData_t  *req;  int                  pri;{  int tid;  RF_ETIMER_START(req->qtime);  rf_get_threadid(tid);  RF_ASSERT(req->type == RF_IO_TYPE_NOP || req->numSector);  req->priority = pri;  if (rf_queueDebug && (req->numSector == 0)) {    printf("Warning: Enqueueing zero-sector access\n");  }  #ifdef KERNEL  /*   * kernel   */  RF_LOCK_QUEUE_MUTEX( queue, "DiskIOEnqueue" );  /* locking request */  if (RF_LOCKING_REQ(req)) {    if (RF_QUEUE_EMPTY(queue)) {      Dprintf3("Dispatching pri %d locking op to r %d c %d (queue empty)\n",pri,queue->row, queue->col);      RF_LOCK_QUEUE(queue);      rf_DispatchKernelIO(queue, req);    } else {      queue->queueLength++;  /* increment count of number of requests waiting in this queue */      Dprintf3("Enqueueing pri %d locking op to r %d c %d (queue not empty)\n",pri,queue->row, queue->col);      req->queue = (void *)queue;      (queue->qPtr->Enqueue)(queue->qHdr, req, pri);    }  }  /* unlocking request */  else if (RF_UNLOCKING_REQ(req)) {           /* we'll do the actual unlock when this I/O completes */    Dprintf3("Dispatching pri %d unlocking op to r %d c %d\n",pri,queue->row, queue->col);    RF_ASSERT(RF_QUEUE_LOCKED(queue));    rf_DispatchKernelIO(queue, req);  }  /* normal request */  else if (RF_OK_TO_DISPATCH(queue, req)) {    Dprintf3("Dispatching pri %d regular op to r %d c %d (ok to dispatch)\n",pri,queue->row, queue->col);    rf_DispatchKernelIO(queue, req);  } else {    queue->queueLength++;  /* increment count of number of requests waiting in this queue */    Dprintf3("Enqueueing pri %d regular op to r %d c %d (not ok to dispatch)\n",pri,queue->row, queue->col);    req->queue = (void *)queue;    (queue->qPtr->Enqueue)(queue->qHdr, req, pri);  }  RF_UNLOCK_QUEUE_MUTEX( queue, "DiskIOEnqueue" );  #else /* KERNEL */  /*   * user-level   */  RF_LOCK_QUEUE_MUTEX( queue, "DiskIOEnqueue" );  queue->queueLength++;  /* increment count of number of requests waiting in this queue */  /* unlocking request */  if (RF_UNLOCKING_REQ(req)) {    Dprintf4("[%d] enqueueing pri %d unlocking op & signalling r %d c %d\n", tid, pri, queue->row, queue->col);    RF_ASSERT(RF_QUEUE_LOCKED(queue) && queue->unlockingOp == NULL);    queue->unlockingOp = req;  }  /* locking and normal requests */  else {    req->queue = (void *)queue;    Dprintf5("[%d] enqueueing pri %d %s op & signalling r %d c %d\n", tid, pri,	     (RF_LOCKING_REQ(req)) ? "locking" : "regular",queue->row,queue->col);    (queue->qPtr->Enqueue)(queue->qHdr, req, pri);

⌨️ 快捷键说明

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