aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2004-09-07 17:47:55 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-09-07 17:47:55 -0700
commit7896d77b969382b8e6d3a587de50a05208498cb9 (patch)
treee06931e86ff30ddd9888efea2661dbe2295c9c87 /mm
parent5511cbde0d2f4cb9472a98d87d9cefc7972324f8 (diff)
downloadhistory-7896d77b969382b8e6d3a587de50a05208498cb9.tar.gz
[PATCH] ppc64: fix compat NUMA API on big endian 64bit
Switch the NUMA API to use compat_get_bitmap/compat_put_bitmap. In order to use compat_alloc_userspace instead of set_fs tricks, we have to do a few copies. This is what we are currently using on ppc64 but are willing to entertain the idea of going to a 32bit bitmap, especially considering how much hoops we have to go through to get it right in this patch. Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/mempolicy.c76
1 files changed, 69 insertions, 7 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index ea806adcda8e35..c87295c4b8d07d 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -525,20 +525,82 @@ asmlinkage long sys_get_mempolicy(int __user *policy,
}
#ifdef CONFIG_COMPAT
-/* The other functions are compatible */
+
asmlinkage long compat_get_mempolicy(int __user *policy,
- unsigned __user *nmask, unsigned maxnode,
- unsigned addr, unsigned flags)
+ compat_ulong_t __user *nmask,
+ compat_ulong_t maxnode,
+ compat_ulong_t addr, compat_ulong_t flags)
{
long err;
unsigned long __user *nm = NULL;
+ unsigned long nr_bits, alloc_size;
+ DECLARE_BITMAP(bm, MAX_NUMNODES);
+
+ nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES);
+ alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
+
if (nmask)
- nm = compat_alloc_user_space(ALIGN(maxnode-1, 64) / 8);
- err = sys_get_mempolicy(policy, nm, maxnode, addr, flags);
- if (!err && copy_in_user(nmask, nm, ALIGN(maxnode-1, 32)/8))
- err = -EFAULT;
+ nm = compat_alloc_user_space(alloc_size);
+
+ err = sys_get_mempolicy(policy, nm, nr_bits+1, addr, flags);
+
+ if (!err && nmask) {
+ err = copy_from_user(bm, nm, alloc_size);
+ /* ensure entire bitmap is zeroed */
+ err |= clear_user(nmask, ALIGN(maxnode-1, 8) / 8);
+ err |= compat_put_bitmap(nmask, bm, nr_bits);
+ }
+
return err;
}
+
+asmlinkage long compat_set_mempolicy(int mode, compat_ulong_t __user *nmask,
+ compat_ulong_t maxnode)
+{
+ long err;
+ unsigned long __user *nm = NULL;
+ unsigned long nr_bits, alloc_size;
+ DECLARE_BITMAP(bm, MAX_NUMNODES);
+
+ nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES);
+ alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
+
+ if (nmask) {
+ err = compat_get_bitmap(bm, nmask, nr_bits);
+ nm = compat_alloc_user_space(alloc_size);
+ err |= copy_to_user(nm, bm, alloc_size);
+ }
+
+ if (err)
+ return -EFAULT;
+
+ return sys_set_mempolicy(mode, nm, nr_bits+1);
+}
+
+asmlinkage long compat_mbind(compat_ulong_t start, compat_ulong_t len,
+ compat_ulong_t mode, compat_ulong_t __user *nmask,
+ compat_ulong_t maxnode, compat_ulong_t flags)
+{
+ long err;
+ unsigned long __user *nm = NULL;
+ unsigned long nr_bits, alloc_size;
+ DECLARE_BITMAP(bm, MAX_NUMNODES);
+
+ nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES);
+ alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
+
+ if (nmask) {
+ err = compat_get_bitmap(bm, nmask, nr_bits);
+ nm = compat_alloc_user_space(alloc_size);
+ err |= copy_to_user(nm, bm, alloc_size);
+ }
+
+ if (err)
+ return -EFAULT;
+
+ return sys_mbind(start, len, mode, nm, nr_bits+1, flags);
+}
+
#endif
/* Return effective policy for a VMA */