ia64 sys32_sysinfo problem/fix

From: Gary Hade <garyhade_at_us.ibm.com>
Date: 2003-06-24 04:03:54
Greetings,
I posted the following to the new linux-ia64@vger.kernel.org 
list on 16-June before many of you were subscribed.  I haven't
seen a response yet so I'm reposting on the assumption that it 
may not have been noticed due to the mailing list transition.

sysinfo(2) called from a 32-bit application does not return
correct system information values when memory or swap exceeds
32 bits.

On a system with with 8 GB of physical memory the output 
of 32-bit and 64-bit versions of the below program is:
32-bit:
   totalram   4155506688, f7b00000, sizeof(4)
   freeram    3901259776, e8888000, sizeof(4)
   sharedram  0, 0, sizeof(4)
   bufferram  21364736, 1460000, sizeof(4)
   totalswap  1077411840, 40380000, sizeof(4)
   freeswap   1077411840, 40380000, sizeof(4)
   mem_unit   1, sizeof(4)

64-bit:
   totalram   8450473984, 1f7b00000, sizeof(8)
   freeram    8196145152, 1e8874000, sizeof(8)
   sharedram  0, 0, sizeof(8)
   bufferram  21364736, 1460000, sizeof(8)
   totalswap  1077411840, 40380000, sizeof(8)
   freeswap   1077411840, 40380000, sizeof(8)
   mem_unit   1, sizeof(4)

Note the discrepancies in the values displayed by the
32-bit application.  e.g. the totalram value indicates that 
only 4 GB of memory is present.

The additional code in the below patch scales the data to
provide more reasonable values.

32-bit:
   totalram   515776, 7dec0, sizeof(4)
   freeram    187082, 2daca, sizeof(4)
   sharedram  0, 0, sizeof(4)
   bufferram  27825, 6cb1, sizeof(4)
   totalswap  65760, 100e0, sizeof(4)
   freeswap   65760, 100e0, sizeof(4)
   mem_unit   16384, sizeof(4)

64-bit:
   totalram   8450473984, 1f7b00000, sizeof(8)
   freeram    3065069568, b6b14000, sizeof(8)
   sharedram  0, 0, sizeof(8)
   bufferram  455884800, 1b2c4000, sizeof(8)
   totalswap  1077411840, 40380000, sizeof(8)
   freeswap   1077411840, 40380000, sizeof(8)
   mem_unit   1, sizeof(4)


The patch should apply cleanly to the 2.4 ia64 bk tree.  2.5 also
needs the fix.

Thanks,
Gary

--
Gary Hade
IBM Linux Technology Center
503-578-4503  IBM T/L: 775-4503
garyhade@us.ibm.com
http://www.ibm.com/linux/ltc


#include <stdlib.h>
#include <stdio.h>
#include <sys/sysinfo.h>
#include <unistd.h>
 
int main (int argc, char *argv[])
{
    struct sysinfo sstats;
 
    sysinfo(&sstats);
    printf(" totalram   %lu, %lx, sizeof(%d)\n", sstats.totalram,
           sstats.totalram,
           sizeof(sstats.totalram));
    printf(" freeram    %lu, %lx, sizeof(%d)\n", sstats.freeram,
           sstats.freeram,
           sizeof(sstats.freeram));
    printf(" sharedram  %lu, %lx, sizeof(%d)\n", sstats.sharedram,
           sstats.sharedram,
           sizeof(sstats.sharedram));
    printf(" bufferram  %lu, %lx, sizeof(%d)\n", sstats.bufferram,
           sstats.bufferram,
           sizeof(sstats.bufferram));
    printf(" totalswap  %lu, %lx, sizeof(%d)\n", sstats.totalswap,
           sstats.totalswap,
           sizeof(sstats.totalswap));
    printf(" freeswap   %lu, %lx, sizeof(%d)\n", sstats.freeswap,
           sstats.freeswap,
           sizeof(sstats.freeswap));
    printf(" mem_unit   %u, sizeof(%d)\n", sstats.mem_unit,
           sizeof(sstats.mem_unit));
 
    return 0;
}


--- linux-ia64-2.4/arch/ia64/ia32/sys_ia32.c	Thu Jun 12 18:15:18 2003
+++ linux-ia64-2.4-sysinfofx/arch/ia64/ia32/sys_ia32.c	Thu Jun 12 18:17:59 2003
@@ -3729,10 +3729,29 @@
 	mm_segment_t old_fs = get_fs();
 	struct sysinfo s;
 	long ret, err;
+	int bitcount = 0;
 
 	set_fs(KERNEL_DS);
 	ret = sys_sysinfo(&s);
 	set_fs(old_fs);
+
+	/* Check to see if any memory value is too large for 32-bit and scale
+	 *  down if needed
+	 */
+	if ((s.totalram >> 32) || (s.totalswap >> 32)) {
+		while (s.mem_unit < PAGE_SIZE) {
+			s.mem_unit <<= 1;
+			bitcount++;
+		}
+		s.totalram >>= bitcount;
+		s.freeram >>= bitcount;
+		s.sharedram >>= bitcount;
+		s.bufferram >>= bitcount;
+		s.totalswap >>= bitcount;
+		s.freeswap >>= bitcount;
+		s.totalhigh >>= bitcount;
+		s.freehigh >>= bitcount;
+	}
 
 	if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
 		return -EFAULT;

-
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Received on Mon Jun 23 13:04:37 2003

This archive was generated by hypermail 2.1.8 : 2005-08-02 09:20:15 EST