From a8339fb5d03a93ee546c1b4313b5a8a3cca9f783 Mon Sep 17 00:00:00 2001 From: Christian Thaeter Date: Fri, 5 Mar 2010 20:53:17 +0100 Subject: [PATCH] add mmaping of exact blocks namely file headers needs to be accessed unaligned and exactly as given, this adds mmap functions to create mmap objects to do this. --- src/backend/mmap.c | 81 +++++++++++++++++++++++++++++++++++ src/backend/mmap.h | 25 ++++++++++- tests/30mmap.tests | 4 ++ tests/backend/test-filemmap.c | 19 ++++++++ 4 files changed, 128 insertions(+), 1 deletion(-) diff --git a/src/backend/mmap.c b/src/backend/mmap.c index 84869328f..37523c9f0 100644 --- a/src/backend/mmap.c +++ b/src/backend/mmap.c @@ -214,6 +214,70 @@ lumiera_mmap_init (LumieraMMap self, LumieraFile file, off_t start, size_t size) return NULL; } + +LumieraMMap +lumiera_mmap_init_exact (LumieraMMap self, LumieraFile file, off_t start, size_t size) +{ + TRACE (mmap_dbg); + + REQUIRE (self); + REQUIRE (file); + REQUIRE (start >= 0); + REQUIRE (size); + + LumieraFiledescriptor descriptor = file->descriptor; + + int fd = lumiera_file_handle_acquire (file); + TRACE (mmap_dbg, "got fd %d", fd); + if (fd == -1) + goto efile; + + if ((off_t)(start + size) > descriptor->stat.st_size) + { + /* request past the end */ + if ((descriptor->flags & O_ACCMODE) == O_RDWR) + { + /* extend file (writable) */ + if (ftruncate (fd, start+size) == -1) + { + LUMIERA_ERROR_SET (mmap, ERRNO, lumiera_filedescriptor_name (file->descriptor)); + goto etruncate; + }; + descriptor->stat.st_size = descriptor->realsize = start+size; + } + } + + TODO ("use resourcecllector here"); + void* addr = mmap (NULL, + size, + (descriptor->flags & O_ACCMODE) == O_RDONLY ? PROT_READ : PROT_READ|PROT_WRITE, + MAP_SHARED, + fd, + start); + + INFO_IF (addr==(void*)-1, mmap_dbg, "mmap failed %s", strerror (errno)); + ENSURE (errno == 0 || errno == ENOMEM, "unexpected mmap error %s", strerror (errno)); + + llist_init (&self->cachenode); + llist_init (&self->searchnode); + + self->start = start; + self->size = size; + self->address = addr; + self->refmap = NULL; + self->refcnt = 1; + lumiera_mmapcache_announce (self); + + lumiera_file_handle_release (file); + return self; + + etruncate: + efile: + lumiera_file_handle_release (file); + return NULL; +} + + LumieraMMap lumiera_mmap_new (LumieraFile file, off_t start, size_t size) { @@ -231,6 +295,23 @@ lumiera_mmap_new (LumieraFile file, off_t start, size_t size) } +LumieraMMap +lumiera_mmap_new_exact (LumieraFile file, off_t start, size_t size) +{ + TRACE (mmap_dbg); + + LumieraMMap self = lumiera_mmapcache_mmap_acquire (); + + if (lumiera_mmap_init_exact (self, file, start, size)) + return self; + else + { + lumiera_free (self); + return NULL; + } +} + + void lumiera_mmap_delete (LumieraMMap self) { diff --git a/src/backend/mmap.h b/src/backend/mmap.h index 0e4145c74..40db39294 100644 --- a/src/backend/mmap.h +++ b/src/backend/mmap.h @@ -69,14 +69,37 @@ struct lumiera_mmap_struct short* refmap; // TODO flexible array? }; - +/** + * Initialize a MMap object. + * The mmap objects are aligned and shifted by the chunksize and bias defined for the file + * @param self the mmap object to be initialized + * @param file file from which to map + * @param start offset in file which must be part of the mmaped region + * @param size minimum size after start to map + * @return self on success or NULL on error + */ LumieraMMap lumiera_mmap_init (LumieraMMap self, LumieraFile file, off_t start, size_t size); +/** + * Initialize a MMap object. + * Maps exactly the given range + * @param self the mmap object to be initialized + * @param file file from which to map + * @param start offset in file which must be part of the mmaped region + * @param size minimum size after start to map + * @return self on success or NULL on error + */ +LumieraMMap +lumiera_mmap_init_exact (LumieraMMap self, LumieraFile file, off_t start, size_t size); + LumieraMMap lumiera_mmap_new (LumieraFile file, off_t start, size_t size); +LumieraMMap +lumiera_mmap_new_exact (LumieraFile file, off_t start, size_t size); + /** * Translate a 'external' offset to a address in memory diff --git a/tests/30mmap.tests b/tests/30mmap.tests index 015691f8e..6b89b4b01 100644 --- a/tests/30mmap.tests +++ b/tests/30mmap.tests @@ -40,6 +40,10 @@ TEST "accessing file" file_access <