Ejemplo n.º 1
0
        /// <returns>Number of bytes</returns>
        public static long GetMaximumSizeToExtendDynamicDiskExtent(DynamicDiskExtent targetExtent)
        {
            DynamicDisk              disk          = DynamicDisk.ReadFromDisk(targetExtent.Disk);
            PrivateHeader            privateHeader = disk.PrivateHeader;
            List <DynamicDiskExtent> extents       = DynamicDiskHelper.GetDiskExtents(disk);

            if (extents == null)
            {
                throw new InvalidDataException("Cannot read extents information from disk");
            }

            long endOfData = (long)((privateHeader.PublicRegionStartLBA + privateHeader.PublicRegionSizeLBA) * (ulong)disk.BytesPerSector);
            long max       = endOfData - (targetExtent.FirstSector * targetExtent.BytesPerSector + targetExtent.Size); // space from the extent end to the end of the disk

            foreach (DynamicDiskExtent extent in extents)
            {
                if (extent.FirstSector > targetExtent.FirstSector)
                {
                    long spaceBetweenExtents = (extent.FirstSector - targetExtent.FirstSector) * disk.BytesPerSector - targetExtent.Size;
                    max = Math.Min(max, spaceBetweenExtents);
                }
            }

            return(max);
        }
        public static void AddDiskToRaid5Volume(DiskGroupDatabase database, Raid5Volume volume, DiskExtent newExtent, ref long bytesCopied)
        {
            // If there will be a power failure during the conversion, our RAID volume will resync during boot,
            // To prevent destruction of the data, we temporarily convert the array to striped volume
            VolumeManagerDatabaseHelper.ConvertRaidToStripedVolume(database, volume.VolumeGuid);
            ulong newExtentID = VolumeManagerDatabaseHelper.AddNewExtentToVolume(database, volume, newExtent);

            // Backup the first sector of the first extent to the last sector of the new extent
            // (We replace the filesystem boot record with our own sector for recovery purposes)
            byte[] filesystemBootRecord = volume.Extents[0].ReadSector(0);
            newExtent.WriteSectors(newExtent.TotalSectors - 1, filesystemBootRecord);

            AddDiskOperationResumeRecord resumeRecord = new AddDiskOperationResumeRecord();

            resumeRecord.VolumeGuid = volume.VolumeGuid;
            PrivateHeader privateHeader = PrivateHeader.ReadFromDisk(newExtent.Disk);

            // privateHeader cannot be null at this point
            resumeRecord.NumberOfCommittedSectors = 0;

            // we use volume.WriteSectors so that the parity information will be update
            // this way, we could recover the first sector of each extent if a disk will fail
            volume.WriteSectors(0, resumeRecord.GetBytes(volume.BytesPerSector));

            ResumeAddDiskToRaid5Volume(database, volume, new DynamicDiskExtent(newExtent, newExtentID), resumeRecord, ref bytesCopied);
        }
Ejemplo n.º 3
0
        public static long FindUnusedRegion(PrivateHeader privateHeader, TOCBlock tocBlock, int sectorCount)
        {
            bool[] bitmap = GetPrivateRegionUsageBitmap(privateHeader, tocBlock);
            // Reserve the first, second, third, third-last and second-last sectors for TOCBlocks
            bitmap[0] = true;
            bitmap[1] = true;
            bitmap[2] = true;
            bitmap[privateHeader.PrivateRegionSizeLBA - 3] = true;
            bitmap[privateHeader.PrivateRegionSizeLBA - 2] = true;

            int startIndex = 0;
            int freeCount  = 0;

            for (int index = 0; index < bitmap.Length; index++)
            {
                if (bitmap[index] == false) // free
                {
                    if (freeCount == 0)
                    {
                        startIndex = index;
                    }
                    freeCount++;
                    if (freeCount == sectorCount)
                    {
                        return((long)privateHeader.PrivateRegionStartLBA + startIndex);
                    }
                }
                else
                {
                    freeCount = 0;
                }
            }

            return(-1);
        }
