예제 #1
0
        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;
        }
예제 #2
0
        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;
        }
예제 #3
0
        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);
        }
예제 #4
0
        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;
        }
예제 #5
0
        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;
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }
예제 #8
0
        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;
        }
예제 #9
0
        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;
        }
예제 #10
0
        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);
        }
예제 #11
0
        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);
        }
예제 #12
0
        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;
        }
예제 #13
0
        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);
            }
        }
예제 #14
0
        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);
        }
예제 #15
0
        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);
        }
예제 #16
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));
 }
예제 #17
0
        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;
            }
        }