As mentioned in https://github.com/elastic/elasticsearch/pull/96216, `LuceneVerifyingIndexOutput` always copies the last chunk byte-by-byte. This might be a pretty big chunk. We should be able to copy all the bytes up to the start of the checksum in bulk (and then I guess bulk-copy the checksum too not that this matters so much).

In the same area, `LuceneVerifyingIndexOutput` is the only subclass of `VerifyingIndexOutput` and there's no need for it to be an inner class of `Store`. `VerifyingIndexInput` also doesn't need to be an inner class.
server/src/main/java/org/elasticsearch/index/store/Store.java
}
        }
        @Override
        public void writeTo(StreamOutput out) throws IOException {
            out.writeMapValues(fileMetadataMap);
            out.writeMap(commitUserData, StreamOutput::writeString, StreamOutput::writeString);
            out.writeLong(numDocs);
        }
        @Nullable
        public org.elasticsearch.Version getCommitVersion() {
            String version = commitUserData.get(ES_VERSION);
            return version == null ? null : org.elasticsearch.Version.fromString(version);
        }
        private static void checksumFromLuceneFile(
            Directory directory,
            String file,
            Map<String, StoreFileMetadata> builder,
            Logger logger,
            String version,
            boolean readFileAsHash,
            BytesRef writerUuid
        ) throws IOException {
            final String checksum;
            final BytesRefBuilder fileHash = new BytesRefBuilder();
            try (IndexInput in = directory.openInput(file, READONCE_CHECKSUM)) {
                final long length;
                try {
                    length = in.length();
                    if (length < CodecUtil.footerLength()) {