Ejemplo n.º 4
0
        private void listDisks_SelectedIndexChanged(object sender, EventArgs e)
        {
            DynamicDisk   dynamicDisk        = (DynamicDisk)listDisks.SelectedValue;
            PrivateHeader privateHeader      = dynamicDisk.PrivateHeader;
            long          publicRegionEndLBA = (long)(privateHeader.PublicRegionStartLBA + privateHeader.PublicRegionSizeLBA);

            numericDiskOffset.Minimum = (long)privateHeader.PublicRegionStartLBA * dynamicDisk.BytesPerSector;
            numericDiskOffset.Maximum = publicRegionEndLBA * dynamicDisk.BytesPerSector - m_extent.Size;
            if (dynamicDisk.Disk != m_extent.Disk)
            {
                DiskExtent allocation = DynamicDiskHelper.FindExtentAllocation(dynamicDisk, m_extent.Size);
                numericDiskOffset.Enabled = (allocation != null);
                btnOK.Enabled             = (allocation != null);
                if (allocation != null)
                {
                    numericDiskOffset.Value    = allocation.FirstSector * allocation.BytesPerSector;
                    m_previousSuffixIndex      = 0;
                    listSuffixes.SelectedIndex = 0;
                    CompactNumericOffset();
                }
            }
            else
            {
                numericDiskOffset.Enabled  = true;
                btnOK.Enabled              = true;
                numericDiskOffset.Value    = m_extent.FirstSector * m_extent.Disk.BytesPerSector;
                m_previousSuffixIndex      = 0;
                listSuffixes.SelectedIndex = 0;
                CompactNumericOffset();
            }
        }
Ejemplo n.º 5
0
        public static void ListPhysicalDisks()
        {
            List <PhysicalDisk> disks = PhysicalDiskHelper.GetPhysicalDisks();

            Console.WriteLine("Disk ##  Size     GPT  Dyn  DiskID  Disk Group Name   ");
            Console.WriteLine("-------  -------  ---  ---  ------  ------------------");
            foreach (PhysicalDisk disk in disks)
            {
                int index = disk.PhysicalDiskIndex;

                string                diskNumber    = index.ToString().PadLeft(2);
                MasterBootRecord      mbr           = MasterBootRecord.ReadFromDisk(disk);
                string                isGPTStr      = (mbr != null && mbr.IsGPTBasedDisk) ? " * " : "   ";
                string                isDynStr      = DynamicDisk.IsDynamicDisk(disk) ? " * " : "   ";
                string                diskID        = String.Empty;
                string                diskGroupName = String.Empty;
                VolumeManagerDatabase database      = VolumeManagerDatabase.ReadFromDisk(disk);
                if (database != null)
                {
                    PrivateHeader privateHeader = PrivateHeader.ReadFromDisk(disk);
                    DiskRecord    diskRecord    = database.FindDiskByDiskGuid(privateHeader.DiskGuid);
                    diskID        = diskRecord.DiskId.ToString();
                    diskGroupName = database.DiskGroupName;
                }

                diskID = diskID.PadLeft(6);
                Console.WriteLine("Disk {0}  {1}  {2}  {3}  {4}  {5}", diskNumber, GetStandardSizeString(disk.Size), isGPTStr, isDynStr, diskID, diskGroupName);
            }
        }
