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

📄 kern_persist.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 1998, 1999, 2001, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <kerninc/kernel.hxx>#include <kerninc/MsgLog.hxx>#include <kerninc/Check.hxx>#include <kerninc/Persist.hxx>#include <arch-kerninc/KernTune.hxx>#include <eros/memory.h>#include <disk/DiskNode.hxx>#include <disk/PagePot.hxx>#include <kerninc/ObjectCache.hxx>#include <kerninc/Thread.hxx>#include <kerninc/Node.hxx>#include <kerninc/util.h>#include <kerninc/Partition.hxx>#include <kerninc/Checkpoint.hxx>#include <kerninc/Persist.hxx>#include <eros/Invoke.h>#include <arch-kerninc/PTE.hxx>#define dbg_io     0x1		/* io requests */#define dbg_div    0x2		/* div tbl */#define dbg_req    0x4		/* requests (high level) */#define dbg_obread 0x8		/* low-level object reads *//* Following should be an OR of some of the above */#define dbg_flags   ( 0u )#define DEBUG(x) if (dbg_##x & dbg_flags)#ifndef NDEBUGextern bool InvocationCommitted;#endif/* static to ensure it ends up in BSS: */static CoreDivision coreDivTbl[KTUNE_NCOREDIV];void *CoreDivision::operator new(size_t /* sz */){  int i;  for (i = 0; i < KTUNE_NCOREDIV; i++) {    CoreDivision& cd = coreDivTbl[i];    if (cd.partition == 0) {      cd.partition = (Partition*) 0x1; /* HACK!! corrected in */				      /* constructor  */      return &cd;    }  }  return 0;}CoreDivision::CoreDivision(Partition* part, const Division& d){  *((Division*)this) = d;    partition = part;  #if 0  nPages = (end - start) / EROS_PAGE_SECTORS;  if (type == dt_Page)    nPages = endOid - startOid;#endif}voidPersist::RegisterDivision(Partition *part, const Division& d){  switch(d.type) {  case dt_Unused:  case dt_Boot:  case dt_DivTbl:  case dt_Spare:	/* These are silently ignored */#if 1    printf("Divsn on %s%d-%d, secs [%d,%d) (%s) skipped\n",		   part->ctrlr->name,		   part->unit, part->ndx,		   d.start, d.end,		   div_TypeName(d.type) );#endif    return;  case dt_Kernel:    break;  }    /* FIX: Verify that ranges do not overlap improperly */    bool isDuplex = false;  for (uint32_t i = 0; i < KTUNE_NCOREDIV; i++) {    if (coreDivTbl[i].type == d.type &&	coreDivTbl[i].startOid == d.startOid &&	coreDivTbl[i].endOid == d.endOid) {      isDuplex = true;      printf("It's a duplex\n");    }  }  CoreDivision *cd = new CoreDivision(part, d);  /* Kernel division is mounted as a page division: */  if (cd->type == dt_Kernel)    cd->type = dt_Object;  if (cd->type == dt_Log && isDuplex == false)    Checkpoint::AttachRange(d.startOid, d.endOid);      if (!cd)    fatal("Out of core divisions\n");  #if 1  printf("Divsn on %s%d-%d, secs [%d,%d)"		 " %s [",		 part->ctrlr->name,		 part->unit, part->ndx,		 cd->start, cd->end,		 (cd->type == dt_Log) ? "lid" : "oid");  print(cd->startOid);  printf(",");  print(cd->endOid);  printf(") (%s)\n", div_TypeName(d.type));#endif    return;}#ifdef OPTION_DDBvoidPersist::ddb_DumpDivisions(){  extern void db_printf(const char *, ...);    for (int i = 0; i < KTUNE_NCOREDIV; i++) {    if (coreDivTbl[i].type != dt_Unused) {      CoreDivision* cd = &coreDivTbl[i];      db_printf("Divsn on %s%d-%d, secs [%d,%d)"		     " oid [",		     cd->partition->ctrlr->name,		     cd->partition->unit, cd->partition->ndx,		     cd->start, cd->end);      db_printf("0x%08x%08x", (uint32_t) (cd->startOid >> 32),		(uint32_t) cd->startOid);      db_printf(",");      db_printf("0x%08x%08x", (uint32_t) (cd->endOid >> 32),		(uint32_t) cd->endOid);      db_printf(") (%s)\n", div_TypeName(cd->type));    }  }}#endifvoidPersist::UnregisterDivisions(Partition* part){  int i;  for (i = 0; i < KTUNE_NCOREDIV; i++) {    if (coreDivTbl[i].type != dt_Unused &&	coreDivTbl[i].partition == part)      delete &coreDivTbl[i];  }}boolPersist::HaveCkptLog(){  int i;  for (i = 0; i < KTUNE_NCOREDIV; i++) {    if (coreDivTbl[i].type == dt_Log)      return true;  }  return false;}/* In order to proceed, we must reserve an object page frame for the * inbound I/O (which will be grabbed later), we must verify that * there are a sufficiency of Request structures, and we must lay our * hands on the appropriate DuplexedIO structure for the OID we are * trying to load.  Having the DuplexedIO structures be keyed by OID * prevents redundant I/O on the same object.  Ensuring space to begin * with guarantees that a read will never preclude a write on a * hash-colliding OID, but we may later want to make read and write * DuplexedIO structures independent since the two operations * fundamentally cannot collide. *  * If a user thread fails to satisfy any of the conditions, it will * Yield() while having reserved an IO page frame.  The Yield code * checks for and takes care of this case, but note that kernel * threads and user threads call CommitIoPageFrame in different places * because kernel threads do not unwind completely.  We will * definitely need to reconsider what to do when tasks start * initiating I/O.  That issue in and of itself may be a sufficient * reason to retain kernel threads. *  * Finally, note that when invoked on log pages, this routine is * handed a LogLoc, not an OID. */voidPersist::ReadPageFrame( CoreDivision *pcd, uint32_t relativePage,			ObType::Type obty, OID oid,			ObCount count){  DEBUG(io) dprintf(true, "Reserving I/O frame...\n");  /* First make sure the I/O won't block: */  ObjectCache::ReserveIoPageFrame();    DEBUG(io) dprintf(true, "Reserving Requests...\n");  Request::Require(KTUNE_MAXDUPLEX);  DEBUG(io) dprintf(true, "Grabbing DIO...\n");  DuplexedIO *dio = DuplexedIO::Grab(oid, IoCmd::Read);  ObjectCache::CommitIoPageFrame();  DEBUG(io) dprintf(true, "Setting up request (dt=%s)...\n",			    div_TypeName(pcd->type));  dio->allocCount = count;  dio->obType = obty;  dio->isObjectRead = true;    /* I/O is free to complete while this loop is still running (happens   * mostly with ramdisk), so we need to go to sleep before queueing   * any of the requests.  Nothing below this point in this function   * will sleep, but we MUST avoid preemption until we yield   * voluntarily!   */  Thread::Current()->SleepOn(dio->stallQ);  uint32_t sectorOffset = relativePage * EROS_PAGE_SECTORS;    for (uint32_t i = 0; i < KTUNE_NCOREDIV; i++) {    CoreDivision *cd = &coreDivTbl[i];        DEBUG(div)      if (cd->type != dt_Unused)	dprintf(true, "Check cd %d (type %s) start=0x%x, end=0x%x\n",			i,			div_TypeName(cd->type),			(uint32_t) cd->startOid,			(uint32_t) cd->endOid);    if (cd->type != pcd->type)      continue;          if ( cd->startOid != pcd->startOid )      continue;	    /* Found a replicate of the right range. Queue the I/O on the     * device:      */    Partition *part = cd->partition;    assert(part);    Request *req = new Request(part->unit,			       IoCmd::Read, sectorOffset + cd->start, EROS_PAGE_SECTORS);    dio->AddRequest(req);    assert(req);    DEBUG(io) dprintf(true, "Insert request on %s%d-%d\n",			      part->ctrlr->name,			      part->unit,			      part->ndx);    part->InsertRequest(req);  }  DEBUG(io) dprintf(true, "Post-setup DIO release\n");  dio->Release();    Thread::Current()->Yield(/* true */);}voidPersist::ReadLogFrame(lid_t lid){  assert ((lid % EROS_OBJECTS_PER_FRAME) == 0);  CoreDivision * pcd = FindDivision(dt_Log, lid);  uint64_t relativeOid = lid - pcd->startOid;  uint32_t relativePage = relativeOid / EROS_OBJECTS_PER_FRAME;  ReadPageFrame( pcd, relativePage, ObType::PtLogPage, lid, 0 );}FrameInfo::FrameInfo(OID argOid){  oid = argOid;    cd = Persist::FindDivision(dt_Object, oid);  if (cd == 0)    return;  assert ((cd->startOid % EROS_OBJECTS_PER_FRAME) == 0);  uint64_t relativeOid = (oid - cd->startOid);  /* No, some of this calculation is NOT the most straightforward way,   * but I am trying to avoid divisions involving 64-bit quantities   * where the divisor is not a power of two.  Also, GCC seems to be   * barfing on some 64 bit x 32 bit multiplies in certain cases.   */    obFrameNdx = oid % EROS_OBJECTS_PER_FRAME;  obFrameOid = oid - obFrameNdx;  relObFrame = relativeOid / EROS_OBJECTS_PER_FRAME;  clusterNo = relObFrame / DATA_PAGES_PER_PAGE_CLUSTER;  tagEntry = relObFrame % DATA_PAGES_PER_PAGE_CLUSTER;  tagFrameOid = relObFrame - tagEntry;  tagFrameOid *= EROS_OBJECTS_PER_FRAME;  tagFrameOid += cd->startOid;  relObFrame += clusterNo;  relObFrame++;		/* add one for cluster pot */  relObFrame++;		/* add one for seq no */    relTagFrame = clusterNo * PAGES_PER_PAGE_CLUSTER;  relTagFrame++;		/* add one for seq no */#if 0  dprintf(false, "   OID=0x%08x%08x frmOid=0x%08x%08x tagOid=0x%08x%08x\n"                  " relFrm 0x%08x clusNo 0x%08x tagEnt 0x%08x tagFrame 0x%08x\n",                  (uint32_t) (oid >> 32),                  (uint32_t) (oid),                  (uint32_t) (obFrameOid >> 32),                  (uint32_t) (obFrameOid),                  (uint32_t) (tagFrameOid >> 32),                  (uint32_t) (tagFrameOid),                  relObFrame,                  clusterNo,                  tagEntry,                  relTagFrame);#endif  assert( tagEntry < DATA_PAGES_PER_PAGE_CLUSTER );  assert( obFrameNdx < EROS_OBJECTS_PER_FRAME );}CoreDivision*Persist::FindDivision(DivType dt, OID oid){  for (uint32_t i = 0; i < KTUNE_NCOREDIV; i++) {    CoreDivision *cd = &coreDivTbl[i];        if (cd->type != dt)      continue;          OID divOID = cd->startOid;    if (divOID > oid || cd->endOid <= oid)      continue;    return cd;  }  return 0;}ObjectHeader *Persist::GetObjectPot(FrameInfo& fi){#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("Top GetObjectPot()");#endif  if (fi.cd == 0)    fatal("Bad oid 0x%08x%08x to GetObjectPot()\n",		  (fi.oid >> 32), fi.oid);    ObjectHeader *obPotHdr =    ObjectHeader::Lookup(ObType::PtObjectPot, fi.obFrameOid);  if (obPotHdr) {#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("End GetObjectPot()");#endif    return obPotHdr;  }  /* Must load node pot: */  ReadPageFrame(fi.cd, fi.relObFrame, ObType::PtObjectPot,		fi.obFrameOid, 0);  assert (false);  return 0;}ObjectHeader *Persist::GetTagPot(FrameInfo& fi){#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("Top GetTagPot()");#endif  if (fi.cd == 0)    fatal("Bad oid 0x%08x%08x to GetTagPot()\n",		  (fi.oid >> 32), fi.oid);    ObjectHeader *tagPotHdr =    ObjectHeader::Lookup(ObType::PtAllocPot, fi.tagFrameOid);  if (tagPotHdr) {#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("End GetTagPot()");#endif    return tagPotHdr;  }  /* Must load node pot: */  ReadPageFrame(fi.cd, fi.relTagFrame, ObType::PtAllocPot,		fi.tagFrameOid, 0);  assert (false);  return 0;}Node *Persist::CopyDiskNode(FrameInfo &fi, DiskNode *nodePot){  if (nodePot[fi.obFrameNdx].oid != fi.oid)    dprintf(false, "oid=0x%08x%08x, potOid=0x%08x%08x ndOid=0x%08x%08x\n",		    (uint32_t) (fi.oid >> 32),		    (uint32_t) fi.oid,		    (uint32_t) (fi.obFrameOid >> 32),		    (uint32_t) fi.obFrameOid,		    (uint32_t) (nodePot[fi.obFrameNdx].oid >> 32),		    (uint32_t) (nodePot[fi.obFrameNdx].oid) );  assert (nodePot[fi.obFrameNdx].oid == fi.oid);  Node *pNode = ObjectCache::GrabNodeFrame();  assert(Thread::Current()->state == Thread::Running);  assert(ObjectCache::ValidNodePtr(pNode));  assert (pNode->kr.IsEmpty());  assert (pNode->obType == ObType::NtUnprepared);      (*pNode) = nodePot[fi.obFrameNdx];#ifdef OPTION_OB_MOD_CHECK  pNode->ob.check = pNode->CalcCheck();#endif  pNode->SetFlags(OFLG_CURRENT|OFLG_DISKCAPS);#ifdef OFLG_PIN  assert (pNode->GetFlags(OFLG_PIN) == 0);#endif  pNode->ClearFlags(OFLG_CKPT|OFLG_DIRTY|OFLG_REDIRTY|OFLG_IO);#ifdef DBG_CLEAN  printf("Object ty %d oid=0x%08x%08x loaded clean\n",		 pNode->obType,		 (uint32_t) (pNode->oid >> 32),		 (uint32_t) pNode->oid);#endif    pNode->ResetKeyRing();  pNode->Intern();  assert (pNode->Validate());  return pNode;}Node *Persist::GetNode(OID oid, ObCount count, bool useCount){  Node *pNode;  pNode = ObjectHeader::LookupNode(oid);  if (pNode) {#ifdef DBG_WILD_PTR    if (dbg_wild_ptr)      Check::Consistency("End GetNode()");#endif    assertex(pNode, pNode->Validate());    if (useCount && pNode->ob.allocCount != count)      return 0;          return pNode;  }  FrameInfo fi(oid);  if (fi.cd == 0) {    fatal("nd oid= 0x%08x%08x.  Should sleep on mountwait queue here\n",		  (uint32_t)(oid>>32), (uint32_t) oid);    return 0;  }#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("Top GetNode()");#endif  DEBUG(req) printf("Doing lookup on node 0x%08x%08x\n",			    (uint32_t) (oid >> 32),			    (uint32_t) oid);  assert (InvocationCommitted == false);    DEBUG(req) printf("Loading node from ckpt area\n");  CoreDirent* cde = Checkpoint::FindObject(oid, ObType::NtUnprepared,					   Checkpoint::current);  if (cde == 0)    return 0;    if (cde != CkNIL) {    if (cde->type != FRM_TYPE_NODE && cde->type != FRM_TYPE_ZNODE)      return 0;    if (useCount && cde->count != count)      return 0;    return Checkpoint::LoadCurrentNode(cde);  }      ObjectHeader *pPot = GetTagPot(fi);  assert (pPot);  PagePot *pp = (PagePot *) ObjectCache::ObHdrToPage(pPot);  if (pp->type[fi.tagEntry] != FRM_TYPE_NODE)    return 0;      DEBUG(req) printf("Loading node from home loc area\n");  ObjectHeader *nodePotHdr = GetObjectPot(fi);  assert(nodePotHdr);  nodePotHdr->TransLock();      DiskNode* nodePot = (DiskNode*) ObjectCache::ObHdrToPage(nodePotHdr);  pNode = CopyDiskNode(fi, nodePot);  nodePotHdr->TransUnlock();  if (useCount && pNode->ob.allocCount != count)    return 0;        assert (pNode->Validate());  return pNode;}ObjectHeader *Persist::GetPage(OID oid, ObCount count, bool useCount){#ifdef DBG_WILD_PTR  if (dbg_wild_ptr)    Check::Consistency("Top GetPage()");#endif  bool stop=false;      DEBUG(req)    dprintf(stop, "Doing lookup on page oid=0x%08x%08x\n",		    (uint32_t) (oid >> 32), (uint32_t) oid);  ObjectHeader *pPage;  pPage = ObjectHeader::Lookup(ObType::PtDataPage, oid);  if (pPage) {#ifdef DBG_WILD_PTR    if (dbg_wild_ptr)      Check::Consistency("End GetPage()");#endif    if (useCount && pPage->ob.allocCount != count)      return 0;

⌨️ 快捷键说明

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