@Override
    public HFileBlock readBlockData(long offset, long onDiskSizeWithHeaderL, boolean pread,
      boolean updateMetrics, boolean intoHeap) throws IOException {
      // Get a copy of the current state of whether to validate
      // hbase checksums or not for this read call. This is not
      // thread-safe but the one constraint is that if we decide
      // to skip hbase checksum verification then we are
      // guaranteed to use hdfs checksum verification.
      boolean doVerificationThruHBaseChecksum = streamWrapper.shouldUseHBaseChecksum();
      FSDataInputStream is = streamWrapper.getStream(doVerificationThruHBaseChecksum);
      final Context context = Context.current().with(CONTEXT_KEY,
        new HFileContextAttributesBuilderConsumer(fileContext)
          .setSkipChecksum(doVerificationThruHBaseChecksum)
          .setReadType(pread ? ReadType.POSITIONAL_READ : ReadType.SEEK_PLUS_READ));
      try (Scope ignored = context.makeCurrent()) {
        HFileBlock blk = readBlockDataInternal(is, offset, onDiskSizeWithHeaderL, pread,
          doVerificationThruHBaseChecksum, updateMetrics, intoHeap);
        if (blk == null) {
          HFile.LOG.warn("HBase checksum verification failed for file {} at offset {} filesize {}."
            + " Retrying read with HDFS checksums turned on...", pathName, offset, fileSize);

          if (!doVerificationThruHBaseChecksum) {
            String msg = "HBase checksum verification failed for file " + pathName + " at offset "
              + offset + " filesize " + fileSize + " but this cannot happen because doVerify is "
              + doVerificationThruHBaseChecksum;
            HFile.LOG.warn(msg);
            throw new IOException(msg); // cannot happen case here
          }
          HFile.CHECKSUM_FAILURES.increment(); // update metrics

          // If we have a checksum failure, we fall back into a mode where
          // the next few reads use HDFS level checksums. We aim to make the
          // next CHECKSUM_VERIFICATION_NUM_IO_THRESHOLD reads avoid
          // hbase checksum verification, but since this value is set without
          // holding any locks, it can so happen that we might actually do
          // a few more than precisely this number.
          is = this.streamWrapper.fallbackToFsChecksum(CHECKSUM_VERIFICATION_NUM_IO_THRESHOLD);
          doVerificationThruHBaseChecksum = false;
          blk = readBlockDataInternal(is, offset, onDiskSizeWithHeaderL, pread,
            doVerificationThruHBaseChecksum, updateMetrics, intoHeap);
          if (blk != null) {
            HFile.LOG.warn(
              "HDFS checksum verification succeeded for file {} at offset {} filesize" + " {}",
              pathName, offset, fileSize);
          }
        }
        if (blk == null && !doVerificationThruHBaseChecksum) {
          String msg =
            "readBlockData failed, possibly due to " + "checksum verification failed for file "
              + pathName + " at offset " + offset + " filesize " + fileSize;
          HFile.LOG.warn(msg);
          throw new IOException(msg);
        }

        // If there is a checksum mismatch earlier, then retry with
        // HBase checksums switched off and use HDFS checksum verification.
        // This triggers HDFS to detect and fix corrupt replicas. The
        // next checksumOffCount read requests will use HDFS checksums.
        // The decrementing of this.checksumOffCount is not thread-safe,
        // but it is harmless because eventually checksumOffCount will be
        // a negative number.
        streamWrapper.checksumOk();
        return blk;
      }
    }
Reads a version 2 block (version 1 blocks not supported and not expected). Tries to do as
little memory allocation as possible, using the provided on-disk size.
@param offset                the offset in the stream to read at
@param onDiskSizeWithHeaderL the on-disk size of the block, including the header, or -1 if
                             unknown; i.e. when iterating over blocks reading in the file
                             metadata info.
@param pread                 whether to use a positional read
@param updateMetrics         whether to update the metrics
@param intoHeap              allocate ByteBuff of block from heap or off-heap.
@see FSReader#readBlockData(long, long, boolean, boolean, boolean) for more details about the
     useHeap.
hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/HFileBlock.java