private static void MoveExtentLeft(DiskGroupDatabase database, DynamicVolume volume, MoveExtentOperationResumeRecord resumeRecord, ref long bytesCopied) { DynamicDiskExtent relocatedExtent = DynamicDiskExtentHelper.GetByExtentID(volume.DynamicExtents, resumeRecord.ExtentID); if (resumeRecord.OldStartSector == (ulong)relocatedExtent.FirstSector) { // the database update was not completed (this must be a resume operation) relocatedExtent = new DynamicDiskExtent(relocatedExtent.Disk, (long)resumeRecord.NewStartSector, relocatedExtent.Size, resumeRecord.ExtentID); VolumeManagerDatabaseHelper.UpdateExtentLocation(database, volume, relocatedExtent); } DiskExtent sourceExtent = new DiskExtent(relocatedExtent.Disk, (long)resumeRecord.OldStartSector, relocatedExtent.Size); MoveHelper.MoveExtentDataLeft(volume, sourceExtent, relocatedExtent, resumeRecord, ref bytesCopied); // if this is a resume, then volume is StripedVolume, otherwise it is a Raid5Volume if (resumeRecord.RestoreRAID5) { VolumeManagerDatabaseHelper.ConvertStripedVolumeToRaid(database, volume.VolumeGuid); // get the updated volume (we just reconverted to RAID-5) volume = DynamicVolumeHelper.GetVolumeByGuid(database.Disks, volume.VolumeGuid); } // restore the filesystem boot sector byte[] filesystemBootRecord = relocatedExtent.Disk.ReadSector((long)resumeRecord.BootRecordBackupSector); volume.WriteSectors(0, filesystemBootRecord); ClearBackupData(relocatedExtent.Disk, resumeRecord); }
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(DiskGroupDatabase database, DynamicVolume volume, DynamicDiskExtent sourceExtent, DiskExtent relocatedExtent, ref long bytesCopied) { // 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); }
private static void MoveExtentRight(DiskGroupDatabase database, DynamicVolume volume, MoveExtentOperationResumeRecord resumeRecord, ref long bytesCopied) { DynamicDiskExtent sourceExtent = GetVolumeExtent(volume, resumeRecord.ExtentID); DiskExtent relocatedExtent = new DiskExtent(sourceExtent.Disk, (long)resumeRecord.NewStartSector, sourceExtent.Size); MoveHelper.MoveExtentDataRight(volume, sourceExtent, relocatedExtent, resumeRecord, ref bytesCopied); // even if the database update won't complete, the resume record was copied // update the database DynamicDiskExtent dynamicRelocatedExtent = new DynamicDiskExtent(relocatedExtent, sourceExtent.ExtentID); dynamicRelocatedExtent.Name = sourceExtent.Name; dynamicRelocatedExtent.DiskGuid = sourceExtent.DiskGuid; VolumeManagerDatabaseHelper.UpdateExtentLocation(database, volume, dynamicRelocatedExtent); // if this is a resume, then volume is StripedVolume, otherwise it is a Raid5Volume if (resumeRecord.RestoreRAID5) { VolumeManagerDatabaseHelper.ConvertStripedVolumeToRaid(database, volume.VolumeGuid); } // get the updated volume (we moved an extent and possibly reconverted to RAID-5) volume = DynamicVolumeHelper.GetVolumeByGuid(database.Disks, volume.VolumeGuid); // restore the filesystem boot sector byte[] filesystemBootRecord = relocatedExtent.Disk.ReadSector((long)resumeRecord.BootRecordBackupSector); volume.WriteSectors(0, filesystemBootRecord); ClearBackupData(relocatedExtent.Disk, resumeRecord); }
private void resumeOperationMenuItem_Click(object sender, EventArgs e) { DynamicVolume volume = (DynamicVolume)((KeyValuePair <Volume, DiskExtent>)extentContextMenu.Tag).Key; DynamicDiskExtent extent = (DynamicDiskExtent)((KeyValuePair <Volume, DiskExtent>)extentContextMenu.Tag).Value; List <DynamicDisk> dynamicDisks = GetDynamicDisks(); List <DynamicDisk> diskGroup = DynamicDiskHelper.FindDiskGroup(dynamicDisks, volume.DiskGroupGuid); ResumeForm resumeForm = new ResumeForm(diskGroup, volume, extent); DialogResult result = resumeForm.ShowDialog(); if (result == DialogResult.OK) { UpdateView(); if (Environment.OSVersion.Version.Major >= 6) { MessageBox.Show("Click OK to Continue", "Operation completed successfully"); } else { string message = OperatingSystemHelper.GetUpdateMessage(); MessageBox.Show(message, "Operation completed successfully"); } } }
public static long GetMaximumSizeToExtendDynamicVolume(DynamicVolume volume) { if (volume is SimpleVolume) { SimpleVolume simpleVolume = (SimpleVolume)volume; return(GetMaximumSizeToExtendDynamicDiskExtent(simpleVolume.DiskExtent)); } else if (volume is StripedVolume) { StripedVolume stripedVolume = (StripedVolume)volume; long max = Int64.MaxValue; foreach (DynamicDiskExtent extent in stripedVolume.Extents) { long extentMax = GetMaximumSizeToExtendDynamicDiskExtent(extent); max = Math.Min(max, extentMax); } return(max); } else if (volume is Raid5Volume) { Raid5Volume raid5Volume = (Raid5Volume)volume; long max = Int64.MaxValue; foreach (DynamicDiskExtent extent in raid5Volume.Extents) { long extentMax = GetMaximumSizeToExtendDynamicDiskExtent(extent); max = Math.Min(max, extentMax); } return(max); } else { return(0); } }
public static string GetExtentsInformation(DynamicVolume volume) { List <DynamicDiskExtent> extents = volume.DynamicExtents; StringBuilder builder = new StringBuilder(); for (int extentIndex = 0; extentIndex < extents.Count; extentIndex++) { DynamicDiskExtent extent = extents[extentIndex]; string extentOffsetString; string diskIDString = String.Empty; if (extent.Disk != null) { long extentOffset = extent.FirstSector * extent.Disk.BytesPerSector; extentOffsetString = FormattingHelper.GetStandardSizeString(extentOffset); VolumeManagerDatabase database = VolumeManagerDatabase.ReadFromDisk(extent.Disk); if (database != null) { ExtentRecord extentRecord = database.FindExtentByExtentID(extent.ExtentID); if (extentRecord != null) { diskIDString = extentRecord.DiskId.ToString(); } } } else { extentOffsetString = "N/A"; } string extentSizeString = FormattingHelper.GetStandardSizeString(extent.Size); builder.AppendFormat("Extent {0}, ID: {1}, Name: {2}, Size: {3}, Disk ID: {4}, Offset: {5}, Start Sector: {6}\n", extentIndex, extent.ExtentID, extent.Name, extentSizeString, diskIDString, extentOffsetString, extent.FirstSector); } return(builder.ToString()); }
public static DynamicVolume GetVolume(List <DynamicDisk> disks, VolumeManagerDatabase database, VolumeRecord volumeRecord) { List <ComponentRecord> componentRecords = database.FindComponentsByVolumeID(volumeRecord.VolumeId); if (volumeRecord.NumberOfComponents != (ulong)componentRecords.Count || componentRecords.Count == 0) { // database record is invalid throw new InvalidDataException("Number of components in volume record does not match actual number of component records"); } if (componentRecords.Count == 1) { ComponentRecord componentRecord = componentRecords[0]; return(GetVolume(disks, database, volumeRecord, componentRecord)); } else // Mirrored volume { // Mirrored Simple Volume is the only kind of mirror suppored by Windows (only 2-way mirror is supported) // Veritas also supports Mirrored Stripe / Mirrored RAID-5 / Mirrored Spanned Volume (up to 32-way mirror is supported) List <DynamicVolume> volumes = new List <DynamicVolume>(); foreach (ComponentRecord componentRecord in componentRecords) { DynamicVolume volume = GetVolume(disks, database, volumeRecord, componentRecord); volumes.Add(volume); } MirroredVolume mirroredVolume = new MirroredVolume(volumes, volumeRecord.VolumeGuid, database.DiskGroupGuid); mirroredVolume.VolumeID = volumeRecord.VolumeId; mirroredVolume.Name = volumeRecord.Name; return(mirroredVolume); } }
public static string GetVolumeInformation(Volume volume) { StringBuilder builder = new StringBuilder(); builder.AppendFormat("Volume size: {0} bytes\n", volume.Size.ToString("###,###,###,###,##0")); builder.AppendFormat("Volume type: {0}\n", VolumeHelper.GetVolumeTypeString(volume)); if (volume is GPTPartition) { builder.AppendFormat("Partition name: {0}\n", ((GPTPartition)volume).PartitionName); } else if (volume is DynamicVolume) { builder.AppendFormat("Volume name: {0}\n", ((DynamicVolume)volume).Name); builder.AppendFormat("Volume status: {0}\n", VolumeHelper.GetVolumeStatusString(volume)); } Guid?windowsVolumeGuid = WindowsVolumeHelper.GetWindowsVolumeGuid(volume); if (windowsVolumeGuid.HasValue) { List <string> mountPoints = WindowsVolumeManager.GetMountPoints(windowsVolumeGuid.Value); foreach (string volumePath in mountPoints) { builder.AppendFormat("Volume path: {0}\n", volumePath); } bool isMounted = WindowsVolumeManager.IsMounted(windowsVolumeGuid.Value); builder.AppendFormat("Mounted: {0}\n", isMounted); } builder.AppendLine(); if (volume is MirroredVolume) { builder.AppendLine("Extents:"); List <DynamicVolume> components = ((MirroredVolume)volume).Components; for (int componentIndex = 0; componentIndex < components.Count; componentIndex++) { if (componentIndex != 0) { builder.AppendLine(); } DynamicVolume component = components[componentIndex]; builder.AppendFormat("Component {0}:\n", componentIndex); builder.Append(GetExtentsInformation(component)); } } else if (volume is DynamicVolume) { builder.AppendLine("Extents:"); builder.Append(GetExtentsInformation((DynamicVolume)volume)); } else if (volume is Partition) { Partition partition = (Partition)volume; long partitionOffset = partition.FirstSector * partition.BytesPerSector; string partitionOffsetString = FormattingHelper.GetStandardSizeString(partitionOffset); builder.AppendFormat("Partiton Offset: {0}, Start Sector: {1}\n", partitionOffsetString, partition.FirstSector); } return(builder.ToString()); }
public ResumeForm(List <DynamicDisk> diskGroup, DynamicVolume volume, DynamicDiskExtent extent) { InitializeComponent(); m_diskGroup = diskGroup; m_volume = volume; m_extent = extent; }
public static List <DynamicVolume> GetDynamicDiskVolumes(DynamicDisk disk) { VolumeManagerDatabase database = VolumeManagerDatabase.ReadFromDisk(disk); List <DynamicDisk> disks = new List <DynamicDisk>(); disks.Add(disk); List <DynamicVolume> result = new List <DynamicVolume>(); if (database != null) { foreach (VolumeRecord volumeRecord in database.VolumeRecords) { DynamicVolume volume = GetVolume(disks, database, volumeRecord); if (volume != null) { foreach (DynamicDiskExtent extent in volume.Extents) { if (extent.DiskGuid == disk.DiskGuid) { result.Add(volume); break; } } } } } return(result); }
private void addDiskToVolumeMenuItem_Click(object sender, EventArgs e) { DynamicVolume volume = (DynamicVolume)((KeyValuePair <Volume, DiskExtent>)extentContextMenu.Tag).Key; DynamicDiskExtent extent = (DynamicDiskExtent)((KeyValuePair <Volume, DiskExtent>)extentContextMenu.Tag).Value; List <DynamicDisk> dynamicDisks = GetDynamicDisks(); List <DynamicDisk> diskGroup = DynamicDiskHelper.FindDiskGroup(dynamicDisks, volume.DiskGroupGuid); AddDiskForm addDisk = new AddDiskForm(diskGroup, volume); DialogResult result = addDisk.ShowDialog(); if (result == DialogResult.OK) { if (Environment.OSVersion.Version.Major >= 6) { // Windows 7 / 2008 will likely make changes to the disk group, it will be marked as 'dirty' if we don't wait Thread.Sleep(Windows6WaitTimeBeforeRefresh); } UpdateView(); if (Environment.OSVersion.Version.Major >= 6) { //MessageBox.Show("Please go to Disk Management and reactivate the disk group", "Operation completed successfully"); MessageBox.Show("The volume has been extended successfully.\nyou can now proceed to extend the underlying file system.", "Operation completed successfully"); } else { string message = "The volume has been extended successfully.\nyou can now proceed to extend the underlying file system."; message += "\n\n" + OperatingSystemHelper.GetUpdateMessage(); MessageBox.Show(message, "Operation completed successfully"); } } }
private void moveExtentMenuItem_Click(object sender, EventArgs e) { DynamicVolume volume = (DynamicVolume)((KeyValuePair <Volume, DiskExtent>)extentContextMenu.Tag).Key; DynamicDiskExtent extent = (DynamicDiskExtent)((KeyValuePair <Volume, DiskExtent>)extentContextMenu.Tag).Value; List <DynamicDisk> dynamicDisks = GetDynamicDisks(); List <DynamicDisk> diskGroup = DynamicDiskHelper.FindDiskGroup(dynamicDisks, volume.DiskGroupGuid); bool isBootVolume; if (RetainHelper.IsVolumeRetained(volume, out isBootVolume)) { StringBuilder builder = new StringBuilder(); builder.AppendLine("You're trying to move a retained volume (volume that has a partition"); builder.AppendLine("associated with it)."); builder.AppendLine("If an operating system is present on this volume, a reconfiguration"); builder.AppendLine("might be necessary before you could boot it successfully."); builder.AppendLine("This operation is currently not supported."); MessageBox.Show(builder.ToString(), "Warning"); return; } if (DynamicDiskPartitionerResumeRecord.HasValidSignature(volume.ReadSector(0))) { StringBuilder builder = new StringBuilder(); builder.AppendLine("There is already an operation in progress"); builder.AppendLine("Use the RESUME command to resume the operation"); MessageBox.Show(builder.ToString(), "Error"); return; } MoveExtentForm moveExtent = new MoveExtentForm(diskGroup, volume, extent); DialogResult result = moveExtent.ShowDialog(); if (result == DialogResult.OK) { if (Environment.OSVersion.Version.Major >= 6) { // Windows 7 / 2008 will likely make changes to the disk group, it will be marked as 'dirty' if we don't wait Thread.Sleep(Windows6WaitTimeBeforeRefresh); } UpdateView(); if (Environment.OSVersion.Version.Major >= 6) { //MessageBox.Show("Please go to Disk Management and reactivate the disk group", "Operation completed successfully"); MessageBox.Show("Click OK to Continue", "Operation completed successfully"); } else { string message = OperatingSystemHelper.GetUpdateMessage(); MessageBox.Show(message, "Operation completed successfully"); } } }
public static bool ContainsVolumeGuid(List <Volume> volumes, Guid volumeGuid) { foreach (Volume volume in volumes) { if (volume is DynamicVolume) { DynamicVolume dynamicVolume = (DynamicVolume)volume; if (dynamicVolume.VolumeGuid == volumeGuid) { return(true); } } } return(false); }
public static List <DynamicVolume> GetDynamicVolumes(List <DynamicDisk> disks) { List <DynamicVolume> result = new List <DynamicVolume>(); List <DiskGroupDatabase> diskGroupDatabases = DiskGroupDatabase.ReadFromDisks(disks); foreach (DiskGroupDatabase database in diskGroupDatabases) { foreach (VolumeRecord volumeRecord in database.VolumeRecords) { DynamicVolume volume = GetVolume(disks, database, volumeRecord); result.Add(volume); } } return(result); }
public static void ExtendDynamicVolume(DynamicVolume volume, long numberOfAdditionalExtentSectors, DiskGroupDatabase database) { if (volume is SimpleVolume) { SimpleVolume simpleVolume = (SimpleVolume)volume; VolumeManagerDatabaseHelper.ExtendSimpleVolume(database, simpleVolume, numberOfAdditionalExtentSectors); } else if (volume is StripedVolume) { StripedVolume stripedVolume = (StripedVolume)volume; VolumeManagerDatabaseHelper.ExtendStripedVolume(database, stripedVolume, numberOfAdditionalExtentSectors); } else if (volume is Raid5Volume) { Raid5Volume raid5Volume = (Raid5Volume)volume; VolumeManagerDatabaseHelper.ExtendRAID5Volume(database, raid5Volume, numberOfAdditionalExtentSectors); } }
public static void ResumeMoveExtent(DiskGroupDatabase database, DynamicVolume volume, MoveExtentOperationResumeRecord resumeRecord, ref long bytesCopied) { if (resumeRecord.OldStartSector == resumeRecord.NewStartSector) { throw new InvalidDataException("Invalid move record"); } if (resumeRecord.RestoreFromBuffer) { // we need to use the backup buffer to restore the data that may have been overwritten DynamicDiskExtent sourceExtent = GetVolumeExtent(volume, resumeRecord.ExtentID); byte[] backupBuffer = sourceExtent.Disk.ReadSectors((long)resumeRecord.BackupBufferStartSector, BackupBufferSizeLBA); if (resumeRecord.OldStartSector < resumeRecord.NewStartSector) { // move right long readCount = (long)resumeRecord.NumberOfCommittedSectors; int sectorsToRead = BackupBufferSizeLBA; long sectorIndex = sourceExtent.TotalSectors - readCount - sectorsToRead; sourceExtent.WriteSectors(sectorIndex, backupBuffer); System.Diagnostics.Debug.WriteLine("Restored to " + sectorIndex); } else { // move left long sectorIndex = (long)resumeRecord.NumberOfCommittedSectors; sourceExtent.WriteSectors(sectorIndex, backupBuffer); System.Diagnostics.Debug.WriteLine("Restored to " + sectorIndex); } } if (resumeRecord.OldStartSector < resumeRecord.NewStartSector) { MoveExtentRight(database, volume, resumeRecord, ref bytesCopied); } else { MoveExtentLeft(database, volume, resumeRecord, ref bytesCopied); } }
private static DynamicDiskExtent GetVolumeExtent(DynamicVolume volume, ulong extentID) { if (volume is MirroredVolume) { foreach (DynamicVolume component in ((MirroredVolume)volume).Components) { int extentIndex = DynamicDiskExtentHelper.GetIndexOfExtentID(component.DynamicExtents, extentID); if (extentIndex >= 0) { return(volume.DynamicExtents[extentIndex]); } } } else { int extentIndex = DynamicDiskExtentHelper.GetIndexOfExtentID(volume.DynamicExtents, extentID); if (extentIndex >= 0) { return(volume.DynamicExtents[extentIndex]); } } throw new ArgumentException("Volume does not have an extent with given ExtentID"); }
public static DiskGroupLockResult ExtendDynamicVolume(List <DynamicDisk> diskGroup, DynamicVolume volume, long numberOfAdditionalExtentSectors) { if (volume is StripedVolume) { numberOfAdditionalExtentSectors -= numberOfAdditionalExtentSectors % ((StripedVolume)volume).SectorsPerStripe; } if (volume is Raid5Volume) { numberOfAdditionalExtentSectors -= numberOfAdditionalExtentSectors % ((Raid5Volume)volume).SectorsPerStripe; } DiskGroupLockResult result = DiskGroupHelper.LockDiskGroup(diskGroup); if (result != DiskGroupLockResult.Success) { return(result); } DiskGroupDatabase database = DiskGroupDatabase.ReadFromDisks(diskGroup, volume.DiskGroupGuid); ExtendHelper.ExtendDynamicVolume((DynamicVolume)volume, numberOfAdditionalExtentSectors, database); DiskGroupHelper.UnlockDiskGroup(diskGroup); return(DiskGroupLockResult.Success); }
/// <summary> /// Move extent to a new location on the same disk /// </summary> public static void MoveExtentWithinSameDisk(DiskGroupDatabase database, DynamicVolume volume, DynamicDiskExtent sourceExtent, DiskExtent relocatedExtent, ref long bytesCopied) { MoveExtentOperationResumeRecord resumeRecord = new MoveExtentOperationResumeRecord(); // 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 = PrivateRegionHelper.FindUnusedSector(dynamicDisk.PrivateHeader, dynamicDisk.TOCBlock); 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 = (long)Math.Abs((double)resumeRecord.NewStartSector - resumeRecord.OldStartSector); if (distanceLBA < MoveHelper.BufferedModeThresholdLBA) { long backupBufferStartSector = PrivateRegionHelper.FindUnusedRegion(dynamicDisk.PrivateHeader, dynamicDisk.TOCBlock, 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(volume.BytesPerSector)); if (sourceExtent.FirstSector < relocatedExtent.FirstSector) { // move right MoveExtentRight(database, 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(relocatedExtent.BytesPerSector)); 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(database.Disks, volume.VolumeGuid); MoveExtentLeft(database, volume, resumeRecord, ref bytesCopied); } }
public AddDiskForm(List <DynamicDisk> diskGroup, DynamicVolume volume) { InitializeComponent(); m_diskGroup = diskGroup; m_volume = volume; }
private static ExtendFileSystemResult ExtendUnmountedFileSystem(List <DynamicDisk> diskGroup, DynamicVolume volume, long numberOfAdditionalSectors) { if (!volume.IsOperational) { return(ExtendFileSystemResult.NonOperationalVolume); } IExtendableFileSystem fileSystem = FileSystemHelper.ReadFileSystem(volume) as IExtendableFileSystem; // Windows Vista / 7 enforce various limitations on direct write operations to volumes and disks. // Basic disks are not needed to be taken offline for direct write operations within volume region. Only dynamic disks have to. if (Environment.OSVersion.Version.Major >= 6) { // Lock disks and volumes DiskGroupLockResult lockResult = DiskGroupHelper.LockDiskGroup(diskGroup); if (lockResult == DiskGroupLockResult.CannotLockDisk) { return(ExtendFileSystemResult.CannotLockDisk); } else if (lockResult == DiskGroupLockResult.CannotLockVolume) { return(ExtendFileSystemResult.CannotLockVolume); } else if (lockResult == DiskGroupLockResult.CannotTakeDiskOffline) { return(ExtendFileSystemResult.CannotTakeDiskOffline); } else if (lockResult == DiskGroupLockResult.OneOrMoreDisksAreOfflineOrReadonly) { return(ExtendFileSystemResult.OneOrMoreDisksAreOfflineOrReadonly); } } fileSystem.Extend(numberOfAdditionalSectors); if (Environment.OSVersion.Version.Major >= 6) { DiskGroupHelper.UnlockDiskGroup(diskGroup); } return(ExtendFileSystemResult.Success); }