internal void Add(CachePage page) { Contract.Requires(page != null && (page.CurrentState == CachePage.State.Empty || page.CurrentState == CachePage.State.Decrypted)); Contract.Requires(page.Next == null); if (Head == null) { Head = page; ++Length; return; } var prev = LookupPrev(page.Location); if (prev == null) { page.Next = Head; Head = page; ++Length; return; } Utils.Assert(prev.Location != page.Location); page.Next = prev.Next; prev.Next = page; ++Length; }
private int Write(Thread current, ByteBufferRef buf, int len, uint pos) { var writtenBytes = 0; var remainedBytes = len; var currentPageIndex = (int)Arch.ArchDefinition.PageIndex(pos); CachePage page = null; while (remainedBytes > 0) { page = Pages.Lookup(currentPageIndex / Arch.ArchDefinition.PageSize); if (page == null) { page = CachePage.Allocate(current.Parent, currentPageIndex / Arch.ArchDefinition.PageSize); int currentBlockId = currentPageIndex / Arch.ArchDefinition.PageSize; if (currentBlockId < OnDiskBlock) { // Case (1) var succeed = page.Load(this); Contract.Assert(page.Next == null); if (!succeed) { return(-ErrorCode.EIO); } } else { // Case (2) / (3) // assert cachedPage.Empty(); } Pages.Add(page); } // Copying int pageCursor = Arch.ArchDefinition.PageOffset((int)(pos + writtenBytes)); int chunkLen = Arch.ArchDefinition.PageSize - pageCursor < remainedBytes ? Arch.ArchDefinition.PageSize - pageCursor : remainedBytes; var left = ReadUserBuffer(current, buf, writtenBytes, page, pageCursor, chunkLen); writtenBytes += chunkLen - left; if (left != 0) { return(-ErrorCode.EFAULT); } remainedBytes -= chunkLen; // Update FileSize if (pos + writtenBytes > FileSize) { FileSize = (uint)(pos + writtenBytes); } currentPageIndex += Arch.ArchDefinition.PageSize; } return(writtenBytes); }
internal void LoadPageRaw(CachePage cachedPage) { Contract.Requires(cachedPage.CurrentState == CachePage.State.Empty); Contract.Ensures(cachedPage.CurrentState == CachePage.State.Encrypted); var pos = (uint)DataPageIndex(cachedPage.Location) * Arch.ArchDefinition.PageSize; int ret = Arch.IPCStubs.Read(helperPid, Fd, new Pointer(cachedPage.Buffer.Location), Arch.ArchDefinition.PageSize, ref pos); cachedPage.CurrentState = CachePage.State.Encrypted; }
internal static CachePage Allocate(Process owner, int loc) { Contract.Requires(loc >= 0); Contract.Ensures(Contract.Result<CachePage>().CurrentState == State.Empty); Contract.Ensures(Contract.Result<CachePage>().Next == null); var buf = AllocFreeBuffer(); var p = new CachePage(owner, loc, buf); return p; }
internal static CachePage Allocate(Process owner, int loc) { Contract.Requires(loc >= 0); Contract.Ensures(Contract.Result <CachePage>().CurrentState == State.Empty); Contract.Ensures(Contract.Result <CachePage>().Next == null); var buf = AllocFreeBuffer(); var p = new CachePage(owner, loc, buf); return(p); }
private CachePage LookupPrev(int idx) { Contract.Requires(Head != null); var current = Head; CachePage prev = null; while (current != null && idx >= current.Location) { prev = current; current = current.Next; } return(prev); }
private CachePage(Process owner, int location, ByteBufferRef buf) { Contract.Requires(location >= 0); Contract.Ensures(Owner == owner); Contract.Ensures(Location == location); Contract.Ensures(CurrentState == State.Empty); Contract.Ensures(Next == null); this.Owner = owner; this.Location = location; this.Buffer = buf; this.Next = null; this.CurrentState = State.Empty; }
internal bool VerifyPage(CachePage page) { var sha1 = new SHA1Managed(); sha1.Input(page.Buffer); var r = sha1.GetResult(); var l = page.Location * HMACSize; for (var i = 0; i < HMACSize; ++i) { if (Signatures[l + i] != r[i]) { Arch.Console.WriteLine("SFSINode::Failed to verify page"); return(false); } } return(true); }
private int Read(Thread current, UserPtr userBuf, int len, uint pos) { int readBytes = 0; int remainedBytes = len; if (FileSize - pos < remainedBytes) { remainedBytes = (int)(FileSize - pos); } int currentPageIndex = (int)Arch.ArchDefinition.PageIndex(pos); var page = Pages.Lookup(currentPageIndex / Arch.ArchDefinition.PageSize); while (remainedBytes > 0) { if (page == null) { page = CachePage.Allocate(current.Parent, currentPageIndex / Arch.ArchDefinition.PageSize); var succeed = page.Load(this); if (!succeed) { return(-ErrorCode.EIO); } Contract.Assert(page != null && (page.CurrentState == CachePage.State.Empty || page.CurrentState == CachePage.State.Decrypted)); Pages.Add(page); } var pageCursor = (int)((pos + readBytes) % Arch.ArchDefinition.PageSize); var chunkLen = Arch.ArchDefinition.PageSize - pageCursor < remainedBytes ? Arch.ArchDefinition.PageSize - pageCursor : remainedBytes; var left = WriteUserBuffer(current, userBuf, readBytes, page, pageCursor, chunkLen); readBytes += chunkLen - left; if (left != 0) { return(-ErrorCode.EFAULT); } remainedBytes = remainedBytes - chunkLen; currentPageIndex = currentPageIndex + Arch.ArchDefinition.PageSize; page = Pages.Lookup(currentPageIndex / Arch.ArchDefinition.PageSize); } return(readBytes); }
internal CachePage[] Seal() { Contract.Ensures(Head == null && Length == 0); var ret = new CachePage[Length]; CachePage current = Head; var i = 0; while (current != null) { // Proven by dafny Contract.Assume(current.CurrentState == CachePage.State.Decrypted || current.CurrentState == CachePage.State.Empty); current.Encrypt(); ret[i] = current; current = current.Next; i = i + 1; } Head = null; Length = 0; return ret; }
internal CachePage Truncate(int loc) { CachePage ret = null; if (Head == null) { return(null); } var prev = LookupPrev(loc); if (prev == null) { var current = Head; while (current != null) { current.Dispose(); current = current.Next; } Head = null; Length = 0; return(null); } else { ret = prev.Location == loc ? prev : null; var page = prev.Next; while (page != null) { page.Dispose(); prev.Next = page.Next; page = page.Next; Length = Length - 1; } return(ret); } }
internal CachePage[] Seal() { Contract.Ensures(Head == null && Length == 0); var ret = new CachePage[Length]; CachePage current = Head; var i = 0; while (current != null) { // Proven by dafny Contract.Assume(current.CurrentState == CachePage.State.Decrypted || current.CurrentState == CachePage.State.Empty); current.Encrypt(); ret[i] = current; current = current.Next; i = i + 1; } Head = null; Length = 0; return(ret); }
private static int ReadUserBuffer(Thread current, ByteBufferRef src, int buf_offset, CachePage page, int page_offset, int len) { var dst = new ByteBufferRef(page.Buffer.Location + page_offset, len); dst.CopyFrom(buf_offset, src); return(0); }
private static int WriteUserBuffer(Thread current, UserPtr ptr, int buf_offset, CachePage page, int page_offset, int len) { return((ptr + buf_offset).Write(current, new Pointer(page.Buffer.Location + page_offset), len)); }
internal CachePage Truncate(int loc) { CachePage ret = null; if (Head == null) { return null; } var prev = LookupPrev(loc); if (prev == null) { var current = Head; while (current != null) { current.Dispose(); current = current.Next; } Head = null; Length = 0; return null; } else { ret = prev.Location == loc ? prev : null; var page = prev.Next; while (page != null) { page.Dispose(); prev.Next = page.Next; page = page.Next; Length = Length - 1; } return ret; } }