xmmap: inform Linux users of tuning knobs on ENOMEM
Linux users may benefit from additional information on how to avoid ENOMEM from mmap despite the system having enough RAM to accomodate them. We can't reliably unmap pack windows to work around the issue since malloc and other library routines may mmap without our knowledge. Signed-off-by: Eric Wong <e@80x24.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Eric Wong committed
Jun 30, 2021 at 00:01 UTC
dc0592941138df684770bfe800ccad6b810214c3
5 files changed
+22
-5
config.c
+2
-1
@@ -3051,7 +3051,8 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
3051
if (contents == MAP_FAILED) {
3052
if (errno == ENODEV && S_ISDIR(st.st_mode))
3053
errno = EISDIR;
3054
- error_errno(_("unable to mmap '%s'"), config_filename);
3054
+ error_errno(_("unable to mmap '%s'%s"),
3055
+ config_filename, mmap_os_err());
3056
ret = CONFIG_INVALID_FILE;
3057
contents = NULL;
3058
goto out_free;
git-compat-util.h
+1
@@ -876,6 +876,7 @@ char *xstrndup(const char *str, size_t len);
876
void *xrealloc(void *ptr, size_t size);
877
void *xcalloc(size_t nmemb, size_t size);
878
void *xmmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
879
+const char *mmap_os_err(void);
880
void *xmmap_gently(void *start, size_t length, int prot, int flags, int fd, off_t offset);
881
int xopen(const char *path, int flags, ...);
882
ssize_t xread(int fd, void *buf, size_t len);
object-file.c
+15
-1
@@ -1023,12 +1023,26 @@ void *xmmap_gently(void *start, size_t length,
1023
return ret;
1024
}
1025
1026
+const char *mmap_os_err(void)
1027
+{
1028
+ static const char blank[] = "";
1029
+#if defined(__linux__)
1030
+ if (errno == ENOMEM) {
1031
+ /* this continues an existing error message: */
1032
+ static const char enomem[] =
1033
+", check sys.vm.max_map_count and/or RLIMIT_DATA";
1034
+ return enomem;
1035
+ }
1036
+#endif /* OS-specific bits */
1037
+ return blank;
1038
+}
1039
+
1040
void *xmmap(void *start, size_t length,
1041
int prot, int flags, int fd, off_t offset)
1042
{
1043
void *ret = xmmap_gently(start, length, prot, flags, fd, offset);
1044
if (ret == MAP_FAILED)
1031
- die_errno(_("mmap failed"));
1045
+ die_errno(_("mmap failed%s"), mmap_os_err());
1046
return ret;
1047
}
1048
packfile.c
+2
-2
@@ -652,8 +652,8 @@ unsigned char *use_pack(struct packed_git *p,
652
PROT_READ, MAP_PRIVATE,
653
p->pack_fd, win->offset);
654
if (win->base == MAP_FAILED)
655
- die_errno("packfile %s cannot be mapped",
656
- p->pack_name);
655
+ die_errno(_("packfile %s cannot be mapped%s"),
656
+ p->pack_name, mmap_os_err());
657
if (!win->offset && win->len == p->pack_size
658
&& !p->do_not_close)
659
close_pack_fd(p);
read-cache.c
+2
-1
@@ -2236,7 +2236,8 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
2236
2237
mmap = xmmap_gently(NULL, mmap_size, PROT_READ, MAP_PRIVATE, fd, 0);
2238
if (mmap == MAP_FAILED)
2239
- die_errno(_("%s: unable to map index file"), path);
2239
+ die_errno(_("%s: unable to map index file%s"), path,
2240
+ mmap_os_err());
2241
close(fd);
2242
2243
hdr = (const struct cache_header *)mmap;