Esempio n. 1
0
        internal bool HigherSequenceThan(LogSequence otherSequence)
        {
            ulong other = otherSequence.Count > 0 ? otherSequence.Head.SequenceNumber : 0;
            ulong self  = Count > 0 ? Head.SequenceNumber : 0;

            return(self > other);
        }
 internal DiskImageFileInfo(FileHeader fileHeader, VhdxHeader vhdxHeader1, VhdxHeader vhdxHeader2, RegionTable regions, Metadata metadata, LogSequence activeLogSequence)
 {
     _fileHeader        = fileHeader;
     _vhdxHeader1       = vhdxHeader1;
     _vhdxHeader2       = vhdxHeader2;
     _regions           = regions;
     _metadata          = metadata;
     _activeLogSequence = activeLogSequence;
 }
Esempio n. 3
0
        private LogSequence FindActiveLogSequence()
        {
            using (
                Stream logStream =
                    new CircularStream(new SubStream(_fileStream, (long)_header.LogOffset, _header.LogLength),
                                       Ownership.Dispose))
            {
                LogSequence candidateActiveSequence = new LogSequence();
                LogEntry    logEntry = null;

                long oldTail;
                long currentTail = 0;

                do
                {
                    oldTail = currentTail;

                    logStream.Position = currentTail;
                    LogSequence currentSequence = new LogSequence();

                    while (LogEntry.TryRead(logStream, out logEntry) &&
                           logEntry.LogGuid == _header.LogGuid &&
                           (currentSequence.Count == 0 ||
                            logEntry.SequenceNumber == currentSequence.Head.SequenceNumber + 1))
                    {
                        currentSequence.Add(logEntry);
                        logEntry = null;
                    }

                    if (currentSequence.Count > 0 &&
                        currentSequence.Contains(currentSequence.Head.Tail) &&
                        currentSequence.HigherSequenceThan(candidateActiveSequence))
                    {
                        candidateActiveSequence = currentSequence;
                    }

                    if (currentSequence.Count == 0)
                    {
                        currentTail += LogEntry.LogSectorSize;
                    }
                    else
                    {
                        currentTail = currentSequence.Head.Position + LogEntry.LogSectorSize;
                    }

                    currentTail = currentTail % logStream.Length;
                } while (currentTail > oldTail);

                return(candidateActiveSequence);
            }
        }
Esempio n. 4
0
        private void ReplayLog()
        {
            _freeSpace.Reserve((long)_header.LogOffset, _header.LogLength);

            _logicalStream = _fileStream;

            // If log is empty, skip.
            if (_header.LogGuid == Guid.Empty)
            {
                return;
            }

            LogSequence activeLogSequence = FindActiveLogSequence();

            if (activeLogSequence == null || activeLogSequence.Count == 0)
            {
                throw new IOException("Unable to replay VHDX log, suspected corrupt VHDX file");
            }

            if (activeLogSequence.Head.FlushedFileOffset > (ulong)_logicalStream.Length)
            {
                throw new IOException("truncated VHDX file found while replaying log");
            }

            if (activeLogSequence.Count > 1 || !activeLogSequence.Head.IsEmpty)
            {
                // However, have seen VHDX with a non-empty log with no data to replay.  These are
                // 'safe' to open.
                if (!_fileStream.CanWrite)
                {
                    SnapshotStream replayStream = new SnapshotStream(_fileStream, Ownership.None);
                    replayStream.Snapshot();
                    _logicalStream = replayStream;
                }
                foreach (LogEntry logEntry in activeLogSequence)
                {
                    if (logEntry.LogGuid != _header.LogGuid)
                    {
                        throw new IOException("Invalid log entry in VHDX log, suspected currupt VHDX file");
                    }
                    if (logEntry.IsEmpty)
                    {
                        continue;
                    }
                    logEntry.Replay(_logicalStream);
                }
                _logicalStream.Seek((long)activeLogSequence.Head.LastFileOffset, SeekOrigin.Begin);
            }
        }
Esempio n. 5
0
        private void ReplayLog()
        {
            _freeSpace.Reserve((long)_header.LogOffset, _header.LogLength);

            _logicalStream = _fileStream;

            // If log is empty, skip.
            if (_header.LogGuid == Guid.Empty)
            {
                return;
            }

            LogSequence activeLogSequence = FindActiveLogSequence();

            if (activeLogSequence == null || activeLogSequence.Count == 0)
            {
                throw new IOException("Unable to replay VHDX log, suspected corrupt VHDX file");
            }

            if (activeLogSequence.Count > 1 || !activeLogSequence.Head.IsEmpty)
            {
                // TODO - perform actual replay (needs VHDX with real log to replay)
                // However, have seen VHDX with a non-empty log with no data to replay.  These are
                // 'safe' to open.
                throw new NotImplementedException("Actual replay of VHDX logs not implemented yet");

                //// Have a log to replay, and the base stream is read-only. Use a snapshot stream to
                //// replay in RAM.
                ////if (!_fileStream.CanWrite)
                ////{
                ////    SnapshotStream replayStream = new SnapshotStream(_fileStream, Ownership.None);
                ////    replayStream.Snapshot();
                ////    _logicalStream = replayStream;
                ////}
            }
        }