Ejemplo n.º 6
0
        /// <param name="targetOffset">in bytes</param>
        public static bool IsMoveLocationValid(DynamicDisk disk, DynamicDiskExtent sourceExtent, long targetOffset)
        {
            List <DynamicDiskExtent> extents = GetDiskExtents(disk);

            // extents are sorted by first sector
            if (extents == null)
            {
                return(false);
            }

            PrivateHeader privateHeader = disk.PrivateHeader;

            if (targetOffset % privateHeader.BytesPerSector > 0)
            {
                return(false);
            }

            int index = GetIndexOfExtentID(extents, sourceExtent.ExtentID);

            extents.RemoveAt(index);

            long targetStartSector = targetOffset / disk.BytesPerSector;

            long publicRegionStartSector = (long)privateHeader.PublicRegionStartLBA;
            long startSector             = publicRegionStartSector;
            long publicRegionSizeLBA     = (long)privateHeader.PublicRegionSizeLBA;

            if (targetStartSector < publicRegionStartSector)
            {
                return(false);
            }

            if (targetStartSector + sourceExtent.TotalSectors > publicRegionStartSector + publicRegionSizeLBA)
            {
                return(false);
            }

            foreach (DynamicDiskExtent extent in extents)
            {
                long extentStartSector = extent.FirstSector;
                long extentEndSector   = extent.FirstSector + extent.Size / disk.BytesPerSector - 1;
                if (extentStartSector >= targetStartSector &&
                    extentStartSector <= targetStartSector + sourceExtent.TotalSectors)
                {
                    // extent start within the requested region
                    return(false);
                }

                if (extentEndSector >= targetStartSector &&
                    extentEndSector <= targetStartSector + sourceExtent.TotalSectors)
                {
                    // extent end within the requested region
                    return(false);
                }
            }

            return(true);
        }
Ejemplo n.º 7
0
 // The secondary TOC is usually alternated between the third-last and the second-last sectors of the private region.
 public static long FindUnusedLBAForSecondaryToc(PrivateHeader privateHeader, TOCBlock tocBlock)
 {
     bool[] bitmap = GetPrivateRegionUsageBitmap(privateHeader, tocBlock);
     for (int index = bitmap.Length - 1; index >= 0; index--)
     {
         if (bitmap[index] == false)
         {
             return((long)privateHeader.PrivateRegionStartLBA + index);
         }
     }
     return(-1);
 }
Ejemplo n.º 8
0
        /// <summary>
        /// Support null disks
        /// </summary>
        public static ulong GetExtentStartSector(DynamicDisk disk, ExtentRecord extentRecord)
        {
            ulong dataStartLBA = 0;

            if (disk != null)
            {
                PrivateHeader privateHeader = disk.PrivateHeader;
                dataStartLBA = privateHeader.PublicRegionStartLBA;
            }
            ulong extentStartSector = dataStartLBA + extentRecord.DiskOffsetLBA;

            return(extentStartSector);
        }
Ejemplo n.º 9
0
        private static bool[] GetPrivateRegionUsageBitmap(PrivateHeader privateHeader, TOCBlock tocBlock)
        {
            // usage bitmap:
            bool[] bitmap = new bool[privateHeader.PrivateRegionSizeLBA];
            bitmap[privateHeader.PrimaryPrivateHeaderLBA]   = true;
            bitmap[privateHeader.SecondaryPrivateHeaderLBA] = true;
            bitmap[privateHeader.PrimaryTocLBA]             = true;
            bitmap[privateHeader.SecondaryTocLBA]           = true;

            foreach (TOCRegion region in tocBlock.Regions)
            {
                for (int index = 0; index < (int)region.SizeLBA; index++)
                {
                    bitmap[(int)region.StartLBA + index] = true;
                }
            }
            return(bitmap);
        }
Ejemplo n.º 10
0
        private static List <DiskExtent> GetUnallocatedSpace(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);
        }
Ejemplo n.º 11
0
        /// <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 = GetDiskExtent(disk, extentRecord);
                        result.Add(extent);
                    }
                    SortExtentsByFirstSector(result);
                    return(result);
                }
            }
            return(null);
        }
Ejemplo n.º 12
0
 public static long TranslateToPublicRegionSizeLBA(long sectorCount, PrivateHeader privateHeader)
 {
     return(TranslateToPublicRegionSizeLBA(sectorCount, (int)privateHeader.BytesPerSector));
 }
Ejemplo n.º 13
0
 public static long TranslateToPublicRegionLBA(long sectorIndex, PrivateHeader privateHeader)
 {
     return(TranslateToPublicRegionLBA(sectorIndex, (long)privateHeader.PublicRegionStartLBA, (int)privateHeader.BytesPerSector));
 }
Ejemplo n.º 14
0
 public static long FindUnusedSector(PrivateHeader privateHeader, TOCBlock tocBlock)
 {
     return(FindUnusedRegion(privateHeader, tocBlock, 1));
 }