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

📄 rf_copyback.c

📁 RAIDFrame是个非常好的磁盘阵列RAID仿真工具
💻 C
📖 第 1 页 / 共 2 页
字号:
  desc->frow          = frow;  desc->fcol          = fcol;  desc->spRow         = badDisk->spareRow;  desc->spCol         = badDisk->spareCol;  desc->stripeAddr    = 0;  desc->sectPerSU     = raidPtr->Layout.sectorsPerStripeUnit;  desc->sectPerStripe = raidPtr->Layout.sectorsPerStripeUnit * raidPtr->Layout.numDataCol;  desc->databuf       = databuf;#ifndef SIMULATE  desc->mcpair        = rf_AllocMCPair();#endif /* !SIMULATE */  printf("COPYBACK: Quiescing the array\n");  /* quiesce the array, since we don't want to code support for user accs here */  rf_SuspendNewRequestsAndWait(raidPtr);  /* adjust state of the array and of the disks */  RF_LOCK_MUTEX(raidPtr->mutex);  raidPtr->Disks[desc->frow][desc->fcol].status = rf_ds_optimal;  raidPtr->status[desc->frow] = rf_rs_optimal;  rf_copyback_in_progress = 1;                   /* debug only */  RF_UNLOCK_MUTEX(raidPtr->mutex);    printf("COPYBACK: Beginning\n");  RF_GETTIME(desc->starttime);  rf_ContinueCopyback(desc);}/* * invoked via callback after a copyback I/O has completed to * continue on with the next one */void rf_ContinueCopyback(desc)  RF_CopybackDesc_t  *desc;{  RF_SectorNum_t testOffs, stripeAddr;  RF_Raid_t *raidPtr = desc->raidPtr;  RF_RaidAddr_t addr;  RF_RowCol_t testRow, testCol;   int old_pctg, new_pctg, done;  struct timeval t, diff;  old_pctg = (-1);  while (1) {    stripeAddr = desc->stripeAddr;    if (rf_prReconSched) {      old_pctg = 100 * desc->stripeAddr / raidPtr->totalSectors;    }    desc->stripeAddr += desc->sectPerStripe;    if (rf_prReconSched) {      new_pctg = 100 * desc->stripeAddr / raidPtr->totalSectors;      if (new_pctg != old_pctg) {        RF_GETTIME(t);        RF_TIMEVAL_DIFF(&desc->starttime, &t, &diff);        printf("%d %d.%06d\n",new_pctg, diff.tv_sec, diff.tv_usec);      }    }        if (stripeAddr >= raidPtr->totalSectors) {      rf_CopybackComplete(desc, 0);      return;    }        /* walk through the current stripe, su-by-su */    for (done=0, addr = stripeAddr; addr < stripeAddr+desc->sectPerStripe; addr += desc->sectPerSU) {            /* map the SU, disallowing remap to spare space */      (raidPtr->Layout.map->MapSector)(raidPtr, addr, &testRow, &testCol, &testOffs, RF_DONT_REMAP);            if (testRow == desc->frow && testCol == desc->fcol) {        rf_CopybackOne(desc, RF_COPYBACK_DATA, addr, testRow, testCol, testOffs);#ifdef SIMULATE        return;#else /* SIMULATE */        done = 1;        break;#endif /* SIMULATE */      }    }    if (!done) {      /* we didn't find the failed disk in the data part.  check parity. */          /* map the parity for this stripe, disallowing remap to spare space */      (raidPtr->Layout.map->MapParity)(raidPtr, stripeAddr, &testRow, &testCol, &testOffs, RF_DONT_REMAP);          if (testRow == desc->frow && testCol == desc->fcol) {        rf_CopybackOne(desc, RF_COPYBACK_PARITY, stripeAddr, testRow, testCol, testOffs);#ifdef SIMULATE        return;#endif /* SIMULATE */      }    }    /* check to see if the last read/write pair failed */    if (desc->status) {      rf_CopybackComplete(desc, 1);      return;    }        /* we didn't find any units to copy back in this stripe.  Continue with the next one */  }}/* copyback one unit */static void rf_CopybackOne(desc, typ, addr, testRow, testCol, testOffs)  RF_CopybackDesc_t  *desc;  int                 typ;  RF_RaidAddr_t       addr;  RF_RowCol_t         testRow;  RF_RowCol_t         testCol;  RF_SectorNum_t      testOffs;{  RF_SectorCount_t sectPerSU = desc->sectPerSU;  RF_Raid_t *raidPtr = desc->raidPtr;  RF_RowCol_t spRow     = desc->spRow;  RF_RowCol_t spCol     = desc->spCol;  RF_SectorNum_t spOffs;  /* find the spare spare location for this SU */  if (raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE) {    if (typ == RF_COPYBACK_DATA)      raidPtr->Layout.map->MapSector(raidPtr, addr, &spRow, &spCol, &spOffs, RF_REMAP);    else      raidPtr->Layout.map->MapParity(raidPtr, addr, &spRow, &spCol, &spOffs, RF_REMAP);        } else {    spOffs = testOffs;  }  /* create reqs to read the old location & write the new */  desc->readreq  = rf_CreateDiskQueueData(RF_IO_TYPE_READ, spOffs,    sectPerSU, desc->databuf, 0L, 0, rf_CopybackReadDoneProc, desc,    NULL, NULL, (void *) raidPtr, RF_DISKQUEUE_DATA_FLAGS_NONE, NULL);  desc->writereq = rf_CreateDiskQueueData(RF_IO_TYPE_WRITE, testOffs,    sectPerSU, desc->databuf, 0L, 0, rf_CopybackWriteDoneProc, desc,    NULL, NULL, (void *) raidPtr, RF_DISKQUEUE_DATA_FLAGS_NONE, NULL);  desc->frow = testRow;  desc->fcol = testCol;    /* enqueue the read.  the write will go out as part of the callback on the read.   * at user-level & in the kernel, wait for the read-write pair to complete.   * in the simulator, just return, since everything will happen as callbacks    */#ifndef SIMULATE  RF_LOCK_MUTEX(desc->mcpair->mutex);  desc->mcpair->flag = 0;#endif /* !SIMULATE */  rf_DiskIOEnqueue(&raidPtr->Queues[spRow][spCol], desc->readreq, RF_IO_NORMAL_PRIORITY);  #ifndef SIMULATE  while (!desc->mcpair->flag) {    RF_WAIT_MCPAIR(desc->mcpair);  }  RF_UNLOCK_MUTEX(desc->mcpair->mutex);  rf_FreeDiskQueueData(desc->readreq);  rf_FreeDiskQueueData(desc->writereq);#endif /* !SIMULATE */}/* called at interrupt context when the read has completed.  just send out the write */static int rf_CopybackReadDoneProc(desc, status)  RF_CopybackDesc_t  *desc;  int                 status;{  if (status) {                                              /* invoke the callback with bad status */    printf("COPYBACK: copyback read failed.  Aborting.\n");    (desc->writereq->CompleteFunc)(desc, -100);  }  else {    rf_DiskIOEnqueue(&(desc->raidPtr->Queues[desc->frow][desc->fcol]), desc->writereq, RF_IO_NORMAL_PRIORITY);  }  return(0);}/* called at interrupt context when the write has completed.   * at user level & in the kernel, wake up the copyback thread. * in the simulator, invoke the next copyback directly. * can't free diskqueuedata structs in the kernel b/c we're at interrupt context. */static int rf_CopybackWriteDoneProc(desc, status)  RF_CopybackDesc_t  *desc;  int                 status;{  if (status && status != -100) {    printf("COPYBACK: copyback write failed.  Aborting.\n");  }#ifdef SIMULATE  rf_FreeDiskQueueData(desc->readreq);  rf_FreeDiskQueueData(desc->writereq);  if (!status)    rf_ContinueCopyback(desc);  else    rf_CopybackComplete(desc, 1);#else /* SIMULATE */  desc->status = status;  rf_MCPairWakeupFunc(desc->mcpair);#endif /* SIMULATE */  return(0);}  /* invoked when the copyback has completed */static void rf_CopybackComplete(desc, status)  RF_CopybackDesc_t  *desc;  int                 status;{  RF_Raid_t *raidPtr = desc->raidPtr;  struct timeval t, diff;  if (!status) {    RF_LOCK_MUTEX(raidPtr->mutex);    if (raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE) {      RF_ASSERT(raidPtr->Layout.map->parityConfig == 'D');      rf_FreeSpareTable(raidPtr);    } else {      raidPtr->Disks[desc->spRow][desc->spCol].status = rf_ds_spare;    }    RF_UNLOCK_MUTEX(raidPtr->mutex);    RF_GETTIME(t);    RF_TIMEVAL_DIFF(&desc->starttime, &t, &diff);    printf("Copyback time was %d.%06d seconds\n",diff.tv_sec, diff.tv_usec);  } else printf("COPYBACK: Failure.\n");  RF_Free(desc->databuf, rf_RaidAddressToByte(raidPtr, desc->sectPerSU));#ifndef SIMULATE  rf_FreeMCPair(desc->mcpair);#endif /* !SIMULATE */  RF_Free(desc, sizeof(*desc));  rf_copyback_in_progress = 0;  rf_ResumeNewRequests(raidPtr);}

⌨️ 快捷键说明

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