public const int BackupBufferSizeLBA = 128; // there are about 180 contiguous free sectors in a private region /// <summary> /// Move extent to another disk /// </summary> public static void MoveExtentToAnotherDisk(List<DynamicDisk> disks, DynamicVolume volume, DynamicDiskExtent sourceExtent, DiskExtent relocatedExtent, ref long bytesCopied) { DiskGroupDatabase database = DiskGroupDatabase.ReadFromDisks(disks, volume.DiskGroupGuid); if (database == null) { throw new DatabaseNotFoundException(); } // copy the data long transferSizeLBA = Settings.MaximumTransferSizeLBA; for (long sectorIndex = 0; sectorIndex < relocatedExtent.TotalSectors; sectorIndex += transferSizeLBA) { long sectorsLeft = relocatedExtent.TotalSectors - sectorIndex; int sectorsToRead = (int)Math.Min(transferSizeLBA, sectorsLeft); byte[] data = sourceExtent.ReadSectors(sectorIndex, sectorsToRead); relocatedExtent.WriteSectors(sectorIndex, data); bytesCopied += sectorsToRead * sourceExtent.BytesPerSector; } // Update the database to point to the relocated extent DynamicDisk targetDisk = DynamicDisk.ReadFromDisk(relocatedExtent.Disk); DynamicDiskExtent dynamicRelocatedExtent = new DynamicDiskExtent(relocatedExtent, sourceExtent.ExtentID); dynamicRelocatedExtent.Name = sourceExtent.Name; dynamicRelocatedExtent.DiskGuid = targetDisk.DiskGuid; VolumeManagerDatabaseHelper.UpdateExtentLocation(database, volume, dynamicRelocatedExtent); }
/// <returns>In bytes</returns> public static long GetMaxNewExtentLength(DynamicDisk disk, long alignInSectors) { List <DiskExtent> unallocatedExtents = GetUnallocatedExtents(disk); if (unallocatedExtents == null) { return(-1); } long result = 0; for (int index = 0; index < unallocatedExtents.Count; index++) { DiskExtent extent = unallocatedExtents[index]; if (alignInSectors > 1) { extent = DiskExtentHelper.GetAlignedDiskExtent(extent, alignInSectors); } if (extent.Size > result) { result = extent.Size; } } return(result); }
public static VolumeManagerDatabase ReadFromDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock) { VolumeManagerDatabaseHeader databaseHeader = VolumeManagerDatabaseHeader.ReadFromDisk(disk, privateHeader, tocBlock); if (databaseHeader == null || !databaseHeader.IsVersionSupported) { return(null); } // The first VBLK entry is the subsequent entry to the VMDB header. // Note: On a disk with 4KB sectors, VBLKs will reside in the same sector as the VMDB header. ulong firstSector = privateHeader.PrivateRegionStartLBA + tocBlock.ConfigStart; // we skip the VMDB int databaseLength = (int)(databaseHeader.HeaderSize + databaseHeader.NumberOfVBlks * databaseHeader.BlockSize); int sectorCount = (int)Math.Ceiling(databaseLength / (double)disk.BytesPerSector); byte[] databaseBytes = disk.ReadSectors((long)firstSector, sectorCount); int numberOfFragments = (int)(databaseHeader.NumberOfVBlks - FirstSequenceNumber); List <DatabaseRecord> databaseRecords = ReadDatabaseRecords(databaseBytes, (int)databaseHeader.HeaderSize, (int)databaseHeader.BlockSize, numberOfFragments); // read all KLog blocks KernelUpdateLog kernelUpdateLog = KernelUpdateLog.ReadFromDisk(disk, privateHeader, tocBlock); DynamicDisk dynamicDisk = new DynamicDisk(disk, privateHeader, tocBlock); return(new VolumeManagerDatabaseCopy(dynamicDisk, databaseHeader, databaseRecords, kernelUpdateLog)); }
public VolumeManagerDatabaseCopy(DynamicDisk disk, VolumeManagerDatabaseHeader databaseHeader, List <DatabaseRecord> databaseRecords, KernelUpdateLog kernelUpdateLog) : base(databaseHeader, databaseRecords, kernelUpdateLog) { m_disk = disk; m_databaseHeader = databaseHeader; m_databaseRecords = databaseRecords; m_kernelUpdateLog = kernelUpdateLog; }
public VolumeManagerDatabase(DynamicDisk disk, VolumeManagerDatabaseHeader databaseHeader, List <DatabaseRecord> databaseRecords, KernelUpdateLog kernelUpdateLog) { m_disk = disk; m_databaseHeader = databaseHeader; m_databaseRecords = databaseRecords; m_kernelUpdateLog = kernelUpdateLog; m_nextRecordID = m_databaseHeader.CommitTransactionID + 1; }
public static VolumeManagerDatabase ReadFromDisk(Disk disk, PrivateHeader privateHeader, TOCBlock tocBlock) { VolumeManagerDatabaseHeader databaseHeader = VolumeManagerDatabaseHeader.ReadFromDisk(disk, privateHeader, tocBlock); if (databaseHeader == null) { return(null); } List <DatabaseRecord> databaseRecords = new List <DatabaseRecord>(); // The first VBLK entry is the subsequent entry to the VMDB, which located at (ConfigurationStartLBA + Item1Start) ulong firstSector = privateHeader.PrivateRegionStartLBA + tocBlock.ConfigStart + 1; // we skip the VMDB int sectorCount = (int)Math.Ceiling((long)databaseHeader.NumberOfVBlks * databaseHeader.BlockSize / (decimal)disk.BytesPerSector); byte[] databaseBytes = disk.ReadSectors((long)firstSector, sectorCount); // read all VBLK blocks: // Note: fragments are not necessarily contiguous! Dictionary <uint, List <DatabaseRecordFragment> > fragments = new Dictionary <uint, List <DatabaseRecordFragment> >(); for (uint index = 0; index < databaseHeader.NumberOfVBlks - 4; index++) { byte[] fragmentBytes = new byte[databaseHeader.BlockSize]; #warning long array index not supported Array.Copy(databaseBytes, (int)(index * databaseHeader.BlockSize), fragmentBytes, 0, (int)databaseHeader.BlockSize); DatabaseRecordFragment fragment = DatabaseRecordFragment.GetDatabaseRecordFragment(fragmentBytes); if (fragment != null) // null fragment means VBLK is empty { if (fragments.ContainsKey(fragment.GroupNumber)) { fragments[fragment.GroupNumber].Add(fragment); } else { List <DatabaseRecordFragment> recordFragments = new List <DatabaseRecordFragment>(); recordFragments.Add(fragment); fragments.Add(fragment.GroupNumber, recordFragments); } } } // We have all the fragments and we can now assemble the records: // We assume that fragments with lower FragmentNumber appear in the database before fragments // of the same group with higher FragmentNumber. foreach (List <DatabaseRecordFragment> recorFragments in fragments.Values) { DatabaseRecord databaseRecord = DatabaseRecord.GetDatabaseRecord(recorFragments); databaseRecords.Add(databaseRecord); } // read all KLog blocks KernelUpdateLog kernelUpdateLog = KernelUpdateLog.ReadFromDisk(disk, privateHeader, tocBlock); DynamicDisk dynamicDisk = new DynamicDisk(disk, privateHeader, tocBlock); return(new VolumeManagerDatabase(dynamicDisk, databaseHeader, databaseRecords, kernelUpdateLog)); }
public static PrivateHeader FindDiskPrivateHeader(Guid diskGuid) { DynamicDisk disk = FindDisk(diskGuid); if (disk != null) { return(disk.PrivateHeader); } return(null); }
public static VolumeManagerDatabase ReadFromDisk(Disk disk) { if (DynamicDisk.IsDynamicDisk(disk)) { PrivateHeader privateHeader = PrivateHeader.ReadFromDisk(disk); if (privateHeader != null) { return(ReadFromDisk(disk, privateHeader)); } } return(null); }
/// <summary> /// Support null disks /// </summary> public static long GetExtentStartSector(DynamicDisk disk, ExtentRecord extentRecord) { long publicRegionStartLBA = 0; int bytesPerDiskSector = DynamicColumn.DefaultBytesPerSector; // default for missing disks if (disk != null) { bytesPerDiskSector = disk.BytesPerSector; PrivateHeader privateHeader = disk.PrivateHeader; publicRegionStartLBA = (long)privateHeader.PublicRegionStartLBA; } return(PublicRegionHelper.TranslateFromPublicRegionLBA((long)extentRecord.DiskOffsetLBA, publicRegionStartLBA, bytesPerDiskSector)); }
public static List <DynamicDisk> GetPhysicalDynamicDisks() { List <PhysicalDisk> disks = PhysicalDiskHelper.GetPhysicalDisks(); List <DynamicDisk> result = new List <DynamicDisk>(); foreach (PhysicalDisk disk in disks) { DynamicDisk dynamicDisk = DynamicDisk.ReadFromDisk(disk); if (dynamicDisk != null) { result.Add(dynamicDisk); } } return(result); }
/// <param name="targetOffset">in bytes</param> public static bool IsMoveLocationValid(DynamicDiskExtent sourceExtent, DynamicDisk targetDisk, long targetOffset) { bool isSameDisk = (sourceExtent.Disk == targetDisk.Disk); List <DynamicDiskExtent> extents = GetDiskExtents(targetDisk); // extents are sorted by first sector if (extents == null) { return(false); } PrivateHeader privateHeader = targetDisk.PrivateHeader; if (sourceExtent.BytesPerSector != targetDisk.BytesPerSector) { // We must not move an extent to another disk that has different sector size return(false); } if (targetOffset % privateHeader.BytesPerSector > 0) { return(false); } long targetSector = targetOffset / targetDisk.BytesPerSector; DiskExtent targetExtent = new DiskExtent(targetDisk.Disk, targetSector, sourceExtent.Size); List <DiskExtent> usedExtents = new List <DiskExtent>(); foreach (DynamicDiskExtent extent in extents) { if (!isSameDisk || extent.FirstSector != sourceExtent.FirstSector) { usedExtents.Add(extent); } } long publicRegionStartSector = (long)privateHeader.PublicRegionStartLBA; long publicRegionSize = (long)privateHeader.PublicRegionSizeLBA * targetDisk.BytesPerSector; List <DiskExtent> unallocatedExtents = DiskExtentsHelper.GetUnallocatedExtents(targetDisk.Disk, publicRegionStartSector, publicRegionSize, usedExtents); foreach (DiskExtent extent in unallocatedExtents) { if (extent.FirstSector <= targetExtent.FirstSector && targetExtent.LastSector <= extent.LastSector) { return(true); } } return(false); }
/// <summary> /// Support null disks /// </summary> public static DynamicDiskExtent GetDiskExtent(DynamicDisk dynamicDisk, ExtentRecord extentRecord) { long extentStartSector = GetExtentStartSector(dynamicDisk, extentRecord); long extentSize = (long)extentRecord.SizeLBA * PublicRegionHelper.BytesPerPublicRegionSector; Disk disk = null; Guid diskGuid = Guid.Empty; if (dynamicDisk != null) { disk = dynamicDisk.Disk; diskGuid = dynamicDisk.DiskGuid; } DynamicDiskExtent extent = new DynamicDiskExtent(disk, extentStartSector, extentSize, extentRecord.ExtentId); extent.Name = extentRecord.Name; extent.DiskGuid = diskGuid; return(extent); }
public static bool IsVolumeRetained(SimpleVolume volume, out bool isBootVolume) { isBootVolume = false; DynamicDisk disk = DynamicDisk.ReadFromDisk(volume.Disk); long bootPartitionStartLBA; List <ExtentRecord> retained = GetRetainedExtentsOnDisk(disk, out bootPartitionStartLBA); foreach (ExtentRecord record in retained) { if (record.ExtentId == volume.DiskExtent.ExtentID) { if ((long)(disk.PrivateHeader.PublicRegionStartLBA + record.DiskOffsetLBA) == bootPartitionStartLBA) { isBootVolume = true; } return(true); } } return(false); }
public static void WriteDatabaseRecordFragment(DynamicDisk disk, DatabaseRecordFragment fragment, int blockSize) { if (fragment.SequenceNumber < FirstSequenceNumber) { throw new ArgumentException("VBLK SequenceNumber must start from 4"); } PrivateHeader privateHeader = disk.PrivateHeader; TOCBlock tocBlock = disk.TOCBlock; ulong sectorIndex = privateHeader.PrivateRegionStartLBA + tocBlock.ConfigStart; int fragmentsPerSector = (int)(disk.Disk.BytesPerSector / blockSize); sectorIndex += (ulong)(fragment.SequenceNumber / fragmentsPerSector); byte[] sectorBytes = disk.Disk.ReadSector((long)sectorIndex); byte[] fragmentBytes = fragment.GetBytes(blockSize); // should we use the same database header? int indexInSector = (int)(fragment.SequenceNumber % fragmentsPerSector); Array.Copy(fragmentBytes, 0, sectorBytes, indexInSector * blockSize, blockSize); disk.Disk.WriteSectors((long)sectorIndex, sectorBytes); }
private static List <ExtentRecord> GetRetainedExtentsOnDisk(DynamicDisk disk, out long bootPartitionStartLBA) { VolumeManagerDatabase database = VolumeManagerDatabase.ReadFromDisk(disk); DiskRecord diskRecord = database.FindDiskByDiskGuid(disk.DiskGuid); bootPartitionStartLBA = -1; List <ExtentRecord> result = new List <ExtentRecord>(); foreach (VolumeRecord volume in database.VolumeRecords) { if ((volume.VolumeFlags & VolumeFlags.RetainPartition) > 0) { List <ComponentRecord> components = database.FindComponentsByVolumeID(volume.VolumeId); foreach (ComponentRecord componentRecord in components) { if (componentRecord.ExtentLayout == ExtentLayoutName.Concatenated) { if (componentRecord.NumberOfExtents == 1) { List <ExtentRecord> extents = database.FindExtentsByComponentID(componentRecord.ComponentId); if (extents.Count == 1) { ExtentRecord extent = extents[0]; if (extent.DiskId == diskRecord.DiskId) { result.Add(extent); if ((volume.VolumeFlags & VolumeFlags.BootVolume) > 0) { bootPartitionStartLBA = (long)(disk.PrivateHeader.PublicRegionStartLBA + extent.DiskOffsetLBA); } } } } } } } } return(result); }
public static List <DiskExtent> GetUnallocatedExtents(DynamicDisk disk) { List <DynamicDiskExtent> extents = GetDiskExtents(disk); // extents are sorted by first sector if (extents == null) { return(null); } List <DiskExtent> result = new List <DiskExtent>(); PrivateHeader privateHeader = disk.PrivateHeader; long publicRegionStartSector = (long)privateHeader.PublicRegionStartLBA; long startSector = publicRegionStartSector; long publicRegionSize = (long)privateHeader.PublicRegionSizeLBA * disk.Disk.BytesPerSector; // see if there is room before each extent foreach (DynamicDiskExtent extent in extents) { long extentStartSector = extent.FirstSector; long nextStartSector = extent.FirstSector + extent.Size / disk.BytesPerSector; long freeSpaceInBytes = (extentStartSector - startSector) * disk.BytesPerSector; if (freeSpaceInBytes > 0) { result.Add(new DiskExtent(disk.Disk, startSector, freeSpaceInBytes)); } startSector = nextStartSector; } // see if there is room after the last extent long spaceInBytes = publicRegionSize - (startSector - publicRegionStartSector) * disk.Disk.BytesPerSector; if (spaceInBytes > 0) { result.Add(new DiskExtent(disk.Disk, startSector, spaceInBytes)); } return(result); }
private static List <DynamicColumn> GetDynamicVolumeColumns(DiskGroupDatabase database, ComponentRecord componentRecord, VolumeRecord volumeRecord) { // extentRecords are sorted by offset in column List <ExtentRecord> extentRecords = database.FindExtentsByComponentID(componentRecord.ComponentId); if (componentRecord.NumberOfExtents != extentRecords.Count || extentRecords.Count == 0) { // database record is invalid throw new InvalidDataException("Number of extents in component record does not match actual number of extent records"); } SortedList <uint, List <DynamicDiskExtent> > columns = new SortedList <uint, List <DynamicDiskExtent> >(); foreach (ExtentRecord extentRecord in extentRecords) { DiskRecord diskRecord = database.FindDiskByDiskID(extentRecord.DiskId); DynamicDisk disk = DynamicDiskHelper.FindDisk(database.Disks, diskRecord.DiskGuid); // we add nulls as well DynamicDiskExtent extent = DynamicDiskExtentHelper.GetDiskExtent(disk, extentRecord); if (columns.ContainsKey(extentRecord.ColumnIndex)) { columns[extentRecord.ColumnIndex].Add(extent); } else { List <DynamicDiskExtent> list = new List <DynamicDiskExtent>(); list.Add(extent); columns.Add(extentRecord.ColumnIndex, list); } } List <DynamicColumn> result = new List <DynamicColumn>(); foreach (List <DynamicDiskExtent> extents in columns.Values) { result.Add(new DynamicColumn(extents)); } return(result); }
/// <summary> /// Sorted by first sector /// </summary> /// <returns>null if there was a problem reading extent information from disk</returns> public static List <DynamicDiskExtent> GetDiskExtents(DynamicDisk disk) { List <DynamicDiskExtent> result = new List <DynamicDiskExtent>(); PrivateHeader privateHeader = disk.PrivateHeader; if (privateHeader != null) { VolumeManagerDatabase database = VolumeManagerDatabase.ReadFromDisk(disk); if (database != null) { DiskRecord diskRecord = database.FindDiskByDiskGuid(privateHeader.DiskGuid); List <ExtentRecord> extentRecords = database.FindExtentsByDiskID(diskRecord.DiskId); foreach (ExtentRecord extentRecord in extentRecords) { DynamicDiskExtent extent = DynamicDiskExtentHelper.GetDiskExtent(disk, extentRecord); result.Add(extent); } DynamicDiskExtentsHelper.SortExtentsByFirstSector(result); return(result); } } return(null); }
/// <param name="allocationLength">In bytes</param> /// <param name="alignInSectors">0 or 1 for no alignment</param> /// <returns>Allocated DiskExtent or null if there is not enough free disk space</returns> public static DiskExtent FindExtentAllocation(DynamicDisk disk, long allocationLength, long alignInSectors) { List <DiskExtent> unallocatedExtents = DynamicDiskHelper.GetUnallocatedExtents(disk); if (unallocatedExtents == null) { return(null); } for (int index = 0; index < unallocatedExtents.Count; index++) { DiskExtent extent = unallocatedExtents[index]; if (alignInSectors > 1) { extent = DiskExtentHelper.GetAlignedDiskExtent(extent, alignInSectors); } if (extent.Size >= allocationLength) { return(new DiskExtent(extent.Disk, extent.FirstSector, allocationLength)); } } return(null); }
public static DynamicDisk FindDisk(Guid diskGuid) { List <int> diskIndexList = PhysicalDiskControl.GetPhysicalDiskIndexList(); foreach (int diskIndex in diskIndexList) { PhysicalDisk disk; try { disk = new PhysicalDisk(diskIndex); // will throw an exception if disk is not valid } catch (DriveNotFoundException) { // The disk must have been removed from the system continue; } catch (DeviceNotReadyException) { continue; } catch (SharingViolationException) // skip this disk, it's probably being used { continue; } DynamicDisk dynamicDisk = DynamicDisk.ReadFromDisk(disk); if (dynamicDisk != null) { if (dynamicDisk.DiskGuid == diskGuid) { return(dynamicDisk); } } } return(null); }
private static SimpleVolume GetSimpleVolume(DiskGroupDatabase database, ComponentRecord componentRecord, VolumeRecord volumeRecord) { List <ExtentRecord> extentRecords = database.FindExtentsByComponentID(componentRecord.ComponentId); if (extentRecords.Count == 1) { ExtentRecord extentRecord = extentRecords[0]; DiskRecord diskRecord = database.FindDiskByDiskID(extentRecord.DiskId); DynamicDisk disk = DynamicDiskHelper.FindDisk(database.Disks, diskRecord.DiskGuid); // we add nulls as well DynamicDiskExtent extent = DynamicDiskExtentHelper.GetDiskExtent(disk, extentRecord); SimpleVolume volume = new SimpleVolume(extent, volumeRecord.VolumeGuid, database.DiskGroupGuid); volume.VolumeID = volumeRecord.VolumeId; volume.Name = volumeRecord.Name; volume.DiskGroupName = database.DiskGroupName; return(volume); } else { // component / extent records are invalid throw new InvalidDataException("Number of extents in component record does not match actual number of extent records"); } }
public static void WriteToDisk(DynamicDisk disk, VolumeManagerDatabaseHeader header) { WriteToDisk(disk.Disk, disk.PrivateHeader, disk.TOCBlock, header); }
/// <summary> /// Move extent to a new location on the same disk /// </summary> public static void MoveExtentWithinSameDisk(List<DynamicDisk> disks, DynamicVolume volume, DynamicDiskExtent sourceExtent, DiskExtent relocatedExtent, ref long bytesCopied) { DiskGroupDatabase database = DiskGroupDatabase.ReadFromDisks(disks, volume.DiskGroupGuid); if (database == null) { throw new DatabaseNotFoundException(); } MoveExtentOperationBootRecord resumeRecord = new MoveExtentOperationBootRecord(); // If there will be a power failure during the move, a RAID volume will resync during boot, // To prevent destruction of the data, we temporarily convert the array to striped volume if (volume is Raid5Volume) { VolumeManagerDatabaseHelper.ConvertRaidToStripedVolume(database, volume.VolumeGuid); resumeRecord.RestoreRAID5 = true; } // We want to write our own volume boot sector for recovery purposes, so we must find where to backup the old boot sector. // We don't want to store the backup in the range of the existing or relocated extent, because then we would have to move // the backup around during the move operation, other options include: // 1. Store it between sectors 1-62 (cons: Could be in use, Windows occasionally start a volume from sector 1) // 2. Find an easily compressible sector (e.g. zero-filled) within the existing extent, overwrite it with the backup, and restore it when the operation is done. // 3. use the LDM private region to store the sector. DynamicDisk dynamicDisk = DynamicDisk.ReadFromDisk(relocatedExtent.Disk); // Note: backupSectorIndex will be from the beginning of the private region while backupBufferStartSector will be from the end // so there is no need to allocate them long backupSectorIndex = DynamicDiskHelper.FindUnusedSectorInPrivateRegion(dynamicDisk); resumeRecord.VolumeGuid = volume.VolumeGuid; resumeRecord.NumberOfCommittedSectors = 0; resumeRecord.ExtentID = sourceExtent.ExtentID; resumeRecord.OldStartSector = (ulong)sourceExtent.FirstSector; resumeRecord.NewStartSector = (ulong)relocatedExtent.FirstSector; resumeRecord.BootRecordBackupSector = (ulong)backupSectorIndex; long distanceLBA = Math.Abs((long)resumeRecord.NewStartSector - (long)resumeRecord.OldStartSector); if (distanceLBA < MoveHelper.BufferedModeThresholdLBA) { long backupBufferStartSector = DynamicDiskHelper.FindUnusedRegionInPrivateRegion(dynamicDisk, BackupBufferSizeLBA); if (backupBufferStartSector == -1) { throw new Exception("Private region is full"); } if (backupBufferStartSector <= backupSectorIndex) { throw new Exception("Private region structure is unknown"); } resumeRecord.BackupBufferStartSector = (ulong)backupBufferStartSector; resumeRecord.BackupBufferSizeLBA = BackupBufferSizeLBA; } // Backup the first sector of the first extent // (We replace the filesystem boot record with our own sector for recovery purposes) byte[] filesystemBootRecord = volume.ReadSector(0); relocatedExtent.Disk.WriteSectors(backupSectorIndex, filesystemBootRecord); // we write the resume record instead of the boot record volume.WriteSectors(0, resumeRecord.GetBytes()); if (sourceExtent.FirstSector < relocatedExtent.FirstSector) { // move right MoveExtentRight(disks, volume, resumeRecord, ref bytesCopied); } else { // move left // we write the resume record at the new location as well (to be able to resume if a power failure will occur immediately after updating the database) relocatedExtent.WriteSectors(0, resumeRecord.GetBytes()); DynamicDiskExtent dynamicRelocatedExtent = new DynamicDiskExtent(relocatedExtent, sourceExtent.ExtentID); dynamicRelocatedExtent.Name = sourceExtent.Name; dynamicRelocatedExtent.DiskGuid = sourceExtent.DiskGuid; VolumeManagerDatabaseHelper.UpdateExtentLocation(database, volume, dynamicRelocatedExtent); int extentIndex = DynamicDiskExtentHelper.GetIndexOfExtentID(volume.DynamicExtents, sourceExtent.ExtentID); // get the updated volume (we just moved an extent) volume = DynamicVolumeHelper.GetVolumeByGuid(disks, volume.VolumeGuid); MoveExtentLeft(disks, volume, resumeRecord, ref bytesCopied); } }
public static VolumeManagerDatabase ReadFromDisk(DynamicDisk disk) { return(ReadFromDisk(disk.Disk, disk.PrivateHeader, disk.TOCBlock)); }
public void SetLastEntry(DynamicDisk databaseDisk, ulong committedTransactionID, ulong pendingTransactionID) { SetLastEntry(databaseDisk.Disk, databaseDisk.PrivateHeader, databaseDisk.TOCBlock, committedTransactionID, pendingTransactionID); }
public static DiskExtent FindExtentAllocation(DynamicDisk disk, long allocationLength) { return(FindExtentAllocation(disk, allocationLength, 0)); }
public static KernelUpdateLog ReadFromDisk(DynamicDisk databaseDisk) { return(ReadFromDisk(databaseDisk.Disk, databaseDisk.PrivateHeader, databaseDisk.TOCBlock)); }
public static long GetMaxNewExtentLength(DynamicDisk disk) { return(GetMaxNewExtentLength(disk, 1)); }