diff options
author | Kyle McMartin <kyle@parisc-linux.org> | 2007-02-10 04:46:00 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-11 13:51:32 -0500 |
commit | d4d23add3abcd18d8021b99f230df608ccb2f007 (patch) | |
tree | 756c5a7d21a9f5a25f10bfcec40c01aecc596c2f /kernel | |
parent | 72fd4a35a824331d7a0f4168d7576502d95d34b3 (diff) |
[PATCH] Common compat_sys_sysinfo
I noticed that almost all architectures implemented exactly the same
sys32_sysinfo... except parisc, where a bug was to be found in handling of
the uptime. So let's remove a whole whack of code for fun and profit.
Cribbed compat_sys_sysinfo from x86_64's implementation, since I figured it
would be the best tested.
This patch incorporates Arnd's suggestion of not using set_fs/get_fs, but
instead extracting out the common code from sys_sysinfo.
Cc: Christoph Hellwig <hch@infradead.org>
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/compat.c | 66 | ||||
-rw-r--r-- | kernel/timer.c | 58 |
2 files changed, 99 insertions, 25 deletions
diff --git a/kernel/compat.c b/kernel/compat.c index 6952dd057300..cebb4c28c039 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
@@ -1016,3 +1016,69 @@ asmlinkage long compat_sys_migrate_pages(compat_pid_t pid, | |||
1016 | return sys_migrate_pages(pid, nr_bits + 1, old, new); | 1016 | return sys_migrate_pages(pid, nr_bits + 1, old, new); |
1017 | } | 1017 | } |
1018 | #endif | 1018 | #endif |
1019 | |||
1020 | struct compat_sysinfo { | ||
1021 | s32 uptime; | ||
1022 | u32 loads[3]; | ||
1023 | u32 totalram; | ||
1024 | u32 freeram; | ||
1025 | u32 sharedram; | ||
1026 | u32 bufferram; | ||
1027 | u32 totalswap; | ||
1028 | u32 freeswap; | ||
1029 | u16 procs; | ||
1030 | u16 pad; | ||
1031 | u32 totalhigh; | ||
1032 | u32 freehigh; | ||
1033 | u32 mem_unit; | ||
1034 | char _f[20-2*sizeof(u32)-sizeof(int)]; | ||
1035 | }; | ||
1036 | |||
1037 | asmlinkage long | ||
1038 | compat_sys_sysinfo(struct compat_sysinfo __user *info) | ||
1039 | { | ||
1040 | struct sysinfo s; | ||
1041 | |||
1042 | do_sysinfo(&s); | ||
1043 | |||
1044 | /* Check to see if any memory value is too large for 32-bit and scale | ||
1045 | * down if needed | ||
1046 | */ | ||
1047 | if ((s.totalram >> 32) || (s.totalswap >> 32)) { | ||
1048 | int bitcount = 0; | ||
1049 | |||
1050 | while (s.mem_unit < PAGE_SIZE) { | ||
1051 | s.mem_unit <<= 1; | ||
1052 | bitcount++; | ||
1053 | } | ||
1054 | |||
1055 | s.totalram >>= bitcount; | ||
1056 | s.freeram >>= bitcount; | ||
1057 | s.sharedram >>= bitcount; | ||
1058 | s.bufferram >>= bitcount; | ||
1059 | s.totalswap >>= bitcount; | ||
1060 | s.freeswap >>= bitcount; | ||
1061 | s.totalhigh >>= bitcount; | ||
1062 | s.freehigh >>= bitcount; | ||
1063 | } | ||
1064 | |||
1065 | if (!access_ok(VERIFY_WRITE, info, sizeof(struct compat_sysinfo)) || | ||
1066 | __put_user (s.uptime, &info->uptime) || | ||
1067 | __put_user (s.loads[0], &info->loads[0]) || | ||
1068 | __put_user (s.loads[1], &info->loads[1]) || | ||
1069 | __put_user (s.loads[2], &info->loads[2]) || | ||
1070 | __put_user (s.totalram, &info->totalram) || | ||
1071 | __put_user (s.freeram, &info->freeram) || | ||
1072 | __put_user (s.sharedram, &info->sharedram) || | ||
1073 | __put_user (s.bufferram, &info->bufferram) || | ||
1074 | __put_user (s.totalswap, &info->totalswap) || | ||
1075 | __put_user (s.freeswap, &info->freeswap) || | ||
1076 | __put_user (s.procs, &info->procs) || | ||
1077 | __put_user (s.totalhigh, &info->totalhigh) || | ||
1078 | __put_user (s.freehigh, &info->freehigh) || | ||
1079 | __put_user (s.mem_unit, &info->mem_unit)) | ||
1080 | return -EFAULT; | ||
1081 | |||
1082 | return 0; | ||
1083 | } | ||
1084 | |||
diff --git a/kernel/timer.c b/kernel/timer.c index 31ab627df8a0..8533c3796082 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -1392,17 +1392,16 @@ asmlinkage long sys_gettid(void) | |||
1392 | } | 1392 | } |
1393 | 1393 | ||
1394 | /** | 1394 | /** |
1395 | * sys_sysinfo - fill in sysinfo struct | 1395 | * do_sysinfo - fill in sysinfo struct |
1396 | * @info: pointer to buffer to fill | 1396 | * @info: pointer to buffer to fill |
1397 | */ | 1397 | */ |
1398 | asmlinkage long sys_sysinfo(struct sysinfo __user *info) | 1398 | int do_sysinfo(struct sysinfo *info) |
1399 | { | 1399 | { |
1400 | struct sysinfo val; | ||
1401 | unsigned long mem_total, sav_total; | 1400 | unsigned long mem_total, sav_total; |
1402 | unsigned int mem_unit, bitcount; | 1401 | unsigned int mem_unit, bitcount; |
1403 | unsigned long seq; | 1402 | unsigned long seq; |
1404 | 1403 | ||
1405 | memset((char *)&val, 0, sizeof(struct sysinfo)); | 1404 | memset(info, 0, sizeof(struct sysinfo)); |
1406 | 1405 | ||
1407 | do { | 1406 | do { |
1408 | struct timespec tp; | 1407 | struct timespec tp; |
@@ -1422,17 +1421,17 @@ asmlinkage long sys_sysinfo(struct sysinfo __user *info) | |||
1422 | tp.tv_nsec = tp.tv_nsec - NSEC_PER_SEC; | 1421 | tp.tv_nsec = tp.tv_nsec - NSEC_PER_SEC; |
1423 | tp.tv_sec++; | 1422 | tp.tv_sec++; |
1424 | } | 1423 | } |
1425 | val.uptime = tp.tv_sec + (tp.tv_nsec ? 1 : 0); | 1424 | info->uptime = tp.tv_sec + (tp.tv_nsec ? 1 : 0); |
1426 | 1425 | ||
1427 | val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT); | 1426 | info->loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT); |
1428 | val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT); | 1427 | info->loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT); |
1429 | val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT); | 1428 | info->loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT); |
1430 | 1429 | ||
1431 | val.procs = nr_threads; | 1430 | info->procs = nr_threads; |
1432 | } while (read_seqretry(&xtime_lock, seq)); | 1431 | } while (read_seqretry(&xtime_lock, seq)); |
1433 | 1432 | ||
1434 | si_meminfo(&val); | 1433 | si_meminfo(info); |
1435 | si_swapinfo(&val); | 1434 | si_swapinfo(info); |
1436 | 1435 | ||
1437 | /* | 1436 | /* |
1438 | * If the sum of all the available memory (i.e. ram + swap) | 1437 | * If the sum of all the available memory (i.e. ram + swap) |
@@ -1443,11 +1442,11 @@ asmlinkage long sys_sysinfo(struct sysinfo __user *info) | |||
1443 | * -Erik Andersen <andersee@debian.org> | 1442 | * -Erik Andersen <andersee@debian.org> |
1444 | */ | 1443 | */ |
1445 | 1444 | ||
1446 | mem_total = val.totalram + val.totalswap; | 1445 | mem_total = info->totalram + info->totalswap; |
1447 | if (mem_total < val.totalram || mem_total < val.totalswap) | 1446 | if (mem_total < info->totalram || mem_total < info->totalswap) |
1448 | goto out; | 1447 | goto out; |
1449 | bitcount = 0; | 1448 | bitcount = 0; |
1450 | mem_unit = val.mem_unit; | 1449 | mem_unit = info->mem_unit; |
1451 | while (mem_unit > 1) { | 1450 | while (mem_unit > 1) { |
1452 | bitcount++; | 1451 | bitcount++; |
1453 | mem_unit >>= 1; | 1452 | mem_unit >>= 1; |
@@ -1459,22 +1458,31 @@ asmlinkage long sys_sysinfo(struct sysinfo __user *info) | |||
1459 | 1458 | ||
1460 | /* | 1459 | /* |
1461 | * If mem_total did not overflow, multiply all memory values by | 1460 | * If mem_total did not overflow, multiply all memory values by |
1462 | * val.mem_unit and set it to 1. This leaves things compatible | 1461 | * info->mem_unit and set it to 1. This leaves things compatible |
1463 | * with 2.2.x, and also retains compatibility with earlier 2.4.x | 1462 | * with 2.2.x, and also retains compatibility with earlier 2.4.x |
1464 | * kernels... | 1463 | * kernels... |
1465 | */ | 1464 | */ |
1466 | 1465 | ||
1467 | val.mem_unit = 1; | 1466 | info->mem_unit = 1; |
1468 | val.totalram <<= bitcount; | 1467 | info->totalram <<= bitcount; |
1469 | val.freeram <<= bitcount; | 1468 | info->freeram <<= bitcount; |
1470 | val.sharedram <<= bitcount; | 1469 | info->sharedram <<= bitcount; |
1471 | val.bufferram <<= bitcount; | 1470 | info->bufferram <<= bitcount; |
1472 | val.totalswap <<= bitcount; | 1471 | info->totalswap <<= bitcount; |
1473 | val.freeswap <<= bitcount; | 1472 | info->freeswap <<= bitcount; |
1474 | val.totalhigh <<= bitcount; | 1473 | info->totalhigh <<= bitcount; |
1475 | val.freehigh <<= bitcount; | 1474 | info->freehigh <<= bitcount; |
1475 | |||
1476 | out: | ||
1477 | return 0; | ||
1478 | } | ||
1479 | |||
1480 | asmlinkage long sys_sysinfo(struct sysinfo __user *info) | ||
1481 | { | ||
1482 | struct sysinfo val; | ||
1483 | |||
1484 | do_sysinfo(&val); | ||
1476 | 1485 | ||
1477 | out: | ||
1478 | if (copy_to_user(info, &val, sizeof(struct sysinfo))) | 1486 | if (copy_to_user(info, &val, sizeof(struct sysinfo))) |
1479 | return -EFAULT; | 1487 | return -EFAULT; |
1480 | 1488 | ||