Exemplo n.º 1
0
        public static void ExtendRAID5Volume(DiskGroupDatabase database, Raid5Volume volume, long numberOfAdditionalExtentSectors)
        {
            if (numberOfAdditionalExtentSectors % volume.SectorsPerStripe > 0)
            {
                throw new ArgumentException("Number of additional sectors must be multiple of stripes per sector");
            }

            List <DatabaseRecord> records = new List <DatabaseRecord>();

            VolumeRecord volumeRecord = database.FindVolumeByVolumeGuid(volume.VolumeGuid);

            volumeRecord          = (VolumeRecord)volumeRecord.Clone();
            volumeRecord.SizeLBA += (ulong)PublicRegionHelper.TranslateToPublicRegionSizeLBA(numberOfAdditionalExtentSectors * (volume.NumberOfColumns - 1), volume.BytesPerSector);
            records.Add(volumeRecord);

            foreach (DynamicColumn column in volume.Columns)
            {
                DynamicDiskExtent lastExtent   = column.Extents[column.Extents.Count - 1];
                ExtentRecord      extentRecord = database.FindExtentByExtentID(lastExtent.ExtentID);
                extentRecord          = (ExtentRecord)extentRecord.Clone();
                extentRecord.SizeLBA += (ulong)PublicRegionHelper.TranslateToPublicRegionSizeLBA(numberOfAdditionalExtentSectors, volume.BytesPerSector);
                records.Add(extentRecord);

                DiskRecord diskRecord = database.FindDiskByDiskID(extentRecord.DiskId); // we should update the disk, see Database.cs
                diskRecord = (DiskRecord)diskRecord.Clone();
                records.Add(diskRecord);
            }

            database.UpdateDatabase(records);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Update the database to point to the new extent location (same or different disk)
        /// </summary>
        public static void UpdateExtentLocation(DiskGroupDatabase database, DynamicVolume volume, DynamicDiskExtent relocatedExtent)
        {
            PrivateHeader privateHeader = PrivateHeader.ReadFromDisk(relocatedExtent.Disk);

            DiskRecord   targetDiskRecord = database.FindDiskByDiskGuid(privateHeader.DiskGuid);
            VolumeRecord volumeRecord     = database.FindVolumeByVolumeGuid(volume.VolumeGuid);

            List <DatabaseRecord> records               = new List <DatabaseRecord>();
            ExtentRecord          sourceExtentRecord    = database.FindExtentByExtentID(relocatedExtent.ExtentID);
            ExtentRecord          relocatedExtentRecord = (ExtentRecord)sourceExtentRecord.Clone();

            relocatedExtentRecord.DiskId        = targetDiskRecord.DiskId;
            relocatedExtentRecord.DiskOffsetLBA = (ulong)PublicRegionHelper.TranslateToPublicRegionLBA(relocatedExtent.FirstSector, privateHeader);
            records.Add(relocatedExtentRecord);

            // we should update the disk records
            foreach (DynamicDiskExtent extent in volume.Extents)
            {
                DiskRecord diskRecord = database.FindDiskByDiskID(relocatedExtentRecord.DiskId);
                // there could be multiple extents on the same disk, make sure we only add each disk once
                if (!records.Contains(diskRecord))
                {
                    diskRecord = (DiskRecord)diskRecord.Clone();
                    records.Add(diskRecord);
                }
            }

            // when moving to a new disk, we should update the new disk record as well
            if (!records.Contains(targetDiskRecord))
            {
                records.Add(targetDiskRecord.Clone());
            }

            database.UpdateDatabase(records);
        }
Exemplo n.º 3
0
        public static void ExtendStripedVolume(DiskGroupDatabase database, StripedVolume volume, long additionalNumberOfExtentSectors)
        {
            if (additionalNumberOfExtentSectors % volume.SectorsPerStripe > 0)
            {
                throw new ArgumentException("Number of additional sectors must be multiple of stripes per sector");
            }

            List <DatabaseRecord> records = new List <DatabaseRecord>();

            VolumeRecord volumeRecord = database.FindVolumeByVolumeGuid(volume.VolumeGuid);

            volumeRecord          = (VolumeRecord)volumeRecord.Clone();
            volumeRecord.SizeLBA += (ulong)(additionalNumberOfExtentSectors * volume.NumberOfColumns);
            records.Add(volumeRecord);

            // we only want to extend the last extent in each column
            foreach (DynamicColumn column in volume.Columns)
            {
                DynamicDiskExtent lastExtent   = column.Extents[column.Extents.Count - 1];
                ExtentRecord      extentRecord = database.FindExtentByExtentID(lastExtent.ExtentID);
                extentRecord          = (ExtentRecord)extentRecord.Clone();
                extentRecord.SizeLBA += (ulong)additionalNumberOfExtentSectors;
                records.Add(extentRecord);

                DiskRecord diskRecord = database.FindDiskByDiskID(extentRecord.DiskId); // we should update the disk, see Database.cs
                diskRecord = (DiskRecord)diskRecord.Clone();
                records.Add(diskRecord);
            }

            database.UpdateDatabase(records);
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 5
0
        public static void ExtendSimpleVolume(DiskGroupDatabase database, SimpleVolume volume, long numberOfAdditionalSectors)
        {
            VolumeRecord volumeRecord = database.FindVolumeByVolumeGuid(volume.VolumeGuid);

            volumeRecord          = (VolumeRecord)volumeRecord.Clone();
            volumeRecord.SizeLBA += (ulong)PublicRegionHelper.TranslateToPublicRegionSizeLBA(numberOfAdditionalSectors, volume.BytesPerSector);
            ExtentRecord extentRecord = database.FindExtentByExtentID(volume.DiskExtent.ExtentID);

            extentRecord          = (ExtentRecord)extentRecord.Clone();
            extentRecord.SizeLBA += (ulong)PublicRegionHelper.TranslateToPublicRegionSizeLBA(numberOfAdditionalSectors, volume.BytesPerSector);
            DiskRecord diskRecord = database.FindDiskByDiskID(extentRecord.DiskId); // we should update the disk, see Database.cs

            diskRecord = (DiskRecord)diskRecord.Clone();

            List <DatabaseRecord> records = new List <DatabaseRecord>();

            records.Add(volumeRecord);
            records.Add(extentRecord);
            records.Add(diskRecord);

            database.UpdateDatabase(records);
        }
Exemplo n.º 6
0
        public static void ExtendSimpleVolume(DiskGroupDatabase database, SimpleVolume volume, long additionalNumberOfSectors)
        {
            VolumeRecord volumeRecord = database.FindVolumeByVolumeGuid(volume.VolumeGuid);

            volumeRecord          = (VolumeRecord)volumeRecord.Clone();
            volumeRecord.SizeLBA += (ulong)additionalNumberOfSectors;
            ExtentRecord extentRecord = database.FindExtentByExtentID(volume.DiskExtent.ExtentID);

            extentRecord          = (ExtentRecord)extentRecord.Clone();
            extentRecord.SizeLBA += (ulong)additionalNumberOfSectors;
            DiskRecord diskRecord = database.FindDiskByDiskID(extentRecord.DiskId); // we should update the disk, see Database.cs

            diskRecord = (DiskRecord)diskRecord.Clone();

            List <DatabaseRecord> records = new List <DatabaseRecord>();

            records.Add(volumeRecord);
            records.Add(extentRecord);
            records.Add(diskRecord);

            database.UpdateDatabase(records);
        }
Exemplo n.º 7
0
        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");
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Update the database (add the new extent)
        /// </summary>
        /// <param name="volume">RAID-5 or striped volume</param>
        /// <returns>new extent ID</returns>
        public static ulong AddNewExtentToVolume(DiskGroupDatabase database, DynamicVolume volume, DiskExtent newExtent)
        {
            PrivateHeader privateHeader = PrivateHeader.ReadFromDisk(newExtent.Disk);

            List <DatabaseRecord> records = new List <DatabaseRecord>();

            VolumeRecord volumeRecord = database.FindVolumeByVolumeGuid(volume.VolumeGuid);

            if (volumeRecord == null)
            {
                throw new MissingDatabaseRecordException("Volume record is missing");
            }
            volumeRecord          = (VolumeRecord)volumeRecord.Clone();
            volumeRecord.SizeLBA += (ulong)PublicRegionHelper.TranslateToPublicRegionSizeLBA(newExtent.TotalSectors, privateHeader);
            records.Add(volumeRecord);

            ComponentRecord componentRecord = database.FindComponentsByVolumeID(volumeRecord.VolumeId)[0];

            if (componentRecord == null)
            {
                throw new MissingDatabaseRecordException("Component record is missing");
            }
            componentRecord = (ComponentRecord)componentRecord.Clone();
            componentRecord.NumberOfExtents++;
            componentRecord.NumberOfColumns++;
            records.Add(componentRecord);

            DiskRecord diskRecord = database.FindDiskByDiskGuid(privateHeader.DiskGuid);

            if (diskRecord == null)
            {
                throw new MissingDatabaseRecordException("Disk record is missing");
            }
            diskRecord = (DiskRecord)diskRecord.Clone();
            records.Add(diskRecord);

            ExtentRecord newExtentRecord = new ExtentRecord();

            newExtentRecord.Name               = GetNextExtentName(database.ExtentRecords, diskRecord.Name);
            newExtentRecord.ComponentId        = componentRecord.ComponentId;
            newExtentRecord.DiskId             = diskRecord.DiskId;
            newExtentRecord.DiskOffsetLBA      = (ulong)PublicRegionHelper.TranslateToPublicRegionLBA(newExtent.FirstSector, privateHeader);
            newExtentRecord.SizeLBA            = (ulong)PublicRegionHelper.TranslateToPublicRegionSizeLBA(newExtent.TotalSectors, privateHeader);
            newExtentRecord.HasColumnIndexFlag = true;
            newExtentRecord.ColumnIndex        = (uint)volume.Columns.Count; // zero based

            records.Add(newExtentRecord);

            // we should update the disk records and extent records
            foreach (DynamicDiskExtent extent in volume.Extents)
            {
                ExtentRecord extentRecord = database.FindExtentByExtentID(extent.ExtentID);
                if (extentRecord == null)
                {
                    throw new MissingDatabaseRecordException("Extent record is missing");
                }
                extentRecord = (ExtentRecord)extentRecord.Clone();
                records.Add(extentRecord);

                diskRecord = database.FindDiskByDiskID(extentRecord.DiskId);
                if (diskRecord == null)
                {
                    throw new MissingDatabaseRecordException("Disk record is missing");
                }
                // there could be multiple extents on the same disk, make sure we only add each disk once
                if (!records.Contains(diskRecord))
                {
                    diskRecord = (DiskRecord)diskRecord.Clone();
                    records.Add(diskRecord);
                }
            }

            database.UpdateDatabase(records);

            return(newExtentRecord.ExtentId);
        }