[Dovecot] Running on HPUX
I've gotten fairly far into compiling and running dovecot on HPUX. The problem I'm currently having is that the index seems to be mmap'ed at twice after login. The 576 byte mmap is the index file:
root@hp46t243 # grep mmap64 /tmp/dovecot.tusc [imap ][1707] mmap64(NULL, 576, PROT_READ|PROT_WRITE, MAP_SHARED, 7, 0) = 0xc166c000 [imap ][1707] mmap64(NULL, 18432, PROT_READ, MAP_SHARED, 8, 0) ........ = 0xc166d000 [imap ][1707] mmap64(NULL, 24, PROT_READ, MAP_SHARED, 9, 0) ........... = 0xc1672000 [imap ][1707] mmap64(NULL, 576, PROT_READ|PROT_WRITE, MAP_SHARED, 7, 0) ERR#12 ENOMEM [imap ][1717] mmap64(NULL, 576, PROT_READ|PROT_WRITE, MAP_SHARED, 7, 0) = 0xc166c000 [imap ][1717] mmap64(NULL, 18432, PROT_READ, MAP_SHARED, 9, 0) ........ = 0xc166d000 [imap ][1717] mmap64(NULL, 24, PROT_READ, MAP_SHARED, 8, 0) ........... = 0xc1672000 [imap ][1717] mmap64(NULL, 576, PROT_READ|PROT_WRITE, MAP_SHARED, 7, 0) ERR#12 ENOMEM [imap ][1897] mmap64(NULL, 576, PROT_READ|PROT_WRITE, MAP_SHARED, 7, 0) = 0xc166c000 [imap ][1897] mmap64(NULL, 18432, PROT_READ, MAP_SHARED, 9, 0) ........ = 0xc166d000 [imap ][1897] mmap64(NULL, 24, PROT_READ, MAP_SHARED, 8, 0) ........... = 0xc1672000 [imap ][1897] mmap64(NULL, 576, PROT_READ|PROT_WRITE, MAP_SHARED, 7, 0) ERR#12 ENOMEM [imap ][2042] mmap64(NULL, 576, PROT_READ|PROT_WRITE, MAP_SHARED, 7, 0) = 0xc166c000 [imap ][2042] mmap64(NULL, 18432, PROT_READ, MAP_SHARED, 9, 0) ........ = 0xc166d000 [imap ][2042] mmap64(NULL, 24, PROT_READ, MAP_SHARED, 8, 0) ........... = 0xc1672000 [imap ][2042] mmap64(NULL, 576, PROT_READ|PROT_WRITE, MAP_SHARED, 7, 0) ERR#12 ENOMEM [imap ][2178] mmap64(NULL, 576, PROT_READ|PROT_WRITE, MAP_SHARED, 7, 0) = 0xc166c000 [imap ][2178] mmap64(NULL, 18432, PROT_READ, MAP_SHARED, 9, 0) ........ = 0xc166d000 [imap ][2178] mmap64(NULL, 24, PROT_READ, MAP_SHARED, 8, 0) ........... = 0xc1672000 [imap ][2178] mmap64(NULL, 576, PROT_READ|PROT_WRITE, MAP_SHARED, 7, 0) ERR#12 ENOMEM [imap ][2318] mmap64(NULL, 576, PROT_READ|PROT_WRITE, MAP_SHARED, 7, 0) = 0xc166c000 [imap ][2318] mmap64(NULL, 18432, PROT_READ, MAP_SHARED, 9, 0) ........ = 0xc166d000 [imap ][2318] mmap64(NULL, 24, PROT_READ, MAP_SHARED, 8, 0) ........... = 0xc1672000 [imap ][2318] mmap64(NULL, 576, PROT_READ|PROT_WRITE, MAP_SHARED, 7, 0) ERR#12 ENOMEM root@hp46t243 #
I think multiple mmap's of the same file are verboten --
+ In most cases, two separate calls to mmap() cannot map
overlapping ranges in a file. The virtual address range
reserved for a file range is determined at the time of the
initial mapping of the file range into a process address
space. The system allocates only the virtual address range
necessary to represent the initial mapping. As long as the
initial mapping exists, subsequent attempts to map a different
file range that includes any portion of the initial range may
fail with an ENOMEM error if an extended contiguous address
range that preserves the mappings of the initial range cannot
be allocated.
So, I was trying to look at why the index file is being mapped twice,
and why the addr isn't saved and reused. I was thinking of adding it to
one of the index structures and skipping the mmap if the addr != 0.
I've been poking around for a couple of hours today and am going to call
it a day, but I thought I'd ping the list to see if there was something
obvious I was missing.
Rich
On Fri, 2006-06-23 at 16:13 -0700, Rich Rauenzahn wrote:
I think multiple mmap's of the same file are verboten --
+ In most cases, two separate calls to mmap() cannot map overlapping ranges in a file. The virtual address range reserved for a file range is determined at the time of the initial mapping of the file range into a process address space. The system allocates only the virtual address range necessary to represent the initial mapping. As long as the initial mapping exists, subsequent attempts to map a different file range that includes any portion of the initial range may fail with an ENOMEM error if an extended contiguous address range that preserves the mappings of the initial range cannot be allocated.
Well, I don't see anything like that described in Linux or UNIX98 man pages..
So, I was trying to look at why the index file is being mapped twice, and why the addr isn't saved and reused.
The problem has something to do with how index file code works internally. A "view" is (supposed to be) a snapshot of the mailbox at a given state. It's not updated until the view is synchronized. Each view points to a "map" which contains the index file's mmap pointer and other information, including records_count which tells how many messages it holds. mail_index_map() is used to get the latest mapping of the index file. If the existing latest map is already used by views, Dovecot simply discards the existing map and mmap()s the file all over again. One way to handle this would be to unmap the existing area always, mmap() it and update all the existing maps' pointer to the new one. But since the maps may have different files mmapped (the index file could have been rebuilt and the maps point to different files), it's not that simple to implement. Another workaround would be to move the map to memory and let the views use that. That would be pretty easy to implement, but if HP-UX is the only OS where this breaks, I think I'll just leave it as it is since it's faster this way.. Anyway, I think something like this should fix it (not tested): diff -u -r1.230.2.5 mail-index.c --- src/lib-index/mail-index.c 17 Jun 2006 13:42:36 -0000 1.230.2.5 +++ src/lib-index/mail-index.c 24 Jun 2006 19:35:30 -0000 @@ -1031,6 +1031,15 @@ /* this map is already used by some views and they may have pointers into it. leave them and create a new mapping. */ if (!index->mmap_disable) { + struct mail_index_map *old_map; + + old_map = index->map; + map = mail_index_map_clone(index->map, + index->map->hdr.record_size); + map->refcount = index->map->refcount; + mail_index_unmap(index, &index->map); + *old_map = *map; + i_free(map); map = NULL; } else { /* create a copy of the mapping instead so we don't
Timo Sirainen wrote:
On Fri, 2006-06-23 at 16:13 -0700, Rich Rauenzahn wrote:
I think multiple mmap's of the same file are verboten --
+ In most cases, two separate calls to mmap() cannot map overlapping ranges in a file. The virtual address range reserved for a file range is determined at the time of the initial mapping of the file range into a process address space. The system allocates only the virtual address range necessary to represent the initial mapping. As long as the initial mapping exists, subsequent attempts to map a different file range that includes any portion of the initial range may fail with an ENOMEM error if an extended contiguous address range that preserves the mappings of the initial range cannot be allocated.
Well, I don't see anything like that described in Linux or UNIX98 man pages..
I'm sure the limitation predates UNIX98 and has something to do with a non-unified buffer cache and was a design/performance tradeoff long ago. Soon we'll have a unified cache.
So, I was trying to look at why the index file is being mapped twice, and why the addr isn't saved and reused.
The problem has something to do with how index file code works internally. A "view" is (supposed to be) a snapshot of the mailbox at a given state. It's not updated until the view is synchronized. Each view points to a "map" which contains the index file's mmap pointer and other information, including records_count which tells how many messages it holds.
mail_index_map() is used to get the latest mapping of the index file. If the existing latest map is already used by views, Dovecot simply discards the existing map and mmap()s the file all over again.
I was pondering an alternate work around from the bottom, but I think there's a problem with it. I could write a mmap64_hpux that would remember the first mapping's addr (also verifies the fd against the inode #), and return the same addr again. I think the problem occurs if you want some mappings to be RO and some RW.
One way to handle this would be to unmap the existing area always, mmap() it and update all the existing maps' pointer to the new one. But since the maps may have different files mmapped (the index file could have been rebuilt and the maps point to different files), it's not that simple to implement.
Would knowing the inode# associated with the fd help? And would the RW/RO problem occur here as well?
Another workaround would be to move the map to memory and let the views use that. That would be pretty easy to implement, but if HP-UX is the only OS where this breaks, I think I'll just leave it as it is since it's faster this way..
Anyway, I think something like this should fix it (not tested):\
Which workaround is this below? Must be the 2nd. It looks like you clone/copy the older memory map, and then unmap it.
diff -u -r1.230.2.5 mail-index.c --- src/lib-index/mail-index.c 17 Jun 2006 13:42:36 -0000 1.230.2.5 +++ src/lib-index/mail-index.c 24 Jun 2006 19:35:30 -0000 @@ -1031,6 +1031,15 @@ /* this map is already used by some views and they may have pointers into it. leave them and create a new mapping. */ if (!index->mmap_disable) { + struct mail_index_map *old_map; + + old_map = index->map; + map = mail_index_map_clone(index->map, + index->map->hdr.record_size); + map->refcount = index->map->refcount; + mail_index_unmap(index, &index->map); + *old_map = *map; + i_free(map); map = NULL; } else { /* create a copy of the mapping instead so we don't
Timo Sirainen wrote:
Anyway, I think something like this should fix it (not tested):
diff -u -r1.230.2.5 mail-index.c --- src/lib-index/mail-index.c 17 Jun 2006 13:42:36 -0000 1.230.2.5 +++ src/lib-index/mail-index.c 24 Jun 2006 19:35:30 -0000 @@ -1031,6 +1031,15 @@ /* this map is already used by some views and they may have pointers into it. leave them and create a new mapping. */ if (!index->mmap_disable) { + struct mail_index_map *old_map; + + old_map = index->map; + map = mail_index_map_clone(index->map, + index->map->hdr.record_size); + map->refcount = index->map->refcount; + mail_index_unmap(index, &index->map); + *old_map = *map; + i_free(map); map = NULL; } else { /* create a copy of the mapping instead so we don't
I don't think that worked -- core dumps, but I didn't track it down. Instead I removed it and tried disabling mmap in the config file and I also tried keeping track of the inode# and device# and keeping a copy of the addr. If the mmap returned ENOSPC, I returned the old addr. That seemed to work, too. But, Thunderbird seems to be really slow with my compiled dovecot server -- When I click on a message it takes thunderbird 1.5.0.4 about 5 seconds to highlight the message. Once it is highlighted, it is displayed immediately. Is it something obvious? The log files don't show anything significant and I turned mail_debug on. Rich
Rich Rauenzahn wrote:
But, Thunderbird seems to be really slow with my compiled dovecot server -- When I click on a message it takes thunderbird 1.5.0.4 about 5 seconds to highlight the message. Once it is highlighted, it is displayed immediately. Is it something obvious? The log files don't show anything significant and I turned mail_debug on.
Fixed it. Some internal structures in Thunderbird must have been hosed from imap coredumping. Deleting and readding the account fixed it.
participants (2)
-
Rich Rauenzahn
-
Timo Sirainen