Beispiel #1
0
 internal IEnumerable <KeyValuePair <string, long> > GetChildIds()
 {
     if (mDslDir.child_dir_zapobj == 0)
     {
         return(Enumerable.Empty <KeyValuePair <string, long> >());
     }
     return(Zap.GetDirectoryEntries(mMos, mDslDir.child_dir_zapobj));
 }
Beispiel #2
0
        public Dictionary <string, DatasetDirectory> GetChildren()
        {
            var ret = new Dictionary <string, DatasetDirectory>();

            if (mDslDir.child_dir_zapobj != 0)
            {
                foreach (var child in Zap.GetDirectoryEntries(mMos, mDslDir.child_dir_zapobj))
                {
                    ret.Add(child.Key, new DatasetDirectory(mMos, child.Value, child.Key, mZio));
                }
            }
            return(ret);
        }
Beispiel #3
0
            public IEnumerable <ZfsItem> GetChildren()
            {
                var dirContents = Zap.GetDirectoryEntries(mDn);

                foreach (var kvp in dirContents)
                {
                    string      name  = kvp.Key;
                    ZfsItemType type  = (ZfsItemType)((ulong)kvp.Value >> 60);
                    long        objId = kvp.Value & (long)~0xF000000000000000;
                    var         dn    = mZpl.mZfsObjset.ReadEntry(objId);

                    using (var saAttrs = this.mZpl.RentAttrBytes(dn))
                    {
                        if (dn.Type == dmu_object_type_t.DIRECTORY_CONTENTS)
                        {
                            yield return(new ZfsDirectory(mZpl, this, name, dn, saAttrs));
                        }
                        else if (dn.Type == dmu_object_type_t.PLAIN_FILE_CONTENTS)
                        {
                            if (type == ZfsItemType.None)
                            {
                                type = mZpl.GetFileType(saAttrs);
                            }
                            if (type == ZfsItemType.S_IFREG)
                            {
                                yield return(new ZfsFile(mZpl, this, name, dn, saAttrs));
                            }
                            else if (type == ZfsItemType.S_IFLNK)
                            {
                                yield return(new ZfsSymLink(mZpl, this, name, dn, saAttrs));
                            }
                            else
                            {
                                //TODO: other file types
                            }
                        }
                        else
                        {
                            throw new NotSupportedException();
                        }
                    }
                }
            }
Beispiel #4
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);
                }
            }
        }
Beispiel #5
0
        private long GetFsObjectId(string path)
        {
            if (string.IsNullOrEmpty(path) || path[0] != '/')
            {
                throw new ArgumentOutOfRangeException("Must be absolute path.");
            }

            long id = mZfsObjDir["ROOT"];

            if (path == "/")
            {
                return(id);
            }

            var pathParts = path.Substring(1).Split('/');

            foreach (var p in pathParts)
            {
                var dir = Zap.GetDirectoryEntries(mZfsObjset, id);
                id = dir[p];
            }

            return(id);
        }
Beispiel #6
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 #7
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 #8
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();
        }