aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sysctl.c
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-10-05 03:32:55 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2010-10-25 21:18:20 -0400
commit7e360c38abe2c70eae3ba5a8a17f17671d8b77c5 (patch)
tree319034360c667ac704bce87b1a0856657bf67e4b /kernel/sysctl.c
parentfde214d414218fb6cace35708730986bcc94fb53 (diff)
fs: allow for more than 2^31 files
Andrew, Could you please review this patch, you probably are the right guy to take it, because it crosses fs and net trees. Note : /proc/sys/fs/file-nr is a read-only file, so this patch doesnt depend on previous patch (sysctl: fix min/max handling in __do_proc_doulongvec_minmax()) Thanks ! [PATCH V4] fs: allow for more than 2^31 files Robin Holt tried to boot a 16TB system and found af_unix was overflowing a 32bit value : <quote> We were seeing a failure which prevented boot. The kernel was incapable of creating either a named pipe or unix domain socket. This comes down to a common kernel function called unix_create1() which does: atomic_inc(&unix_nr_socks); if (atomic_read(&unix_nr_socks) > 2 * get_max_files()) goto out; The function get_max_files() is a simple return of files_stat.max_files. files_stat.max_files is a signed integer and is computed in fs/file_table.c's files_init(). n = (mempages * (PAGE_SIZE / 1024)) / 10; files_stat.max_files = n; In our case, mempages (total_ram_pages) is approx 3,758,096,384 (0xe0000000). That leaves max_files at approximately 1,503,238,553. This causes 2 * get_max_files() to integer overflow. </quote> Fix is to let /proc/sys/fs/file-nr & /proc/sys/fs/file-max use long integers, and change af_unix to use an atomic_long_t instead of atomic_t. get_max_files() is changed to return an unsigned long. get_nr_files() is changed to return a long. unix_nr_socks is changed from atomic_t to atomic_long_t, while not strictly needed to address Robin problem. Before patch (on a 64bit kernel) : # echo 2147483648 >/proc/sys/fs/file-max # cat /proc/sys/fs/file-max -18446744071562067968 After patch: # echo 2147483648 >/proc/sys/fs/file-max # cat /proc/sys/fs/file-max 2147483648 # cat /proc/sys/fs/file-nr 704 0 2147483648 Reported-by: Robin Holt <holt@sgi.com> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Acked-by: David Miller <davem@davemloft.net> Reviewed-by: Robin Holt <holt@sgi.com> Tested-by: Robin Holt <holt@sgi.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel/sysctl.c')
-rw-r--r--kernel/sysctl.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 3a45c224770f..694b140852c2 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1352,16 +1352,16 @@ static struct ctl_table fs_table[] = {
1352 { 1352 {
1353 .procname = "file-nr", 1353 .procname = "file-nr",
1354 .data = &files_stat, 1354 .data = &files_stat,
1355 .maxlen = 3*sizeof(int), 1355 .maxlen = sizeof(files_stat),
1356 .mode = 0444, 1356 .mode = 0444,
1357 .proc_handler = proc_nr_files, 1357 .proc_handler = proc_nr_files,
1358 }, 1358 },
1359 { 1359 {
1360 .procname = "file-max", 1360 .procname = "file-max",
1361 .data = &files_stat.max_files, 1361 .data = &files_stat.max_files,
1362 .maxlen = sizeof(int), 1362 .maxlen = sizeof(files_stat.max_files),
1363 .mode = 0644, 1363 .mode = 0644,
1364 .proc_handler = proc_dointvec, 1364 .proc_handler = proc_doulongvec_minmax,
1365 }, 1365 },
1366 { 1366 {
1367 .procname = "nr_open", 1367 .procname = "nr_open",