On Fri, 23 Jun 2000, Linus Torvalds wrote:
> ... and said "It is Good. It is Bugfree".
he (the Penguin) was wrong. It is not Bugfree yet :)
Seriously, here is my fix that went into Alan Cox's tree but not in
2.4.0-test2:
> The assumption that C code:
>
>int x;
>int y;
>int z;
>
>allocates x,y,z at consecutive virtual addresses is wrong. Yet it is
>assumed when passing &nr_files in kernel/sysctl.c and saying "give me, I
>pray thee, 3 sizeof(int)". This results in garbage displayed in
>/proc/sys/fs/file-nr.
>
>To fix this, I followed (almost) the same technique as inodes_stat in
>fs/inode.c, i.e. gathered variables in a structure called files_stat.
>
>Tested under 2.3.99-pre10-3 (aka 2.4.0-test1)
Now, tested under 2.4.0-test2.
Thanks,
Tigran
PS. 2.4.0-test2 has a much more serious bug than this - xterm coredumps
when trying to:
open("/lib/libc.so.6", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=4101324, ...}) = 0
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\210\212"...,
4096) = 4096
old_mmap(NULL, 1001564, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) =
0x4001f000
mprotect(0x4010c000, 30812, PROT_NONE) = 0
old_mmap(0x4010c000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED,
3, 0xec000) = 0x4010c000
old_mmap(0x40110000, 14428, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40110000
close(3) = 0
mprotect(0x4001f000, 970752, PROT_READ|PROT_WRITE) = 0
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +++
so I quickly typed this email in rxvt and now back to 2.4.0-test1-ac18
which worked faithfully for me for ages...
-----------------------------------------------------------------------------
diff -urN -X dontdiff linux/fs/file_table.c work/fs/file_table.c
--- linux/fs/file_table.c Sat Jun 24 12:44:28 2000
+++ work/fs/file_table.c Sat Jun 24 12:57:25 2000
@@ -16,9 +16,7 @@
static kmem_cache_t *filp_cache;
/* sysctl tunables... */
-int nr_files; /* read only */
-int nr_free_files; /* read only */
-int max_files = NR_FILE;/* tunable */
+struct files_stat_struct files_stat = {0, 0, NR_FILE};
/* Here the new files go */
static LIST_HEAD(anon_list);
@@ -53,11 +51,11 @@
struct file * f;
file_list_lock();
- if (nr_free_files > NR_RESERVED_FILES) {
+ if (files_stat.nr_free_files > NR_RESERVED_FILES) {
used_one:
f = list_entry(free_list.next, struct file, f_list);
list_del(&f->f_list);
- nr_free_files--;
+ files_stat.nr_free_files--;
new_one:
file_list_unlock();
memset(f, 0, sizeof(*f));
@@ -73,25 +71,25 @@
/*
* Use a reserved one if we're the superuser
*/
- if (nr_free_files && !current->euid)
+ if (files_stat.nr_free_files && !current->euid)
goto used_one;
/*
* Allocate a new one if we're below the limit.
*/
- if (nr_files < max_files) {
+ if (files_stat.nr_files < files_stat.max_files) {
file_list_unlock();
f = kmem_cache_alloc(filp_cache, SLAB_KERNEL);
file_list_lock();
if (f) {
- nr_files++;
+ files_stat.nr_files++;
goto new_one;
}
/* Big problems... */
printk("VFS: filp allocation failed\n");
- } else if (max_files > old_max) {
- printk("VFS: file-max limit %d reached\n", max_files);
- old_max = max_files;
+ } else if (files_stat.max_files > old_max) {
+ printk("VFS: file-max limit %d reached\n", files_stat.max_files);
+ old_max = files_stat.max_files;
}
file_list_unlock();
return NULL;
@@ -148,7 +146,7 @@
file_list_lock();
list_del(&file->f_list);
list_add(&file->f_list, &free_list);
- nr_free_files++;
+ files_stat.nr_free_files++;
file_list_unlock();
}
@@ -160,7 +158,7 @@
file_list_lock();
list_del(&file->f_list);
list_add(&file->f_list, &free_list);
- nr_free_files++;
+ files_stat.nr_free_files++;
file_list_unlock();
}
}
diff -urN -X dontdiff linux/include/linux/fs.h work/include/linux/fs.h
--- linux/include/linux/fs.h Sat Jun 24 12:44:28 2000
+++ work/include/linux/fs.h Sat Jun 24 12:57:25 2000
@@ -47,7 +47,12 @@
#define BLOCK_SIZE (1<<BLOCK_SIZE_BITS)
/* And dynamically-tunable limits and defaults: */
-extern int max_files, nr_files, nr_free_files;
+struct files_stat_struct {
+ int nr_files; /* read only */
+ int nr_free_files; /* read only */
+ int max_files; /* tunable */
+};
+extern struct files_stat_struct files_stat;
extern int max_super_blocks, nr_super_blocks;
#define NR_FILE 8192 /* this can well be larger on a larger system */
diff -urN -X dontdiff linux/kernel/sysctl.c work/kernel/sysctl.c
--- linux/kernel/sysctl.c Sat Jun 24 12:44:28 2000
+++ work/kernel/sysctl.c Sat Jun 24 12:57:25 2000
@@ -255,9 +255,9 @@
0444, NULL, &proc_dointvec},
{FS_STATINODE, "inode-state", &inodes_stat, 7*sizeof(int),
0444, NULL, &proc_dointvec},
- {FS_NRFILE, "file-nr", &nr_files, 3*sizeof(int),
+ {FS_NRFILE, "file-nr", &files_stat, 3*sizeof(int),
0444, NULL, &proc_dointvec},
- {FS_MAXFILE, "file-max", &max_files, sizeof(int),
+ {FS_MAXFILE, "file-max", &files_stat.max_files, sizeof(int),
0644, NULL, &proc_dointvec},
{FS_NRSUPER, "super-nr", &nr_super_blocks, sizeof(int),
0444, NULL, &proc_dointvec},
diff -urN -X dontdiff linux/net/netsyms.c work/net/netsyms.c
--- linux/net/netsyms.c Sat Jun 24 12:44:28 2000
+++ work/net/netsyms.c Sat Jun 24 12:57:25 2000
@@ -196,7 +196,7 @@
/* Needed by unix.o */
EXPORT_SYMBOL(scm_fp_dup);
-EXPORT_SYMBOL(max_files);
+EXPORT_SYMBOL(files_stat);
EXPORT_SYMBOL(memcpy_toiovec);
EXPORT_SYMBOL(csum_partial);
diff -urN -X dontdiff linux/net/unix/af_unix.c work/net/unix/af_unix.c
--- linux/net/unix/af_unix.c Sat Jun 24 12:44:28 2000
+++ work/net/unix/af_unix.c Sat Jun 24 12:57:25 2000
@@ -445,7 +445,7 @@
{
struct sock *sk;
- if (atomic_read(&unix_nr_socks) >= 2*max_files)
+ if (atomic_read(&unix_nr_socks) >= 2*files_stat.max_files)
return NULL;
MOD_INC_USE_COUNT;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Mon Jun 26 2000 - 21:00:04 EST