diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2012-01-05 00:06:24 +0100 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2012-01-05 00:06:24 +0100 |
commit | c233523b3d392e530033a7587d7970dc62a02361 (patch) | |
tree | dc7df403ebc50de7c745c1904f093897c234cf18 | |
parent | 9ec23949a2d1cb2574c5ec927ccab6dc5685e5f9 (diff) | |
parent | c336078bf65c4d38caa9a4b8b7b7261c778e622c (diff) | |
download | linux-c233523b3d392e530033a7587d7970dc62a02361.tar.gz linux-c233523b3d392e530033a7587d7970dc62a02361.tar.bz2 linux-c233523b3d392e530033a7587d7970dc62a02361.zip |
Merge branch 'pm-sleep' into pm-for-linus
* pm-sleep:
PM / Hibernate: Implement compat_ioctl for /dev/snapshot
-rw-r--r-- | kernel/power/user.c | 64 |
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 @@ #include <linux/swapops.h> #include <linux/pm.h> #include <linux/fs.h> +#include <linux/compat.h> #include <linux/console.h> #include <linux/cpu.h> #include <linux/freezer.h> @@ -380,6 +381,66 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, return error; } +#ifdef CONFIG_COMPAT + +struct compat_resume_swap_area { + compat_loff_t offset; + u32 dev; +} __packed; + +static long +snapshot_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + BUILD_BUG_ON(sizeof(loff_t) != sizeof(compat_loff_t)); + + switch (cmd) { + case SNAPSHOT_GET_IMAGE_SIZE: + case SNAPSHOT_AVAIL_SWAP_SIZE: + case SNAPSHOT_ALLOC_SWAP_PAGE: { + compat_loff_t __user *uoffset = compat_ptr(arg); + loff_t offset; + mm_segment_t old_fs; + int err; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = snapshot_ioctl(file, cmd, (unsigned long) &offset); + set_fs(old_fs); + if (!err && put_user(offset, uoffset)) + err = -EFAULT; + return err; + } + + case SNAPSHOT_CREATE_IMAGE: + return snapshot_ioctl(file, cmd, + (unsigned long) compat_ptr(arg)); + + case SNAPSHOT_SET_SWAP_AREA: { + struct compat_resume_swap_area __user *u_swap_area = + compat_ptr(arg); + struct resume_swap_area swap_area; + mm_segment_t old_fs; + int err; + + err = get_user(swap_area.offset, &u_swap_area->offset); + err |= get_user(swap_area.dev, &u_swap_area->dev); + if (err) + return -EFAULT; + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = snapshot_ioctl(file, SNAPSHOT_SET_SWAP_AREA, + (unsigned long) &swap_area); + set_fs(old_fs); + return err; + } + + default: + return snapshot_ioctl(file, cmd, arg); + } +} + +#endif /* CONFIG_COMPAT */ + static const struct file_operations snapshot_fops = { .open = snapshot_open, .release = snapshot_release, @@ -387,6 +448,9 @@ static const struct file_operations snapshot_fops = { .write = snapshot_write, .llseek = no_llseek, .unlocked_ioctl = snapshot_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = snapshot_compat_ioctl, +#endif }; static struct miscdevice snapshot_device = { |