istream-mmap.c revision 252db51b6c0a605163326b3ea5d09e9936ca3b29
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2003 Timo Sirainen */
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainenstatic void _close(struct iostream_private *stream)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mstream->autoclose_fd && mstream->istream.fd != -1) {
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainenstatic void i_stream_munmap(struct mmap_istream *mstream)
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen struct istream_private *_stream = &mstream->istream;
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen if (munmap(mstream->mmap_base, _stream->buffer_size) < 0)
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainenstatic void _destroy(struct iostream_private *stream)
c6227d7ecc972b6c58602d78602210f75190ae3fTimo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainenstatic size_t mstream_get_mmap_block_size(struct istream_private *stream)
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen return (stream->max_buffer_size + mmap_get_page_size() - 1) & ~
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainenstatic ssize_t _read(struct istream_private *stream)
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen /* more bytes available without needing to mmap() */
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen if (stream->istream.v_offset >= mstream->v_size) {
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen if (aligned_skip == 0 && mstream->mmap_base != NULL) {
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen /* didn't skip enough bytes */
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen if (munmap(mstream->mmap_base, stream->buffer_size) < 0)
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen i_error("io_stream_read_mmaped(): munmap() failed: %m");
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen stream->buffer_size = I_MIN(top, mstream_get_mmap_block_size(stream));
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen i_assert((uoff_t)mstream->mmap_offset + stream->buffer_size <=
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen /* don't bother even trying mmap */
eadbca0f2b78fcc36332678fee9ee08003df63deTimo Sirainen mmap(NULL, stream->buffer_size, PROT_READ, MAP_PRIVATE,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (stream->buffer_size > mmap_get_page_size()) {
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen if (madvise(mstream->mmap_base, stream->buffer_size,
d22301419109ed4a38351715e6760011421dadecTimo Sirainenstatic void _seek(struct istream_private *stream, uoff_t v_offset,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (uoff_t)mstream->mmap_offset + stream->buffer_size > v_offset) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* already mmaped */
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen stream->skip = stream->pos = v_offset - mstream->mmap_offset;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* force reading next time */
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainenstatic void _sync(struct istream_private *stream)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
4b2a4c8c762e3eaddf7fd2abfe7d4cca6e5e3fd8Timo Sirainen stream->skip = stream->pos = stream->istream.v_offset;
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainenstatic int fstat_cached(struct mmap_istream *mstream)
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen if (mstream->fstat_cache_stamp.tv_sec == ioloop_timeval.tv_sec &&
607a8bc27298b711270381364f2a9a999a810a87Timo Sirainen mstream->fstat_cache_stamp.tv_usec == ioloop_timeval.tv_usec)
607a8bc27298b711270381364f2a9a999a810a87Timo Sirainen if (fstat(mstream->istream.fd, &mstream->istream.statbuf) < 0) {
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainenstatic const struct stat *
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen_stat(struct istream_private *stream, bool exact ATTR_UNUSED)
607a8bc27298b711270381364f2a9a999a810a87Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Boschstruct istream *i_stream_create_mmap(int fd, size_t block_size,
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen i_error("i_stream_create_mmap(): fstat() failed: %m");
df3963075d67f76ade66b6a74764f4eae31d9c87Josef 'Jeff' Sipek mstream->istream.max_buffer_size = block_size;