/// <summary> /// Just reads the bytes off the disk, reading gang blocks as needed. /// </summary> /// <param name="blkptr"></param> /// <param name="dva"></param> /// <returns>A buffer allocated from <see cref="Program.RentBytes"/>.</returns> private ArraySegment <byte> ReadPhyical(blkptr_t blkptr, dva_t dva) { Vdev dev = mVdevs[dva.VDev]; int hddReadSize = dva.IsGang ? zio_gbh_phys_t.SPA_GANGBLOCKSIZE : blkptr.PhysicalSizeBytes; var hddBytes = Program.RentBytes(hddReadSize); dev.ReadBytes(hddBytes, dva.Offset << SPA_MINBLOCKSHIFT); if (!dva.IsGang) { return(hddBytes); } var gangHeader = Program.ToStruct <zio_gbh_phys_t>(hddBytes); bool isChecksumValid = IsEmbeddedChecksumValid(hddBytes, CalculateGangChecksumVerifier(ref blkptr)); Program.ReturnBytes(hddBytes); hddBytes = default(ArraySegment <byte>); if (!isChecksumValid) throw new Exception("Could not find a correct copy of the requested data."); }
private void Load() { if (mHdds.Count == 0) { throw new Exception("Did not find any hard drives."); } //make sure we support reading the pool foreach (var hdd in mHdds) { CheckVersion(hdd.Config); } //ensure all HDDs are part of the same pool var poolGuid = mHdds.Select(h => h.Config.Get <ulong>("pool_guid")).Distinct().ToArray(); if (poolGuid.Length != 1) { throw new Exception("Hard drives are part of different pools: " + string.Join(", ", poolGuid.Select(p => p.ToString()))); } //ensure all HDDs agree on the transaction group id var txg = mHdds.Select(hdd => hdd.Uberblock.Txg).Distinct().ToArray(); if (txg.Length != 1) { throw new Exception("Uberblocks do not all have the same transaction group id: " + string.Join(", ", txg.Select(p => p.ToString()))); } var ub = mHdds[0].Uberblock; if (ub.Txg == 0) { throw new Exception("Root block pointer's transaction group is zero!"); } var vdevs = Vdev.CreateVdevTree(mHdds); mZio = new Zio(vdevs); mMos = new ObjectSet(mZio, mZio.Get <objset_phys_t>(ub.rootbp)); if (mMos.Type != dmu_objset_type_t.DMU_OST_META) { throw new Exception("Given block pointer did not point to the MOS."); } mZio.InitMetaSlabs(mMos); //the second time we will make sure that space maps contain themselves mZio.InitMetaSlabs(mMos); var objectDirectory = mMos.ReadEntry(1); //The MOS's directory sometimes has things that don't like like directory entries. //For example, the "scan" entry has scrub status stuffed into as an array of longs. mObjDir = Zap.GetDirectoryEntries(objectDirectory, true); if (mObjDir.ContainsKey(DDT_STATISTICS)) { var ddtStats = Zap.Parse(mMos.ReadEntry(mObjDir[DDT_STATISTICS])); //TODO: maybe do something interesting with the stats } { var configDn = mMos.ReadEntry(mObjDir[CONFIG]); var configBytes = Program.RentBytes(checked ((int)configDn.AvailableDataSize)); configDn.Read(configBytes, 0); mConfig = new NvList(configBytes); Program.ReturnBytes(configBytes); } CheckVersion(mConfig); CheckFeatures(); }