Exemple #1
0
        public MetaSlabs(ObjectSet mos, long metaSlabArray, int metaSlabShift, int aShift)
        {
            mMos      = mos;
            mSlabSize = 1L << metaSlabShift;

            var slabDnode = mos.ReadEntry(metaSlabArray);
            var someBytes = Program.RentBytes(checked ((int)slabDnode.AvailableDataSize));

            slabDnode.Read(someBytes, 0);

            int numberOfSlabs = someBytes.Count / 8;

            mRangeMap = new RangeMap[numberOfSlabs];
            long[] ids = new long[numberOfSlabs];
            Buffer.BlockCopy(someBytes.Array, someBytes.Offset, ids, 0, someBytes.Count);

            Program.ReturnBytes(someBytes);
            someBytes = default(ArraySegment <byte>);

            for (int i = 0; i < numberOfSlabs; i++)
            {
                var      id = ids[i];
                RangeMap map;
                if (id == 0)
                {
                    map = new RangeMap();
                }
                else
                {
                    map = LoadEntrysForMetaSlab(id, aShift);
                }
                mRangeMap[i] = map;
            }
        }
Exemple #2
0
        unsafe RangeMap LoadEntrysForMetaSlab(long dnEntry, int sm_shift)
        {
            RangeMap ret = new RangeMap();

            var dn = mMos.ReadEntry(dnEntry);

            if (dn.Type != dmu_object_type_t.SPACE_MAP || dn.BonusType != dmu_object_type_t.SPACE_MAP_HEADER)
            {
                throw new Exception("Not a space map.");
            }

            var head = dn.GetBonus <space_map_obj>();

            if (head.smo_object != dnEntry)
            {
                throw new Exception();
            }

            if (head.smo_objsize > int.MaxValue)
            {
                throw new Exception("Holy cow, this space map is greater than 2GB, what is wrong with your VDev!?!?");
            }

            var someBytes = Program.RentBytes((int)head.smo_objsize);

            dn.Read(someBytes, 0);
            for (int i = 0; i < someBytes.Count; i += 8)
            {
                var ent = Program.ToStruct <spaceMapEntry>(someBytes.SubSegment(i, sizeof(spaceMapEntry)));
                if (ent.IsDebug)
                {
                    continue;
                }

                ulong offset = (ent.Offset << sm_shift);
                ulong range  = ent.Run << sm_shift;
                //Console.WriteLine("\t    [{4,6}]    {0}  range: {1:x10}-{2:x10}  size: {3:x6}", ent.Type, offset, offset + range, range, i / 8);
                if (ent.Type == SpaceMapEntryType.A)
                {
                    ret.AddRange(offset, range);
                }
                else if (ent.Type == SpaceMapEntryType.F)
                {
                    ret.RemoveRange(offset, range);
                }
            }
            Program.ReturnBytes(someBytes);

            return(ret);
        }
Exemple #3
0
        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);
                }
            }
        }
Exemple #4
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));
            }
        }
Exemple #5
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());
            }
        }
Exemple #6
0
 public Zap(ObjectSet objectSet, long objectId)
     : this(objectSet.ReadEntry(objectId))
 {
 }
Exemple #7
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();
        }