aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/power
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2011-12-27 16:54:52 -0500
committerRafael J. Wysocki <rjw@sisk.pl>2012-01-04 18:05:55 -0500
commitc336078bf65c4d38caa9a4b8b7b7261c778e622c (patch)
tree607e18f9f5e60ad370e7c0ed7c13c665af04b7e8 /kernel/power
parent90363ddf0a1a4dccfbb8d0c10b8f488bc7fa69f8 (diff)
PM / Hibernate: Implement compat_ioctl for /dev/snapshot
This allows uswsusp built for i386 to run on an x86_64 kernel (tested with Debian package version 1.0+20110509-2). References: http://bugs.debian.org/502816 Signed-off-by: Ben Hutchings <ben@decadent.org.uk> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'kernel/power')
-rw-r--r--kernel/power/user.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 78bdb4404aab..6b1ab7a88522 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -21,6 +21,7 @@
21#include <linux/swapops.h> 21#include <linux/swapops.h>
22#include <linux/pm.h> 22#include <linux/pm.h>
23#include <linux/fs.h> 23#include <linux/fs.h>
24#include <linux/compat.h>
24#include <linux/console.h> 25#include <linux/console.h>
25#include <linux/cpu.h> 26#include <linux/cpu.h>
26#include <linux/freezer.h> 27#include <linux/freezer.h>
@@ -380,6 +381,66 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
380 return error; 381 return error;
381} 382}
382 383
384#ifdef CONFIG_COMPAT
385
386struct compat_resume_swap_area {
387 compat_loff_t offset;
388 u32 dev;
389} __packed;
390
391static long
392snapshot_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
393{
394 BUILD_BUG_ON(sizeof(loff_t) != sizeof(compat_loff_t));
395
396 switch (cmd) {
397 case SNAPSHOT_GET_IMAGE_SIZE:
398 case SNAPSHOT_AVAIL_SWAP_SIZE:
399 case SNAPSHOT_ALLOC_SWAP_PAGE: {
400 compat_loff_t __user *uoffset = compat_ptr(arg);
401 loff_t offset;
402 mm_segment_t old_fs;
403 int err;
404
405 old_fs = get_fs();
406 set_fs(KERNEL_DS);
407 err = snapshot_ioctl(file, cmd, (unsigned long) &offset);
408 set_fs(old_fs);
409 if (!err && put_user(offset, uoffset))
410 err = -EFAULT;
411 return err;
412 }
413
414 case SNAPSHOT_CREATE_IMAGE:
415 return snapshot_ioctl(file, cmd,
416 (unsigned long) compat_ptr(arg));
417
418 case SNAPSHOT_SET_SWAP_AREA: {
419 struct compat_resume_swap_area __user *u_swap_area =
420 compat_ptr(arg);
421 struct resume_swap_area swap_area;
422 mm_segment_t old_fs;
423 int err;
424
425 err = get_user(swap_area.offset, &u_swap_area->offset);
426 err |= get_user(swap_area.dev, &u_swap_area->dev);
427 if (err)
428 return -EFAULT;
429 old_fs = get_fs();
430 set_fs(KERNEL_DS);
431 err = snapshot_ioctl(file, SNAPSHOT_SET_SWAP_AREA,
432 (unsigned long) &swap_area);
433 set_fs(old_fs);
434 return err;
435 }
436
437 default:
438 return snapshot_ioctl(file, cmd, arg);
439 }
440}
441
442#endif /* CONFIG_COMPAT */
443
383static const struct file_operations snapshot_fops = { 444static const struct file_operations snapshot_fops = {
384 .open = snapshot_open, 445 .open = snapshot_open,
385 .release = snapshot_release, 446 .release = snapshot_release,
@@ -387,6 +448,9 @@ static const struct file_operations snapshot_fops = {
387 .write = snapshot_write, 448 .write = snapshot_write,
388 .llseek = no_llseek, 449 .llseek = no_llseek,
389 .unlocked_ioctl = snapshot_ioctl, 450 .unlocked_ioctl = snapshot_ioctl,
451#ifdef CONFIG_COMPAT
452 .compat_ioctl = snapshot_compat_ioctl,
453#endif
390}; 454};
391 455
392static struct miscdevice snapshot_device = { 456static struct miscdevice snapshot_device = {