From: Jakub Jelinek <jakub@redhat.com>
To: Ulrich Drepper <drepper@redhat.com>
Cc: Glibc hackers <libc-hacker@sources.redhat.com>
Subject: [PATCH] Fix localedef
Date: Mon, 27 Apr 2009 09:12:00 -0000 [thread overview]
Message-ID: <20090427092233.GC16681@sunsite.ms.mff.cuni.cz> (raw)
Hi!
We still have a bunch of issues in localedef:
1) MAP_ANON without MAP_PRIVATE or MAP_SHARED is MAP_FAILED/EINVAL,
so we actually never reserved anything
2) enlarge_archive, if the reserved region size isn't big enough,
now munmaps the old region and mmaps the whole file elsewhere, but
doesn't update the head pointer, which now points to the munmaped
area
3) unfortunately, it seems kernel rejects mremap MREMAP_MAYMOVE|MREMAP_FIXED
if new_addr == addr (-1/EINVAL):
/* Check if the location we're moving into overlaps the
* old location at all, and fail if it does.
*/
if ((new_addr <= addr) && (new_addr+new_len) > addr)
goto out;
if ((addr <= new_addr) && (addr+old_len) > new_addr)
goto out;
This patch fixes 1) by oring in MAP_PRIVATE, 2) by head = ah->addr,
3) by replacing mremap with mmap64 (for speed I'm just mmaping starting
at end of previous mmapping rounded down to page boundary) and in addition
to this it adds the RESERVE_MMAP_SIZE stuff to enlarge_archive, as e.g.
when --add-to-archive hundreds of locales into an empty locale-archive
this makes quite a significant difference.
2009-04-27 Jakub Jelinek <jakub@redhat.com>
* locale/programs/locarchive.c (create_archive): Add MAP_PRIVATE
to MAP_ANON in PROT_NONE mmap64 call.
(open_archive): Likewise.
(file_data_available_p): Use mmap64 instead of mremap.
(enlarge_archive): Likewise. Update head if ah->addr changed.
Attempt to reserve address space after mmap64 region.
--- libc/locale/programs/locarchive.c.jj 2009-04-27 10:44:42.000000000 +0200
+++ libc/locale/programs/locarchive.c 2009-04-27 10:45:42.000000000 +0200
@@ -134,8 +134,8 @@ create_archive (const char *archivefname
size_t reserved = RESERVE_MMAP_SIZE;
int xflags = 0;
if (total < reserved
- && ((p = mmap64 (NULL, reserved, PROT_NONE, MAP_ANON, -1, 0))
- != MAP_FAILED))
+ && ((p = mmap64 (NULL, reserved, PROT_NONE, MAP_PRIVATE | MAP_ANON,
+ -1, 0)) != MAP_FAILED))
xflags = MAP_FIXED;
else
{
@@ -259,10 +259,16 @@ file_data_available_p (struct locarhandl
if (st.st_size > ah->reserved)
return false;
- void *p = mremap (ah->addr, ah->mmaped, st.st_size,
- MREMAP_FIXED | MREMAP_MAYMOVE, ah->addr);
+ const size_t pagesz = getpagesize ();
+ size_t start = ah->mmaped & ~(pagesz - 1);
+ void *p = mmap64 (ah->addr + start, st.st_size - start,
+ PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED,
+ ah->fd, start);
if (p == MAP_FAILED)
- return false;
+ {
+ ah->mmaped = start;
+ return false;
+ }
ah->mmaped = st.st_size;
return true;
@@ -312,14 +318,15 @@ enlarge_archive (struct locarhandle *ah,
error (EXIT_FAILURE, errno, _("cannot map locale archive file"));
if (st.st_size < ah->reserved)
- ah->addr = mremap (ah->addr, ah->mmaped, st.st_size,
- MREMAP_MAYMOVE | MREMAP_FIXED, ah->addr);
+ ah->addr = mmap64 (ah->addr, st.st_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_FIXED, ah->fd, 0);
else
{
munmap (ah->addr, ah->reserved);
ah->addr = mmap64 (NULL, st.st_size, PROT_READ | PROT_WRITE,
MAP_SHARED, ah->fd, 0);
ah->reserved = st.st_size;
+ head = ah->addr;
}
if (ah->addr == MAP_FAILED)
goto enomap;
@@ -384,8 +391,22 @@ enlarge_archive (struct locarhandle *ah,
error (EXIT_FAILURE, errval, _("cannot resize archive file"));
}
+ /* To prepare for enlargements of the mmaped area reserve some
+ address space. */
+ size_t reserved = RESERVE_MMAP_SIZE;
+ int xflags = 0;
+ if (total < reserved
+ && ((p = mmap64 (NULL, reserved, PROT_NONE, MAP_PRIVATE | MAP_ANON,
+ -1, 0)) != MAP_FAILED))
+ xflags = MAP_FIXED;
+ else
+ {
+ p = NULL;
+ reserved = total;
+ }
+
/* Map the header and all the administration data structures. */
- p = mmap64 (NULL, total, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ p = mmap64 (p, total, PROT_READ | PROT_WRITE, MAP_SHARED | xflags, fd, 0);
if (p == MAP_FAILED)
{
int errval = errno;
@@ -404,7 +425,7 @@ enlarge_archive (struct locarhandle *ah,
new_ah.mmaped = total;
new_ah.addr = p;
new_ah.fd = fd;
- new_ah.reserved = total;
+ new_ah.reserved = reserved;
/* Walk through the hash name hash table to find out what data is
still referenced and transfer it into the new file. */
@@ -593,8 +614,8 @@ open_archive (struct locarhandle *ah, bo
int xflags = 0;
void *p;
if (st.st_size < reserved
- && ((p = mmap64 (NULL, RESERVE_MMAP_SIZE, PROT_NONE, MAP_ANON, -1, 0))
- != MAP_FAILED))
+ && ((p = mmap64 (NULL, reserved, PROT_NONE, MAP_PRIVATE | MAP_ANON,
+ -1, 0)) != MAP_FAILED))
xflags = MAP_FIXED;
else
{
Jakub
next reply other threads:[~2009-04-27 9:12 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-04-27 9:12 Jakub Jelinek [this message]
-- strict thread matches above, loose matches on Subject: below --
2002-10-22 7:00 Jakub Jelinek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090427092233.GC16681@sunsite.ms.mff.cuni.cz \
--to=jakub@redhat.com \
--cc=drepper@redhat.com \
--cc=libc-hacker@sources.redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).