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

📄 volume.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 3 页
字号:
Volume::DivisionClearFlags(int ndx, uint32_t flags){  assert(working_fd >= 0);  if (ndx >= topDiv)    Diag::fatal(1, "Attempt to update flags for nonexistent division\n");  divTable[ndx].flags &= ~flags;  Diag::printf("Division %d: flags set to [ ", ndx);  if (divTable[ndx].flags & DF_PRELOAD)    Diag::printf("preload ");  Diag::printf("]\n");  needSyncDivisions = true;  return divTable[ndx].flags;}uint32_tVolume::GetDivisionFlags(int ndx){  assert(working_fd >= 0);  if (ndx >= topDiv)    Diag::fatal(1, "Attempt to get flags for nonexistent division\n");  return divTable[ndx].flags;}voidVolume::WriteBootImage(const char *bootName){  assert(working_fd >= 0);  if (bootName) {    ExecImage bootImage;    if ( !bootImage.SetImage(bootName) ) {      App.SetExitValue(1);      App.Exit();			/* diagnostics generated by SegImage. */    }    WriteImageAtDivisionOffset(0, bootImage, 0);  }  else {    ZeroDivision(0);  }    uint8_t buf[EROS_PAGE_SIZE];  if (!Read(0, buf, EROS_PAGE_SIZE))    Diag::fatal(1, "Unable to read boot sector\n");    /* copy leading jump into volume header */  memcpy(volHdr.code, buf, sizeof(volHdr.code));  /* Recompute the image size from the division table: */  volHdr.VolSectors = 0;  if (bootName)    volHdr.BootFlags |= VolHdr::VF_BOOT;  else    volHdr.BootFlags &= ~VolHdr::VF_BOOT;    for (int i = 0; i < topDiv; i++) {    if (divTable[i].end > volHdr.VolSectors)      volHdr.VolSectors = divTable[i].end;  }    /* put the volume header on the boot sector */  memcpy(buf, &volHdr, sizeof(volHdr));  if (!Write(0, buf, EROS_PAGE_SIZE))    Diag::fatal(1, "Unable to read boot sector\n");  needSyncHdr = 0;}intVolume::Create(const char* targname, const char* bootName){#if 0  if (!pDisk)    Diag::fatal(2, "Disk model undefined\n");#endif    assert(working_fd == -1);  assert(target_fd == -1);    InitVolume();    volHdr.HdrVersion = VOLHDR_VERSION;  volHdr.PageSize = EROS_PAGE_SIZE;  volHdr.DivTable = 0;  volHdr.AltDivTable = 0;  volHdr.BootFlags = 0;  volHdr.BootSectors = DISK_BOOTSTRAP_SECTORS;  volHdr.VolSectors = 0;  volHdr.zipLen = 0;  volHdr.iplKey = VoidDiskKey();  volHdr.iplSysId = time(NULL); /* get a random value, hopefully unique  */  volHdr.signature[0] = 'E';  volHdr.signature[1] = 'R';  volHdr.signature[2] = 'O';  volHdr.signature[3] = 'S';    /* Open the target file */  target_fd = ::open(targname, O_RDWR|O_TRUNC);  if (target_fd < 0 && errno == ENOENT)    target_fd = ::open(targname, O_RDWR|O_CREAT, 0666);  if (target_fd < 0)    return 0;    /* Either way, target is now clobbered, so arrange to delete it if     we screw up. */  App.AddTarget(targname);    /* We assume uncompressed until told otherwise */  working_fd = target_fd;    int i;  for (i = 0; i < NDIVENT; i++)    divNeedsInit[i] = false;      /* Add division table entries for standard items: */  AddFixedDivision(dt_Boot, 0, DISK_BOOTSTRAP_SECTORS);  AddFixedDivision(dt_DivTbl, DISK_BOOTSTRAP_SECTORS,		   EROS_PAGE_SECTORS); #if 0  if (pDisk->badsecs)    AddDivision(dt_Spare, pDisk->badsecs);#endif  /* Must initialize divisions first, or writing boot page and   * sync'ing division tables will fail!   */  InitDivisions();    /* We write the boot page and division page immediately.  If   * this fails, the disk is quite bad.   */    WriteBootImage(bootName);    SyncDivTables();    return 1;}intVolume::Open(const char* targname, bool rewriting){  assert(working_fd == -1);  assert(target_fd == -1);    InitVolume();    /* Open the target file descriptor -- we will do nothing to disturb     its content until the call to Volume::Close() */  if ((target_fd = ::open(targname, O_RDWR)) < 0)    return 0;  working_fd = target_fd;    if (! Read(0, &volHdr, sizeof(volHdr)) )    Diag::fatal(3, "Couldn't read volume header\n");  DecompressTarget();    needSyncHdr = 0;    if ( !Read(EROS_SECTOR_SIZE * volHdr.DivTable,	   &divTable, NDIVENT * sizeof(Division)) )    Diag::fatal(3, "Couldn't read primary division table\n");  needSyncDivisions = 0;  needSyncCkptLog = 0;  int i;  for (i = 0; i < NDIVENT; i++)    divNeedsInit[i] = false;      /* interpret the newly loaded tables: */  for (i = 0; i < NDIVENT; i++) {    if (divTable[i].type == dt_Unused) {      topDiv = i;      break;    }    if (divTable[i].type == dt_Log &&	divTable[i].endOid > topLogLid) {      topLogLid = divTable[i].endOid;      lastAvailLogLid = divTable[i].endOid;    }  }  LoadLogHeaders();  if (rewriting == false && topLogLid) {    /* We are opening for volume debugging rather than writing an     * erosimage onto the volume.  We must therefore read in the     * directory of the existing checkpoint log.     */    LoadLogDirectory();  }    return 1;}voidVolume::LoadLogDirectory(){  assert(curDskCkpt);    uint32_t logEnt = 0;  /* Read in the reserve table: */  for (uint32_t d = 0; d < curDskCkpt->nRsrvPage; d++, logEnt++) {    uint8_t dirPage[EROS_PAGE_SIZE];    ReadLogPage(curDskCkpt->dirPage[logEnt], dirPage);    ReserveDirPage *rdp = (ReserveDirPage*) dirPage;    for (uint32_t entry = 0; entry < rdp->nDirent; entry++) {      CpuReserveInfo& cri = rdp->entry[entry];	      memcpy(&reserveTable[cri.index], &cri, sizeof(CpuReserveInfo));    }  }  /* Read the thread directory from the current checkpoint. */  for (uint32_t d = 0; d < curDskCkpt->nThreadPage; d++, logEnt++) {    uint8_t dirPage[EROS_PAGE_SIZE];    ReadLogPage(curDskCkpt->dirPage[logEnt], dirPage);    ThreadDirPage *tdp = (ThreadDirPage*) dirPage;    for (uint32_t entry = 0; entry < tdp->nDirent; entry++) {      ThreadDirent& tde = tdp->entry[entry];	      AddThread(tde.oid, tde.allocCount, tde.schedNdx);    }  }  /* Read the object directory from the current checkpoint. */  if (curDskCkpt->hasMigrated == false) {    for (uint32_t d = 0; d < curDskCkpt->nDirPage; d++, logEnt++) {      uint8_t dirPage[EROS_PAGE_SIZE];      ReadLogPage(curDskCkpt->dirPage[logEnt], dirPage);      CkptDirPage *dp = (CkptDirPage*) dirPage;      for (uint32_t entry = 0; entry < dp->nDirent; entry++) {	CkptDirent& de = dp->entry[entry];		AddDirent(de.oid, de.count, de.lid, de.type);      }    }  }}lid_tVolume::AllocLogPage(){  if (lastAvailLogLid <= firstAvailLogLid)    Diag::fatal(3, "Log pages exhausted\n");  lastAvailLogLid -= EROS_OBJECTS_PER_FRAME;  return lastAvailLogLid;}lid_tVolume::AllocLogDirPage(){  if (lastAvailLogLid <= firstAvailLogLid)    Diag::fatal(3, "Log pages exhausted\n");  lid_t theLid = firstAvailLogLid;  firstAvailLogLid += EROS_OBJECTS_PER_FRAME;  return theLid;}voidVolume::GrowCkptDir(){  AllocLogDirPage();  maxCkptDirent += CkptDirPage::maxDirEnt;  CkptDirent *newDir = new CkptDirent[maxCkptDirent];  if (ckptDir)    memcpy(newDir, ckptDir, nCkptDirent * sizeof(CkptDirent));  delete [] ckptDir;  ckptDir = newDir;}voidVolume::GrowThreadDir(){  AllocLogDirPage();  maxThreadDirent += ThreadDirPage::maxDirEnt;  ThreadDirent *newDir = new ThreadDirent[maxThreadDirent];  if (threadDir)    memcpy(newDir, threadDir, nThreadDirent * sizeof(ThreadDirent));  delete [] threadDir;  threadDir = newDir;}ThreadDirent*Volume::LookupThread(OID oid){  for (uint32_t i = 0; i < nThreadDirent; i++) {    if ( threadDir[i].oid == oid )      return &threadDir[i];  }  return 0;}CkptDirent*Volume::LookupObject(OID oid){  for (uint32_t i = 0; i < nCkptDirent; i++) {    if ( ckptDir[i].oid == oid )      return &ckptDir[i];  }  return 0;}voidVolume::AddDirent(OID oid, ObCount allocCount, lid_t lid, uint8_t ckObType){  CkptDirent* cpd = LookupObject(oid);    if (cpd == 0) {    if (maxCkptDirent == nCkptDirent)      GrowCkptDir();    cpd = &ckptDir[nCkptDirent];    nCkptDirent++;  }  cpd->oid = oid;  cpd->count = allocCount;  cpd->lid = lid;  cpd->type = ckObType;  needSyncCkptLog = true;}boolVolume::AddThread(const OID& oid, ObCount allocCount, uint16_t rsrvNdx){  ThreadDirent* tde = LookupThread(oid);  if (tde == 0) {    if (maxThreadDirent == nThreadDirent)      GrowThreadDir();    tde = &threadDir[nThreadDirent];    nThreadDirent++;  }  tde->oid = oid;  tde->allocCount = allocCount;  tde->schedNdx = rsrvNdx;  needSyncCkptLog = true;  return true;}voidVolume::LoadLogHeaders(){  ReadLogPage(0, (uint8_t*) dskCkptHdr0);  ReadLogPage(1*EROS_OBJECTS_PER_FRAME, (uint8_t*) dskCkptHdr1);  if (dskCkptHdr0->sequenceNumber > dskCkptHdr1->sequenceNumber) {    curDskCkpt = dskCkptHdr0;    oldDskCkpt = dskCkptHdr1;  }  else {    curDskCkpt = dskCkptHdr1;    oldDskCkpt = dskCkptHdr0;  }}voidVolume::SyncHdr(){  assert(working_fd >= 0);  char buf[EROS_PAGE_SIZE];    Read(0, buf, EROS_PAGE_SIZE);  /* Recompute the image size from the division table: */  volHdr.VolSectors = 0;  for (int i = 0; i < topDiv; i++) {    if (divTable[i].end > volHdr.VolSectors)      volHdr.VolSectors = divTable[i].end;  }    memcpy(buf, &volHdr, sizeof(volHdr));  Write(0, buf, EROS_PAGE_SIZE);  needSyncHdr = 0;}voidVolume::SyncCkptLog(){  if (!needSyncCkptLog)    return;    assert(working_fd >= 0);  assert((maxCkptDirent % CkptDirPage::maxDirEnt) == 0);  assert((maxThreadDirent % ThreadDirPage::maxDirEnt) == 0);  uint32_t dirPgCount = 0;  uint32_t startDirPage = 0;  uint32_t curDirLid = 2*EROS_OBJECTS_PER_FRAME;  uint8_t dirPage[EROS_PAGE_SIZE];  /* Write out the reserve table: */  CpuReserveInfo *cri = reserveTable;  uint32_t residual = MAX_CPU_RESERVE;  startDirPage = dirPgCount;    ReserveDirPage *rdp = (ReserveDirPage*) dirPage;  while (residual) {    uint32_t count = residual;    if (count > ReserveDirPage::maxDirEnt)      count = ReserveDirPage::maxDirEnt;    rdp->nDirent = count;        memcpy(rdp->entry, cri, sizeof(CpuReserveInfo) * count);    WriteLogPage(curDirLid, dirPage);    curDskCkpt->dirPage[dirPgCount] = curDirLid;    curDirLid += EROS_OBJECTS_PER_FRAME;    dirPgCount++;    cri += count;    residual -= count;  }	   curDskCkpt->nRsrvPage = dirPgCount - startDirPage;  /* Write out the thread directory: */  ThreadDirent* tde = threadDir;  residual = nThreadDirent;  startDirPage = dirPgCount;  ThreadDirPage *tdp = (ThreadDirPage*) dirPage;  while (residual) {    uint32_t count = residual;    if (count > ThreadDirPage::maxDirEnt)      count = ThreadDirPage::maxDirEnt;    tdp->nDirent = count;    memcpy(tdp->entry, tde, sizeof(ThreadDirent) * count);    WriteLogPage(curDirLid, dirPage);    curDskCkpt->dirPage[dirPgCount] = curDirLid;    curDirLid += EROS_OBJECTS_PER_FRAME;    dirPgCount++;    tde += count;    residual -= count;  }    curDskCkpt->nThreadPage = dirPgCount - startDirPage;  /* Write out the object directory: */  CkptDirent* cpd = ckptDir;  residual = nCkptDirent;  startDirPage = dirPgCount;  CkptDirPage *dp = (CkptDirPage*) dirPage;  while (residual) {    uint32_t count = residual;    if (count > CkptDirPage::maxDirEnt)      count = CkptDirPage::maxDirEnt;    dp->nDirent = count;    memcpy(dp->entry, cpd, sizeof(CkptDirent) * count);    WriteLogPage(curDirLid, dirPage);    curDskCkpt->dirPage[dirPgCount] = curDirLid;    curDirLid += EROS_OBJECTS_PER_FRAME;    dirPgCount++;    cpd += count;    residual -= count;  }    curDskCkpt->nDirPage = dirPgCount - startDirPage;  if (curDskCkpt->nDirPage)    curDskCkpt->hasMigrated = false;  else    curDskCkpt->hasMigrated = true;  /* I don't know which one is current -- just rewrite them both. */  WriteLogPage((lid_t)0, (uint8_t *) dskCkptHdr0);  WriteLogPage((lid_t)1*EROS_OBJECTS_PER_FRAME, (uint8_t *) dskCkptHdr1);    needSyncCkptLog = 0;}voidVolume::SyncDivTables(){  if (!needSyncDivisions)    return;    assert(working_fd >= 0);    for (int div = 0; div < topDiv; div++) {    Division& d = divTable[div];        if (d.type == dt_DivTbl) {      uint8_t buf[EROS_PAGE_SIZE];            uint32_t divStart = d.start * EROS_SECTOR_SIZE;      if ( !Read(divStart, buf, EROS_PAGE_SIZE) )	Diag::fatal(1, "Unable to read division table\n");      memcpy(buf, divTable, NDIVENT * sizeof(Division));            if ( !Write(divStart, buf, EROS_PAGE_SIZE) )	Diag::fatal(1, "Unable to write division table\n");    }  }  needSyncDivisions = false;}voidVolume::InitDivisions(){  int i;  for (i = 0; i < topDiv; i++)    if (divNeedsInit[i]) {      ZeroDivision(i);      if (divTable[i].type == dt_Object || divTable[i].type == dt_Kernel)	FormatObjectDivision(i);      if (divTable[i].type == dt_Log)	FormatLogDivision(i);      divNeedsInit[i] = false;    }  needDivInit = false;}voidVolume::ResetVolume(){  /* Used by sysgen to ensure that writing new data on an existing   * volume causes no problems.   */  for (int i = 0; i < topDiv; i++) {    if (divTable[i].type == dt_Object)      FormatObjectDivision(i);    if (divTable[i].type == dt_Log)      FormatLogDivision(i);  }}voidVolume::Close(){  /* If we are exiting on an error, there is no need to save anything,   * since the file has been deleted.   */  if (App.Aborting())    return;    InitDivisions();  SyncHdr();  SyncDivTables();  SyncCkptLog();  if (working_fd == -1)    return;    if (fsync(working_fd) == -1)    Diag::fatal(1, "Final fsync failed with errno %d\n", errno);    if (CompressTarget() < 0)    Diag::fatal(1, "Unable to compress target volume -- errno %d\n", errno);  

⌨️ 快捷键说明

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