private void CheckFeatures() { var fr = Zap.GetDirectoryEntries(mMos, mObjDir["features_for_read"]); var fw = Zap.GetDirectoryEntries(mMos, mObjDir["features_for_write"]); var ff = Zap.Parse(mMos.ReadEntry(mObjDir["feature_descriptions"])).ToDictionary(kvp => kvp.Key, kvp => Encoding.ASCII.GetString((byte[])kvp.Value)); if (fw.ContainsKey("com.delphix:enabled_txg") && fw["com.delphix:enabled_txg"] > 0) { var fe = Zap.GetDirectoryEntries(mMos, mObjDir["feature_enabled_txg"]); } foreach (var feature in fr) { if (feature.Value != 0 && !sSupportReadFeatures.Contains(feature.Key)) { throw new Exception("Unsupported feature: " + feature.Key); } } }
internal Zpl(ObjectSet mos, long objectid, Zio zio) { this.mZio = zio; var rootDataSetObj = mos.ReadEntry(objectid); if (!DatasetDirectory.IsDataSet(rootDataSetObj)) { throw new Exception("Not a DSL_DIR."); } mDataset = rootDataSetObj.GetBonus <dsl_dataset_phys_t>(); if (rootDataSetObj.IsNewType && rootDataSetObj.NewType == dmu_object_byteswap.DMU_BSWAP_ZAP) { var dataSetExtensions = Zap.Parse(rootDataSetObj); } if (mDataset.prev_snap_obj != 0) { var dn = mos.ReadEntry(mDataset.prev_snap_obj); var moreDs = dn.GetBonus <dsl_dataset_phys_t>(); } if (mDataset.props_obj != 0) { var someProps = Zap.Parse(mos, mDataset.props_obj); } mZfsObjset = new ObjectSet(mZio, zio.Get <objset_phys_t>(mDataset.bp)); if (mZfsObjset.Type != dmu_objset_type_t.DMU_OST_ZFS) { throw new NotSupportedException(); } mZfsObjDir = Zap.GetDirectoryEntries(mZfsObjset, 1); if (mZfsObjDir["VERSION"] != 5) { throw new NotSupportedException(); } var saAttrs = Zap.GetDirectoryEntries(mZfsObjset, mZfsObjDir["SA_ATTRS"]); var saLayouts = Zap.Parse(mZfsObjset.ReadEntry(saAttrs["LAYOUTS"])); var saRegistry = Zap.GetDirectoryEntries(mZfsObjset, saAttrs["REGISTRY"]); mAttrSize = new Dictionary <zpl_attr_t, int>(); foreach (var kvp in saRegistry) { var attrName = (zpl_attr_t)(kvp.Value & 0xffff); var size = (int)(kvp.Value >> 24 & 0xffff); if (kvp.Key != attrName.ToString()) { throw new Exception(); } mAttrSize.Add(attrName, size); } foreach (var layoutName in saLayouts.Keys) { var layoutNumber = int.Parse(layoutName); var types = ((short[])saLayouts[layoutName]).Select(a => (zpl_attr_t)a).ToArray(); mAttrLayouts.Add(layoutNumber, new SaLayout(mAttrSize, types)); } }
internal DatasetDirectory(ObjectSet mos, long objectid, string name, Zio zio) { this.mMos = mos; this.mZio = zio; this.Name = name; this.Type = DataSetType.MetaData; var rootDslObj = mos.ReadEntry(objectid); if (rootDslObj.Type != dmu_object_type_t.DSL_DIR) { throw new NotSupportedException("Expected DSL_DIR dnode."); } if (rootDslObj.BonusType != dmu_object_type_t.DSL_DIR) { throw new NotSupportedException("Expected DSL_DIR bonus."); } mDslDir = rootDslObj.GetBonus <dsl_dir_phys_t>(); var rootDslProps = Zap.Parse(mos, mDslDir.props_zapobj); Dictionary <string, long> clones; if (mDslDir.clones != 0) { clones = Zap.GetDirectoryEntries(mos, mDslDir.clones); } if (mDslDir.head_dataset_obj == 0) { return; //probably meta data, like $MOS or $FREE } var rootDataSetObj = mos.ReadEntry(mDslDir.head_dataset_obj); if (!IsDataSet(rootDataSetObj)) { throw new Exception("Not a dataset!"); } if (rootDataSetObj.BonusType != dmu_object_type_t.DSL_DATASET) { throw new Exception("Missing dataset bonus!"); } var headDs = rootDataSetObj.GetBonus <dsl_dataset_phys_t>(); if (headDs.bp.IsHole && mDslDir.origin_obj == 0) { return; //this is $ORIGIN } if (headDs.snapnames_zapobj != 0) { mSnapShots = Zap.GetDirectoryEntries(mMos, headDs.snapnames_zapobj); } if (headDs.bp.Type != dmu_object_type_t.OBJSET) { throw new Exception("Expected OBJSET."); } var headDsObjset = zio.Get <objset_phys_t>(headDs.bp); switch (headDsObjset.Type) { case dmu_objset_type_t.DMU_OST_ZFS: this.Type = DataSetType.ZFS; break; case dmu_objset_type_t.DMU_OST_ZVOL: this.Type = DataSetType.ZVOL; break; default: throw new Exception("Unknow dataset type: " + headDsObjset.Type.ToString()); } }
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(); }