file-cache.c revision b22f3db16d33b8e509b7331e46108c313e7f3b94
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen/* Copyright (c) 2004 Timo Sirainen */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->page_bitmask = buffer_create_dynamic(default_pool, 128);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (munmap_anon(cache->mmap_base, cache->mmap_length) < 0)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainenvoid file_cache_set_fd(struct file_cache *cache, int fd)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen file_cache_invalidate(cache, 0, cache->mmap_length);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainenssize_t file_cache_read(struct file_cache *cache, uoff_t offset, size_t size)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen size_t poffset, psize, mmap_needed, dest_offset, dest_size;
f83a33d8ddb275984cd89835ee8afe0ff584fe91Timo Sirainen /* make sure our calculations won't overflow. most likely
f83a33d8ddb275984cd89835ee8afe0ff584fe91Timo Sirainen we'll be reading less data, but allow it anyway so caller
f83a33d8ddb275984cd89835ee8afe0ff584fe91Timo Sirainen doesn't have to deal with any extra checks. */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen offset + size - cache->mmap_length > 1024*1024) {
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* growing more than a megabyte, make sure that the
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen file is large enough so we don't allocate memory
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen more than needed */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen psize = (offset + size + page_size-1) / page_size - poffset;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* grow mmaping */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen i_error("mmap_anon(%"PRIuSIZE_T") failed: %m",
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen cache->mmap_base = mremap_anon(cache->mmap_base,
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen i_error("mremap_anon(%"PRIuSIZE_T") failed: %m",
77717f1e9e8442fd2cdbca87cbc45c03d0b5fcaeTimo Sirainen bits = buffer_get_space_unsafe(cache->page_bitmask, 0,
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen dest = PTR_OFFSET(cache->mmap_base, dest_offset);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen while (psize > 0) {
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen if (bits[poffset / CHAR_BIT] & (1 << (poffset % CHAR_BIT))) {
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* page is already in cache */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen ret = pread(cache->fd, dest, dest_size, dest_offset);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* FIXME: we should mark the last block cached and
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen invalidate it only when trying to read past the
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* partial read - probably EOF but make sure. */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen bits[poffset / CHAR_BIT] |= 1 << (poffset % CHAR_BIT);
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainenconst void *file_cache_get_map(struct file_cache *cache, size_t *size_r)
b22f3db16d33b8e509b7331e46108c313e7f3b94Timo Sirainenvoid file_cache_write(struct file_cache *cache, const void *data, size_t size,
b22f3db16d33b8e509b7331e46108c313e7f3b94Timo Sirainen unsigned char *bits;
b22f3db16d33b8e509b7331e46108c313e7f3b94Timo Sirainen /* mark fully written pages cached */
b22f3db16d33b8e509b7331e46108c313e7f3b94Timo Sirainen bits = buffer_get_space_unsafe(cache->page_bitmask, 0,
b22f3db16d33b8e509b7331e46108c313e7f3b94Timo Sirainen for (; first_page < last_page; first_page++) {
74eff344f67ca582eec8c38dfdc6f5f6faa21fd8Timo Sirainenvoid file_cache_invalidate(struct file_cache *cache, uoff_t offset, uoff_t size)
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen unsigned int i;
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen size = (offset + size + page_size-1) / page_size;
72767afd6cd99439a4d93fcba1621bfcac5e791cTimo Sirainen /* tell operating system that we don't need the memory anymore
72767afd6cd99439a4d93fcba1621bfcac5e791cTimo Sirainen and it may free it. don't bother to do it for single pages,
72767afd6cd99439a4d93fcba1621bfcac5e791cTimo Sirainen there's a good chance that they get re-read back
72767afd6cd99439a4d93fcba1621bfcac5e791cTimo Sirainen immediately. */
72767afd6cd99439a4d93fcba1621bfcac5e791cTimo Sirainen (void)madvise(PTR_OFFSET(cache->mmap_base, offset * page_size),
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen bits = buffer_get_space_unsafe(cache->page_bitmask, offset / CHAR_BIT,
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* set the first byte */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen for (i = offset % CHAR_BIT, mask = 0; i < CHAR_BIT && size > 0; i++) {
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* set the middle bytes */
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen /* set the last byte */