aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorKyle McMartin <kyle@parisc-linux.org>2007-02-10 04:46:00 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-11 13:51:32 -0500
commitd4d23add3abcd18d8021b99f230df608ccb2f007 (patch)
tree756c5a7d21a9f5a25f10bfcec40c01aecc596c2f /kernel
parent72fd4a35a824331d7a0f4168d7576502d95d34b3 (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.c66
-rw-r--r--kernel/timer.c58
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
1020struct 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
1037asmlinkage long
1038compat_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 */
1398asmlinkage long sys_sysinfo(struct sysinfo __user *info) 1398int 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
1476out:
1477 return 0;
1478}
1479
1480asmlinkage 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