private void ReadGangBlkPtr(blkptr_t blkptr, ArraySegment <byte> dest, ref int offset) { int size = blkptr.LogicalSizeBytes; Read(blkptr, dest.SubSegment(offset, size)); offset += size; }
public void Read(blkptr_t blkptr, Span <byte> dest) { if (blkptr.birth == 0) { throw new NotSupportedException("Invalid block pointer: 0 birth txg."); } if (blkptr.IsHole) { throw new Exception("Block pointer is a hole."); } if (blkptr.IsLittleEndian != BitConverter.IsLittleEndian) { throw new NotImplementedException("Byte swapping not implemented."); } if (blkptr.LogicalSizeBytes != dest.Length) { throw new ArgumentOutOfRangeException("dest", "Dest does not match logical size of block pointer."); } if (blkptr.IsEmbedded) { ReadEmbedded(blkptr, dest); return; } //if (blkptr.fill == 0) // throw new NotSupportedException("There is no data in this block pointer."); //TODO: try other DVAs Read(blkptr, blkptr.dva1, dest); }
private static zio_cksum_t CalculateGangChecksumVerifier(ref blkptr_t blkptr) { var ret = new zio_cksum_t(); ret.word1 = (ulong)blkptr.dva1.VDev; ret.word2 = (ulong)(blkptr.dva1.Offset << SPA_MINBLOCKSHIFT); ret.word3 = (ulong)blkptr.PhysBirth; ret.word4 = 0; return(ret); }
unsafe void ReadEmbedded(blkptr_t blkptr, Span <byte> dest) { if (blkptr.EmbedType != EmbeddedType.Data) { throw new Exception("Unsupported embedded type: " + blkptr.EmbedType); } int physicalSize = blkptr.PhysicalSizeBytes; if (physicalSize > blkptr_t.EM_DATA_SIZE) { throw new Exception("PSize is too big!"); } var physicalBytes = Program.RentBytes(physicalSize); const int NUMBER_OF_EMBEDDED_CHUNKS = 3; Debug.Assert(blkptr_t.EmbeddedSizes.Length == NUMBER_OF_EMBEDDED_CHUNKS); byte **embeddedDataPoints = stackalloc byte *[NUMBER_OF_EMBEDDED_CHUNKS]; embeddedDataPoints[0] = blkptr.EmbeddedData1; embeddedDataPoints[1] = blkptr.EmbeddedData2; embeddedDataPoints[2] = blkptr.EmbeddedData3; fixed(byte *pStartPtr = physicalBytes.Array) { var pBytes = pStartPtr + physicalBytes.Offset; int remaingBytes = physicalSize; for (int i = 0; remaingBytes > 0 && i < NUMBER_OF_EMBEDDED_CHUNKS; i++) { int size = Math.Min(remaingBytes, blkptr_t.EmbeddedSizes[i]); Debug.Assert(size > 0); Unsafe.CopyBlock(pBytes, embeddedDataPoints[i], (uint)size); pBytes += size; remaingBytes -= size; } } mCompression[blkptr.Compress].Decompress(physicalBytes, dest); Program.ReturnBytes(physicalBytes); }
/// <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."); }
private void readBlock(Span <byte> dest, blkptr_t blkptr, int startNdx) { if (blkptr.IsHole) return; }
public void Read(blkptr_t blkptr, ArraySegment <byte> dest) { Read(blkptr, (Span <byte>)dest); }