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

📄 rf_paritylog.c

📁 RAIDFrame是个非常好的磁盘阵列RAID仿真工具
💻 C
📖 第 1 页 / 共 3 页
字号:
static void RequeueParityLogData(  RF_ParityLogData_t   *data,  RF_ParityLogData_t  **head,  RF_ParityLogData_t  **tail){  RF_Raid_t *raidPtr;  /* Insert an in-core parity log (*data) into the tail of     a disk queue (*head, *tail).     NON-BLOCKING */  raidPtr = data->common->raidPtr;  RF_ASSERT(data);  if (rf_parityLogDebug)    printf("[requeueing parity log data, region %d, raidAddress %d, numSector %d]\n",data->regionID,data->diskAddress.raidAddress, data->diskAddress.numSector);  RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);  if (*tail)    {      /* append to tail of list */      data->prev = *tail;      data->next = NULL;      (*tail)->next = data;      *tail = data;    }  else    {      /* inserting into an empty list */      *head = data;      *tail = data;      (*head)->prev = NULL;      (*tail)->next = NULL;    }  RF_ASSERT((*head)->prev == NULL);  RF_ASSERT((*tail)->next == NULL);  RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);}RF_ParityLogData_t *rf_CreateParityLogData(  RF_ParityRecordType_t    operation,  RF_PhysDiskAddr_t       *pda,  caddr_t                  bufPtr,  RF_Raid_t               *raidPtr,  int                    (*wakeFunc)(),  void                    *wakeArg,  RF_AccTraceEntry_t      *tracerec,  RF_Etimer_t              startTime){  RF_ParityLogData_t *data, *resultHead = NULL, *resultTail = NULL;  RF_CommonLogData_t *common;  RF_PhysDiskAddr_t *diskAddress;  int boundary, offset = 0;  /* Return an initialized struct of info to be logged.     Build one item per physical disk address, one item per region.     NON-BLOCKING */  diskAddress = pda;  common = AllocParityLogCommonData(raidPtr);  RF_ASSERT(common);  common->operation = operation;  common->bufPtr = bufPtr;  common->raidPtr = raidPtr;  common->wakeFunc = wakeFunc;  common->wakeArg = wakeArg;  common->tracerec = tracerec;  common->startTime = startTime;  common->cnt = 0;  if (rf_parityLogDebug)    printf("[entering CreateParityLogData]\n");  while (diskAddress)    {      common->cnt++;      data = AllocParityLogData(raidPtr);      RF_ASSERT(data);      data->common = common;      data->next = NULL;      data->prev = NULL;      data->regionID = rf_MapRegionIDParityLogging(raidPtr, diskAddress->startSector);      if (data->regionID == rf_MapRegionIDParityLogging(raidPtr, diskAddress->startSector + diskAddress->numSector - 1))	{	  /* disk address does not cross a region boundary */	  data->diskAddress = *diskAddress;	  data->bufOffset = offset;	  offset = offset + diskAddress->numSector;	  EnqueueParityLogData(data, &resultHead, &resultTail);	  /* adjust disk address */	  diskAddress = diskAddress->next;	}      else	{	  /* disk address crosses a region boundary */	  /* find address where region is crossed */	  boundary = 0;	  while (data->regionID == rf_MapRegionIDParityLogging(raidPtr, diskAddress->startSector + boundary))	    boundary++;	  /* enter data before the boundary */	  data->diskAddress = *diskAddress;	  data->diskAddress.numSector = boundary;	  data->bufOffset = offset;	  offset += boundary;	  EnqueueParityLogData(data, &resultHead, &resultTail);	  /* adjust disk address */	  diskAddress->startSector += boundary;	  diskAddress->numSector -= boundary;	}    }  if (rf_parityLogDebug)    printf("[leaving CreateParityLogData]\n");  return(resultHead);}RF_ParityLogData_t *rf_SearchAndDequeueParityLogData(  RF_Raid_t            *raidPtr,  int                   regionID,  RF_ParityLogData_t  **head,  RF_ParityLogData_t  **tail,  int                   ignoreLocks){  RF_ParityLogData_t *w;  /* Remove and return an in-core parity log from a specified region (regionID).     If a matching log is not found, return NULL.     NON-BLOCKING.     */  /* walk backward through a list, looking for an entry with a matching region ID */  if (!ignoreLocks)    RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);  w = (*tail);  while (w)    {      if (w->regionID == regionID)	{	  /* remove an element from the list */	  if (w == *tail)	    {	      if (*head == *tail)		{		  /* removing only element in the list */		  *head = NULL;		  *tail = NULL;		}	      else		{		  /* removing last item in the list */		  *tail = (*tail)->prev;		  (*tail)->next = NULL;		  RF_ASSERT((*head)->prev == NULL);		  RF_ASSERT((*tail)->next == NULL);		}	    }	  else	    {	      if (w == *head)		{		  /* removing first item in the list */		  *head = (*head)->next;		  (*head)->prev = NULL;		  RF_ASSERT((*head)->prev == NULL);		  RF_ASSERT((*tail)->next == NULL);		}	      else		{		  /* removing an item from the middle of the list */		  w->prev->next = w->next;		  w->next->prev = w->prev;		  RF_ASSERT((*head)->prev == NULL);		  RF_ASSERT((*tail)->next == NULL);		}	    }	  w->prev = NULL;	  w->next = NULL;	  if (rf_parityLogDebug)	    printf("[dequeueing parity log data, region %d, raidAddress %d, numSector %d]\n",w->regionID,w->diskAddress.raidAddress, w->diskAddress.numSector);	  return(w);	}      else	w = w->prev;    }  if (!ignoreLocks)    RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);  return(NULL);}static RF_ParityLogData_t *DequeueMatchingLogData(  RF_Raid_t            *raidPtr,  RF_ParityLogData_t  **head,  RF_ParityLogData_t  **tail){  RF_ParityLogData_t *logDataList, *logData;  int regionID;  /* Remove and return an in-core parity log from the tail of     a disk queue (*head, *tail).  Then remove all matching     (identical regionIDs) logData and return as a linked list.     NON-BLOCKING     */  logDataList = DequeueParityLogData(raidPtr, head, tail, RF_TRUE);  if (logDataList)    {      regionID = logDataList->regionID;      logData = logDataList;      logData->next = rf_SearchAndDequeueParityLogData(raidPtr, regionID, head, tail, RF_TRUE);      while (logData->next)	{	  logData = logData->next;	  logData->next = rf_SearchAndDequeueParityLogData(raidPtr, regionID, head, tail, RF_TRUE);	}    }  return(logDataList);}static RF_ParityLog_t *AcquireParityLog(  RF_ParityLogData_t  *logData,  int                  finish){  RF_ParityLog_t *log = NULL;  RF_Raid_t *raidPtr;  /* Grab a log buffer from the pool and return it.     If no buffers are available, return NULL.     NON-BLOCKING     */  raidPtr = logData->common->raidPtr;  RF_LOCK_MUTEX(raidPtr->parityLogPool.mutex);  if (raidPtr->parityLogPool.parityLogs)    {      log = raidPtr->parityLogPool.parityLogs;      raidPtr->parityLogPool.parityLogs = raidPtr->parityLogPool.parityLogs->next;      log->regionID = logData->regionID;      log->numRecords = 0;      log->next = NULL;      raidPtr->logsInUse++;      RF_ASSERT(raidPtr->logsInUse >= 0 && raidPtr->logsInUse <= raidPtr->numParityLogs);    }  else    {      /* no logs available, so place ourselves on the queue of work waiting on log buffers	 this is done while parityLogPool.mutex is held, to ensure synchronization	 with ReleaseParityLogs.	 */      if (rf_parityLogDebug)	printf("[blocked on log, region %d, finish %d]\n", logData->regionID, finish);      if (finish)	RequeueParityLogData(logData, &raidPtr->parityLogDiskQueue.logBlockHead, &raidPtr->parityLogDiskQueue.logBlockTail);      else	EnqueueParityLogData(logData, &raidPtr->parityLogDiskQueue.logBlockHead, &raidPtr->parityLogDiskQueue.logBlockTail);    }  RF_UNLOCK_MUTEX(raidPtr->parityLogPool.mutex);  return(log);}void rf_ReleaseParityLogs(  RF_Raid_t       *raidPtr,  RF_ParityLog_t  *firstLog){  RF_ParityLogData_t *logDataList;  RF_ParityLog_t *log, *lastLog;  int cnt;  /* Insert a linked list of parity logs (firstLog) to      the free list (parityLogPool.parityLogPool)     NON-BLOCKING.     */  RF_ASSERT(firstLog);  /* Before returning logs to global free list, service all     requests which are blocked on logs.  Holding mutexes for parityLogPool and parityLogDiskQueue     forces synchronization with AcquireParityLog().     */  RF_LOCK_MUTEX(raidPtr->parityLogPool.mutex);  RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);  logDataList = DequeueMatchingLogData(raidPtr, &raidPtr->parityLogDiskQueue.logBlockHead, &raidPtr->parityLogDiskQueue.logBlockTail);  log = firstLog;  if (firstLog)    firstLog = firstLog->next;  log->numRecords = 0;  log->next = NULL;  while (logDataList && log)    {      RF_UNLOCK_MUTEX(raidPtr->parityLogPool.mutex);      RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);      rf_ParityLogAppend(logDataList, RF_TRUE, &log, RF_FALSE);      if (rf_parityLogDebug)	printf("[finishing up buf-blocked log data, region %d]\n", logDataList->regionID);      if (log == NULL)	{	  log = firstLog;	  if (firstLog)	    {	      firstLog = firstLog->next;	      log->numRecords = 0;	      log->next = NULL;	    }	}      RF_LOCK_MUTEX(raidPtr->parityLogPool.mutex);      RF_LOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);      if (log)	logDataList = DequeueMatchingLogData(raidPtr, &raidPtr->parityLogDiskQueue.logBlockHead, &raidPtr->parityLogDiskQueue.logBlockTail);    }  /* return remaining logs to pool */  if (log)    {      log->next = firstLog;      firstLog = log;    }  if (firstLog)    {      lastLog = firstLog;      raidPtr->logsInUse--;      RF_ASSERT(raidPtr->logsInUse >= 0 && raidPtr->logsInUse <= raidPtr->numParityLogs);      while (lastLog->next)	{	  lastLog = lastLog->next;	  raidPtr->logsInUse--;	  RF_ASSERT(raidPtr->logsInUse >= 0 && raidPtr->logsInUse <= raidPtr->numParityLogs);	}      lastLog->next = raidPtr->parityLogPool.parityLogs;      raidPtr->parityLogPool.parityLogs = firstLog;      cnt = 0;      log = raidPtr->parityLogPool.parityLogs;      while (log)	{	  cnt++;	  log = log->next;	}      RF_ASSERT(cnt + raidPtr->logsInUse == raidPtr->numParityLogs);    }  RF_UNLOCK_MUTEX(raidPtr->parityLogPool.mutex);  RF_UNLOCK_MUTEX(raidPtr->parityLogDiskQueue.mutex);

⌨️ 快捷键说明

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