📄 volume.cxx
字号:
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 + -