Ejemplo n.º 1
0
        /// <summary>
        /// Just reads the bytes off the disk, reading gang blocks as needed.
        /// </summary>
        /// <param name="blkptr"></param>
        /// <param name="dva"></param>
        /// <returns>A buffer allocated from <see cref="Program.RentBytes"/>.</returns>
        private ArraySegment <byte> ReadPhyical(blkptr_t blkptr, dva_t dva)
        {
            Vdev dev         = mVdevs[dva.VDev];
            int  hddReadSize = dva.IsGang ? zio_gbh_phys_t.SPA_GANGBLOCKSIZE : blkptr.PhysicalSizeBytes;

            var hddBytes = Program.RentBytes(hddReadSize);

            dev.ReadBytes(hddBytes, dva.Offset << SPA_MINBLOCKSHIFT);

            if (!dva.IsGang)
            {
                return(hddBytes);
            }

            var gangHeader = Program.ToStruct <zio_gbh_phys_t>(hddBytes);

            bool isChecksumValid = IsEmbeddedChecksumValid(hddBytes, CalculateGangChecksumVerifier(ref blkptr));

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

            if (!isChecksumValid)
                throw new Exception("Could not find a correct copy of the requested data."); }
Ejemplo n.º 2
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();
        }