📄 volume.cxx
字号:
::close(target_fd); if (target_fd != working_fd) close(working_fd); target_fd = -1; working_fd = -1;#if defined(__linux__) && 0 sync(); sleep(5); /* linux sync is busted - schedules */ /* the writes but doesn't do them. */ sync(); sleep(5); /* linux sync is busted - schedules */ /* the writes but doesn't do them. */#endif}uint32_tVolume::GetLogFrameVolOffset(int ndx, const OID& loc){ const Division& d = divTable[ndx]; assert(div_contains(&d, loc)); uint32_t relPage = (uint32_t) (loc - d.startOid); relPage /= EROS_OBJECTS_PER_FRAME; uint32_t divStart = d.start * EROS_SECTOR_SIZE; uint32_t pageOffset = relPage * EROS_PAGE_SIZE; return divStart + pageOffset;} uint32_tVolume::GetOidFrameVolOffset(int ndx, const OID& oid){ const Division& d = divTable[ndx]; assert(div_contains(&d, oid)); assert ((d.startOid % EROS_OBJECTS_PER_FRAME) == 0); uint32_t relPage = (uint32_t) ((oid - d.startOid) / EROS_OBJECTS_PER_FRAME); relPage += (relPage / DATA_PAGES_PER_PAGE_CLUSTER); relPage += 1; /* clusters precede data */ relPage += 1; /* skip ckpt sequence pg */ uint32_t divStart = d.start * EROS_SECTOR_SIZE; uint32_t pageOffset = relPage * EROS_PAGE_SIZE; return divStart + pageOffset;} /* Return true/false according to whether this is a valid object OID * given the frame type: */boolVolume::ValidOid(int ndx, const OID& oid){ const Division& d = divTable[ndx]; assert(div_contains(&d, oid)); assert (d.type != dt_Log); uint32_t obOffset = (uint32_t) (oid % EROS_OBJECTS_PER_FRAME); VolPagePot frameInfo; GetPagePotInfo(oid, frameInfo); switch (frameInfo.type) { case FRM_TYPE_ZDPAGE: case FRM_TYPE_DPAGE: return (obOffset == 0) ? true : false; case FRM_TYPE_NODE: return (obOffset < DISK_NODES_PER_PAGE) ? true : false; default: return false; }}/* given a division index and a OID, return the volume-relative * offset of the object in that division. */uint32_tVolume::GetOidVolOffset(int ndx, const OID& oid){ const Division& d = divTable[ndx]; assert(div_contains(&d, oid)); assert (d.type != dt_Log); uint32_t frameStart = GetOidFrameVolOffset(ndx, oid); uint32_t obOffset = (uint32_t) (oid % EROS_OBJECTS_PER_FRAME); if (obOffset) { VolPagePot frameInfo; GetPagePotInfo(oid, frameInfo); switch (frameInfo.type) { case FRM_TYPE_ZDPAGE: case FRM_TYPE_DPAGE: obOffset *= EROS_PAGE_SIZE; break; case FRM_TYPE_NODE: obOffset *= sizeof(DiskNode); break; default: Diag::fatal(1, "Unknown object type tag!\n"); } } if (obOffset >= EROS_PAGE_SIZE) Diag::fatal(1, "Bad OID (gives improper offset)\n"); return frameStart + obOffset;}boolVolume::GetPagePotInfo(const OID& oid, VolPagePot& pot){ CkptDirent* cpd = LookupObject(oid); if (cpd) { pot.count = cpd->count; pot.type = cpd->type; return true; } return ReadPagePotEntry(oid, pot);}/* Object I/O support: */boolVolume::ReadDataPage(const OID& oid, uint8_t *buf){ VolPagePot pp; if (oid % EROS_OBJECTS_PER_FRAME) { Diag::printf("Page OID must be multiple of %d (0x%x)\n", EROS_OBJECTS_PER_FRAME, EROS_OBJECTS_PER_FRAME); return false; } if ( GetPagePotInfo(oid, pp) == false ) { Diag::printf("Requested OID invalid\n"); return false; } switch(pp.type) { case FRM_TYPE_ZDPAGE: memset(buf, 0, EROS_PAGE_SIZE); return true; case FRM_TYPE_DPAGE: break; default: Diag::printf("Requested OID not a page frame\n"); return false; } CkptDirent* cpd = LookupObject(oid); if (cpd) { assert (CONTENT_LID(cpd->lid)); assert (cpd->type != FRM_TYPE_ZDPAGE); if (ReadLogPage(cpd->lid, buf) == false) return false; return true; } for (int div = 0; div < topDiv; div++) { Division& d = divTable[div]; if (((d.type == dt_Object) || (d.type == dt_Kernel)) && div_contains(&d, oid)) { if (ValidOid(div, oid) == false) { Diag::printf("Requested OID invalid\n"); return false; } VolPagePot frameInfo; ReadPagePotEntry(oid, frameInfo); if ((frameInfo.type != FRM_TYPE_DPAGE) && (frameInfo.type != FRM_TYPE_ZDPAGE)) { Diag::printf("Non-page frame\n"); return false; } uint32_t offset = GetOidVolOffset(div, oid); return Read(offset, buf, EROS_PAGE_SIZE); } } return false;}boolVolume::WriteDataPage(const OID& oid, const uint8_t *buf){ bool isZeroPage = true; for (uint32_t i = 0; i < EROS_PAGE_SIZE; i++) if (buf[i]) { isZeroPage = false; break; } CkptDirent* cpd = LookupObject(oid); if (cpd && cpd->type != FRM_TYPE_DPAGE && cpd->type != FRM_TYPE_ZDPAGE) return false; /* If a location has already been fabricated, write it there even if * it is a zero page. */ if ( cpd && CONTENT_LID(cpd->lid) ) { if (WriteLogPage(cpd->lid, buf) == false) return false; return true; } for (int div = 0; div < topDiv; div++) { Division& d = divTable[div]; if (((d.type == dt_Object) || (d.type == dt_Kernel)) && div_contains(&d, oid)) { VolPagePot frameInfo; ReadPagePotEntry(oid, frameInfo); assert ((oid % EROS_OBJECTS_PER_FRAME) == 0); uint8_t wantTag = isZeroPage ? FRM_TYPE_ZDPAGE : FRM_TYPE_DPAGE; if (frameInfo.type != wantTag) { Diag::debug(1, "Re-tagging frame for OID 0x%08x%08x to %d\n", (uint32_t) (oid >> 32), (uint32_t) (oid), wantTag); frameInfo.type = wantTag; WritePagePotEntry(oid, frameInfo); } uint32_t offset = GetOidVolOffset(div, oid); if ( !Write(offset, buf, EROS_PAGE_SIZE) ) Diag::fatal(5, "Volume write failed at offset %d.\n", offset); return true; } } if (rewriting == false) return false; /* If we get here, we didn't find what we wanted. Allocate space * for this page in the checkpoint log. */ Diag::fatal(1, "Cannot write page with OID 0x%08x%08x -- no home location\n", (uint32_t)(oid>>32), (uint32_t)oid); lid_t lid = ZERO_LID; uint8_t type = FRM_TYPE_ZDPAGE; if (isZeroPage == false) { lid = AllocLogPage(); type = FRM_TYPE_DPAGE; if (WriteLogPage(lid, buf) == false) return false; } AddDirent(oid, 0, lid, type); return true;}/* Log I/O support: */boolVolume::ReadLogPage(const lid_t lid, uint8_t *buf){ for (int div = 0; div < topDiv; div++) { Division& d = divTable[div]; if (d.type == dt_Log && div_contains(&d, lid)) { uint32_t offset = GetLogFrameVolOffset(div, lid); return Read(offset, buf, EROS_PAGE_SIZE); } } return false;}boolVolume::WriteLogPage(const lid_t lid, const uint8_t *buf){ for (int div = 0; div < topDiv; div++) { Division& d = divTable[div]; if (d.type == dt_Log && div_contains(&d, lid)) { uint32_t offset = GetLogFrameVolOffset(div, lid); if ( !Write(offset, buf, EROS_PAGE_SIZE) ) Diag::fatal(5, "Volume write failed at offset %d.\n", offset); } } return true;}/* given a division index and a OID, return the volume-relative * offset of the page pot for that OID */uint32_tVolume::GetOidPagePotVolOffset(int ndx, const OID& oid){ const Division& d = divTable[ndx]; assert(d.type == dt_Object); assert(div_contains(&d, oid)); assert ((d.startOid % EROS_OBJECTS_PER_FRAME) == 0); uint32_t relPage = (uint32_t) ((oid - d.startOid) / EROS_OBJECTS_PER_FRAME); uint32_t whichCluster = (uint32_t) (relPage / DATA_PAGES_PER_PAGE_CLUSTER); uint32_t pagePotFrame = whichCluster * PAGES_PER_PAGE_CLUSTER; pagePotFrame ++; /* for ckpt sequence number pg */ uint32_t pageOffset = pagePotFrame * EROS_PAGE_SIZE; uint32_t divStart = d.start * EROS_SECTOR_SIZE; return divStart + pageOffset;}boolVolume::ReadPagePotEntry(const OID& oid, VolPagePot& pagePot){ for (int div = 0; div < topDiv; div++) { Division& d = divTable[div]; uint8_t data[EROS_PAGE_SIZE]; if ( d.type == dt_Object && div_contains(&d, oid) ) { bool result; assert ((d.startOid % EROS_OBJECTS_PER_FRAME) == 0); uint32_t offset = GetOidPagePotVolOffset(div, oid); result = Read(offset, data, EROS_PAGE_SIZE); if (result == false) return result; uint32_t relPage = (uint32_t) ((oid - d.startOid) / EROS_OBJECTS_PER_FRAME); PagePot* pp = (PagePot *) data; uint32_t potEntry = relPage % DATA_PAGES_PER_PAGE_CLUSTER; pagePot.type = pp->type[potEntry]; pagePot.count = pp->count[potEntry]; return true; } } return false;}boolVolume::WritePagePotEntry(const OID& oid, const VolPagePot& pagePot){ for (int div = 0; div < topDiv; div++) { Division& d = divTable[div]; uint8_t data[EROS_PAGE_SIZE]; if ( d.type == dt_Object && div_contains(&d, oid) ) { bool result; assert ((d.startOid % EROS_OBJECTS_PER_FRAME) == 0); uint32_t offset = GetOidPagePotVolOffset(div, oid); result = Read(offset, data, EROS_PAGE_SIZE); if (result == false) return result; uint32_t relPage = (uint32_t) ((oid - d.startOid) / EROS_OBJECTS_PER_FRAME); PagePot* pp = (PagePot *) data; uint32_t potEntry = relPage % DATA_PAGES_PER_PAGE_CLUSTER; pp->type[potEntry] = pagePot.type; pp->count[potEntry] = pagePot.count; if ( !Write(offset, data, EROS_PAGE_SIZE) ) Diag::fatal(5, "Volume write failed at offset %d.\n", offset); return true; } } return false;}boolVolume::ReadNode(const OID& oid, DiskNode& node){ CkptDirent* ccd = LookupObject(oid); if (ccd && ccd->type == FRM_TYPE_NODE && ccd->lid != UNDEF_LID) { uint8_t logPage[EROS_PAGE_SIZE]; DiskNode* logPot = (DiskNode *) logPage; assert (CONTENT_LID(ccd->lid)); if (ReadLogPage(ccd->lid, logPage) == false) return false; for (uint32_t i = 0; i < DISK_NODES_PER_PAGE; i++) { if (logPot[i].oid == oid) { memcpy(&node, &logPot[i], sizeof(DiskNode)); return true; } } return false; } for (int div = 0; div < topDiv; div++) { Division& d = divTable[div]; if (d.type == dt_Object && div_contains(&d, oid)) { if (ValidOid(div, oid) == false) { Diag::printf("Requested OID invalid\n"); return false; } VolPagePot frameInfo; ReadPagePotEntry(oid, frameInfo); if (frameInfo.type != FRM_TYPE_NODE) { Diag::printf("Non-node frame\n"); return false; } uint32_t offset = GetOidVolOffset(div, oid); return Read(offset, &node, sizeof(DiskNode)); } } return false;}boolVolume::WriteNodeToLog(const OID& oid, const DiskNode& node){ assert (oid == node.oid); if (curLogPotLid == UNDEF_LID) { curLogPotLid = AllocLogPage(); } uint8_t logPage[EROS_PAGE_SIZE]; DiskNode* logPot = (DiskNode *) logPage; if (ReadLogPage(curLogPotLid, logPage) == false) return false; uint8_t ndx = curLogPotLid % EROS_OBJECTS_PER_FRAME; memcpy(&logPot[ndx], &node, sizeof(DiskNode)); if (WriteLogPage(curLogPotLid, logPage) == false) return false; AddDirent(oid, 0, curLogPotLid, FRM_TYPE_NODE); curLogPotLid++; if (curLogPotLid % EROS_OBJECTS_PER_FRAME == DISK_NODES_PER_PAGE) curLogPotLid = UNDEF_LID; return true;}boolVolume::WriteNode(const OID& oid, const DiskNode& node){ CkptDirent* ccd = LookupObject(oid); if (ccd && ccd->type != FRM_TYPE_NODE) return false; if (ccd && CONTENT_LID(ccd->lid)) { uint8_t logPage[EROS_PAGE_SIZE]; DiskNode* logPot = (DiskNode *) logPage; if (ReadLogPage(ccd->lid, logPage) == false) return false; for (uint32_t i = 0; i < DISK_NODES_PER_PAGE; i++) { if (logPot[i].oid == oid) { memcpy(&logPot[i], &node, sizeof(DiskNode)); if (WriteLogPage(ccd->lid, logPage) == false) return false; return true; } } return false; } for (int div = 0; div < topDiv; div++) { Division& d = divTable[div]; if (d.type == dt_Object && div_contains(&d, oid)) { VolPagePot frameInfo; ReadPagePotEntry(oid, frameInfo); if (frameInfo.type != FRM_TYPE_NODE) { Diag::debug(1, "Re-tagging frame for OID 0x%08x%08x to %d\n", (uint32_t) (oid >> 32), (uint32_t) (oid), FRM_TYPE_NODE); OID frameOID = oid & ~(EROS_OBJECTS_PER_FRAME - 1u); if ( ! FormatNodeFrame(div, frameOID) ) Diag::fatal(5, "Unable to format node frame 0x%08x%08x\n", (uint32_t) (frameOID >> 32), (uint32_t) frameOID); frameInfo.type = FRM_TYPE_NODE; WritePagePotEntry(oid, frameInfo); } uint32_t offset = GetOidVolOffset(div, oid); if ( !Write(offset, &node, sizeof(DiskNode)) ) Diag::fatal(5, "Volume write failed at offset %d.\n", offset); return true; } } if (rewriting == false) return false; /* If we get here, we didn't find what we wanted. Allocate space * for this node in the checkpoint log. */ Diag::fatal(1, "Cannot write node with OID 0x%08x%08x -- no home location\n", (uint32_t)(oid>>32), (uint32_t)oid); if ( !WriteNodeToLog(oid, node) ) Diag::fatal(5, "Volume write to log failed\n"); return true;} boolVolume::FormatNodeFrame(int div, OID frameOID){ char buf[EROS_PAGE_SIZE]; bzero (buf, EROS_PAGE_SIZE); DiskNode *pdn = (DiskNode *) buf; for (int nd = 0; nd < EROS_NODES_PER_FRAME; nd++) { pdn[nd].oid = frameOID + nd; for (uint32_t slot = 0; slot < EROS_NODE_SIZE; slot++) pdn[nd][slot] = VoidDiskKey(); } uint32_t offset = GetOidVolOffset(div, frameOID); return Write(offset, buf, EROS_PAGE_SIZE);}boolVolume::ContainsNode(const OID& oid){ CkptDirent* ccd = LookupObject(oid); if (ccd && ccd->type == FRM_TYPE_NODE) return true; VolPagePot frameInfo; if (ReadPagePotEntry(oid, frameInfo) == false) return false; if (frameInfo.type != FRM_TYPE_NODE) return false; return true;}boolVolume::ContainsPage(const OID& oid){ CkptDirent* ccd = LookupObject(oid); if (ccd && (ccd->type == FRM_TYPE_DPAGE || ccd->type == FRM_TYPE_ZDPAGE)) return true; VolPagePot frameInfo; if (ReadPagePotEntry(oid, frameInfo) == false) return false; if (frameInfo.type != FRM_TYPE_DPAGE && frameInfo.type != FRM_TYPE_ZDPAGE) return false; return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -