bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenstatic void i_stream_mmap_close(struct iostream_private *stream,
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (mstream->autoclose_fd && mstream->istream.fd != -1) {
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen i_stream_get_name(&mstream->istream.istream));
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic void i_stream_munmap(struct mmap_istream *mstream)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = &mstream->istream;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic void i_stream_mmap_destroy(struct iostream_private *stream)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstatic size_t mstream_get_mmap_block_size(struct istream_private *stream)
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen return (stream->max_buffer_size + mmap_get_page_size() - 1) & ~
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainenstatic void i_stream_mmap_marea_free(struct mmap_memarea *marea)
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen if (munmap(marea->mmap_base, marea->mmap_size) < 0)
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic ssize_t i_stream_mmap_read(struct istream_private *stream)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* more bytes available without needing to mmap() */
9e095dd6a77097356aca8216356d4d71ef1bea45Timo Sirainen if (stream->istream.v_offset >= mstream->v_size) {
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen if (aligned_skip == 0 && stream->buffer != NULL) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* didn't skip enough bytes */
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen stream->buffer_size = I_MIN(top, mstream_get_mmap_block_size(stream));
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_assert((uoff_t)mstream->mmap_offset + stream->buffer_size <=
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen /* don't bother even trying mmap */
67c24901ac5e1521e38a91efc452faeb3e2135a1Timo Sirainen mmap(NULL, stream->buffer_size, PROT_READ, MAP_PRIVATE,
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen "mmap() failed: %m");
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen struct mmap_memarea *marea = i_new(struct mmap_memarea, 1);
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen stream->memarea = memarea_init(mmap_base, marea->mmap_size,
d74c9f4bf7ee37f3f58a895032ea013d07294865Timo Sirainen if (stream->buffer_size > mmap_get_page_size()) {
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic void i_stream_mmap_seek(struct istream_private *stream, uoff_t v_offset,
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
b3142c8e513bc78da821fa70f479016148fa95e5Timo Sirainen (uoff_t)mstream->mmap_offset + stream->buffer_size > v_offset) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* already mmaped */
b3142c8e513bc78da821fa70f479016148fa95e5Timo Sirainen stream->skip = stream->pos = v_offset - mstream->mmap_offset;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* force reading next time */
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainenstatic void i_stream_mmap_sync(struct istream_private *stream)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen stream->skip = stream->pos = stream->istream.v_offset;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainenstatic int fstat_cached(struct mmap_istream *mstream)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (mstream->fstat_cache_stamp.tv_sec == ioloop_timeval.tv_sec &&
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen mstream->fstat_cache_stamp.tv_usec == ioloop_timeval.tv_usec)
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen if (fstat(mstream->istream.fd, &mstream->istream.statbuf) < 0) {
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen i_stream_get_name(&mstream->istream.istream));
a94936bafd127680184da114c6a177b37ff656e5Timo Siraineni_stream_mmap_stat(struct istream_private *stream, bool exact ATTR_UNUSED)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen struct mmap_istream *mstream = (struct mmap_istream *) stream;
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainenstruct istream *i_stream_create_mmap(int fd, size_t block_size,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen i_error("i_stream_create_mmap(): fstat() failed: %m");
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen mstream->istream.iostream.close = i_stream_mmap_close;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen mstream->istream.iostream.destroy = i_stream_mmap_destroy;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen mstream->istream.max_buffer_size = block_size;