Beispiel #1
0
        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());
            }
        }
Beispiel #2
0
        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));
            }
        }
Beispiel #3
0
        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();
        }