示例#1
0
        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);
                }
            }
        }
示例#2
0
        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;
        }
示例#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();
        }
示例#4
0
        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);
            }
        }