private static void CheckVersion(NvList cfg) { if (cfg.Get <ulong>("version") != SUPPORTED_VERSION) { throw new Exception("Unsupported version."); } var state = (pool_state)cfg.Get <ulong>("state"); if (state != pool_state.ACTIVE && state != pool_state.EXPORTED) { throw new Exception("Unknown state: " + state); } var features = cfg.Get <NvList>("features_for_read"); foreach (var kvp in features) { if (!sSupportReadFeatures.Contains(kvp.Key)) { throw new Exception("Unsupported feature: " + kvp.Key); } } }
public LeafVdevInfo(HardDisk hdd) { this.HDD = hdd; var rentedBytes = Program.RentBytes(VDEV_PHYS_SIZE); try { if (!hdd.ReadLabelBytes(rentedBytes, VDEV_SKIP_SIZE)) { throw new Exception("Invalid checksum on lable config data!"); } Config = new NvList(rentedBytes); } finally { Program.ReturnBytes(rentedBytes); rentedBytes = default(ArraySegment <byte>); } //figure out how big the uber blocks are var vdevTree = Config.Get <NvList>("vdev_tree"); var ubShift = (int)vdevTree.Get <ulong>("ashift"); ubShift = Math.Max(ubShift, UBERBLOCK_SHIFT); ubShift = Math.Min(ubShift, MAX_UBERBLOCK_SHIFT); var ubSize = 1 << ubShift; var ubCount = VDEV_UBERBLOCK_RING >> ubShift; List <uberblock_t> blocks = new List <uberblock_t>(); var ubBytes = Program.RentBytes(ubSize); try { for (long i = 0; i < ubCount; i++) { var offset = VDEV_SKIP_SIZE + VDEV_PHYS_SIZE + ubSize * i; if (!hdd.ReadLabelBytes(ubBytes, offset)) { continue; } uberblock_t b = Program.ToStruct <uberblock_t>(ubBytes.Array, ubBytes.Offset); if (b.Magic == uberblock_t.UbMagic) { blocks.Add(b); } } } finally { Program.ReturnBytes(ubBytes); ubBytes = default(ArraySegment <byte>); } this.Uberblock = blocks.OrderByDescending(u => u.Txg).ThenByDescending(u => u.TimeStamp).First(); const int VDevLableSizeStart = 4 << 20; const int VDevLableSizeEnd = 512 << 10; hdd = OffsetHardDisk.Create(hdd, VDevLableSizeStart, hdd.Length - VDevLableSizeStart - VDevLableSizeEnd); this.HDD = hdd; }
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(); }
private void Load(NvListBinaryReader r) { int version = r.ReadInt32(); if (version != NV_VERSION) { throw new NotSupportedException("Unsupport NVList version!"); } NvFlags flags = (NvFlags)r.ReadInt32(); while (true) { int encodedSize = r.ReadInt32(); int decodedSize = r.ReadInt32(); if (encodedSize == 0 && decodedSize == 0) { break; } string name = r.ReadString(); NvDataType type = (NvDataType)r.ReadInt32(); int numberOfElements = r.ReadInt32(); object val; switch (type) { case NvDataType.STRING: val = r.ReadString(); break; case NvDataType.UINT64: val = r.ReadUInt64(); break; case NvDataType.NVLIST: val = new NvList(r); break; case NvDataType.NVLIST_ARRAY: var array = new NvList[numberOfElements]; for (int i = 0; i < numberOfElements; i++) { array[i] = new NvList(r); } val = array; break; case NvDataType.BOOLEAN: val = true; break; case NvDataType.BOOLEAN_VALUE: val = r.ReadInt32() != 0; break; default: throw new NotImplementedException(); } mVals.Add(name, val); } }