istream-mmap.c revision 0536ccb51d41e3078c3a9fa33e509fb4b2420f95
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2002-2011 Dovecot authors, see the included COPYING file */
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainenstatic void i_stream_mmap_close(struct iostream_private *stream)
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen if (mstream->autoclose_fd && mstream->istream.fd != -1) {
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen i_stream_get_name(&mstream->istream.istream));
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainenstatic void i_stream_munmap(struct mmap_istream *mstream)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen struct istream_private *_stream = &mstream->istream;
4b41116563110d00330896a568eff1078c382827Timo Sirainen if (munmap(mstream->mmap_base, _stream->buffer_size) < 0) {
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainenstatic void i_stream_mmap_destroy(struct iostream_private *stream)
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainenstatic size_t mstream_get_mmap_block_size(struct istream_private *stream)
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen return (stream->max_buffer_size + mmap_get_page_size() - 1) & ~
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainenstatic ssize_t i_stream_mmap_read(struct istream_private *stream)
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen /* more bytes available without needing to mmap() */
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen if (stream->istream.v_offset >= mstream->v_size) {
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen if (aligned_skip == 0 && mstream->mmap_base != NULL) {
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen /* didn't skip enough bytes */
910fa4e4204a73d3d24c03f3059dd24e727ca057Timo Sirainen if (munmap(mstream->mmap_base, stream->buffer_size) < 0) {
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen stream->buffer_size = I_MIN(top, mstream_get_mmap_block_size(stream));
fe6c1556d3529a6376d4cbb3766c34aebde0de99Timo Sirainen i_assert((uoff_t)mstream->mmap_offset + stream->buffer_size <=
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen /* don't bother even trying mmap */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen mmap(NULL, stream->buffer_size, PROT_READ, MAP_PRIVATE,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (stream->buffer_size > mmap_get_page_size()) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (madvise(mstream->mmap_base, stream->buffer_size,
90adcaa0a00eba29b7fbd50ca66be11c8d086d6aTimo Sirainenstatic void i_stream_mmap_seek(struct istream_private *stream, uoff_t v_offset,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen (uoff_t)mstream->mmap_offset + stream->buffer_size > v_offset) {
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen /* already mmaped */
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen stream->skip = stream->pos = v_offset - mstream->mmap_offset;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen /* force reading next time */
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainenstatic void i_stream_mmap_sync(struct istream_private *stream)
bf9402875418faf11825cf11fbe06326b6086e3dTimo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainen stream->skip = stream->pos = stream->istream.v_offset;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainenstatic int fstat_cached(struct mmap_istream *mstream)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (mstream->fstat_cache_stamp.tv_sec == ioloop_timeval.tv_sec &&
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen mstream->fstat_cache_stamp.tv_usec == ioloop_timeval.tv_usec)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (fstat(mstream->istream.fd, &mstream->istream.statbuf) < 0) {
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen i_stream_get_name(&mstream->istream.istream));
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainenstatic const struct stat *
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Siraineni_stream_mmap_stat(struct istream_private *stream, bool exact ATTR_UNUSED)
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
5daa12cc1c862eec4f63df42227812d3514da2ccTimo Sirainenstruct istream *i_stream_create_mmap(int fd, size_t block_size,
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen i_error("i_stream_create_mmap(): fstat() failed: %m");
5abb33fdc94c081ccd3213bf7d0fa9d0367b4bfdTimo Sirainen mstream->istream.iostream.close = i_stream_mmap_close;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen mstream->istream.iostream.destroy = i_stream_mmap_destroy;
54d42552005111841ab45ec9ca7559075fabd5dfTimo Sirainen mstream->istream.max_buffer_size = block_size;
64a67c0296b120b6e15169ac9d84dec964e55969Timo Sirainen mstream->istream.abs_start_offset = start_offset;