0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/suspend.h>
0011 #include <linux/reboot.h>
0012 #include <linux/string.h>
0013 #include <linux/device.h>
0014 #include <linux/miscdevice.h>
0015 #include <linux/mm.h>
0016 #include <linux/swap.h>
0017 #include <linux/swapops.h>
0018 #include <linux/pm.h>
0019 #include <linux/fs.h>
0020 #include <linux/compat.h>
0021 #include <linux/console.h>
0022 #include <linux/cpu.h>
0023 #include <linux/freezer.h>
0024
0025 #include <linux/uaccess.h>
0026
0027 #include "power.h"
0028
0029 static bool need_wait;
0030
0031 static struct snapshot_data {
0032 struct snapshot_handle handle;
0033 int swap;
0034 int mode;
0035 bool frozen;
0036 bool ready;
0037 bool platform_support;
0038 bool free_bitmaps;
0039 dev_t dev;
0040 } snapshot_state;
0041
0042 int is_hibernate_resume_dev(dev_t dev)
0043 {
0044 return hibernation_available() && snapshot_state.dev == dev;
0045 }
0046
0047 static int snapshot_open(struct inode *inode, struct file *filp)
0048 {
0049 struct snapshot_data *data;
0050 int error;
0051
0052 if (!hibernation_available())
0053 return -EPERM;
0054
0055 lock_system_sleep();
0056
0057 if (!hibernate_acquire()) {
0058 error = -EBUSY;
0059 goto Unlock;
0060 }
0061
0062 if ((filp->f_flags & O_ACCMODE) == O_RDWR) {
0063 hibernate_release();
0064 error = -ENOSYS;
0065 goto Unlock;
0066 }
0067 nonseekable_open(inode, filp);
0068 data = &snapshot_state;
0069 filp->private_data = data;
0070 memset(&data->handle, 0, sizeof(struct snapshot_handle));
0071 if ((filp->f_flags & O_ACCMODE) == O_RDONLY) {
0072
0073 data->swap = swap_type_of(swsusp_resume_device, 0);
0074 data->mode = O_RDONLY;
0075 data->free_bitmaps = false;
0076 error = pm_notifier_call_chain_robust(PM_HIBERNATION_PREPARE, PM_POST_HIBERNATION);
0077 } else {
0078
0079
0080
0081
0082 need_wait = true;
0083
0084 data->swap = -1;
0085 data->mode = O_WRONLY;
0086 error = pm_notifier_call_chain_robust(PM_RESTORE_PREPARE, PM_POST_RESTORE);
0087 if (!error) {
0088 error = create_basic_memory_bitmaps();
0089 data->free_bitmaps = !error;
0090 }
0091 }
0092 if (error)
0093 hibernate_release();
0094
0095 data->frozen = false;
0096 data->ready = false;
0097 data->platform_support = false;
0098 data->dev = 0;
0099
0100 Unlock:
0101 unlock_system_sleep();
0102
0103 return error;
0104 }
0105
0106 static int snapshot_release(struct inode *inode, struct file *filp)
0107 {
0108 struct snapshot_data *data;
0109
0110 lock_system_sleep();
0111
0112 swsusp_free();
0113 data = filp->private_data;
0114 data->dev = 0;
0115 free_all_swap_pages(data->swap);
0116 if (data->frozen) {
0117 pm_restore_gfp_mask();
0118 free_basic_memory_bitmaps();
0119 thaw_processes();
0120 } else if (data->free_bitmaps) {
0121 free_basic_memory_bitmaps();
0122 }
0123 pm_notifier_call_chain(data->mode == O_RDONLY ?
0124 PM_POST_HIBERNATION : PM_POST_RESTORE);
0125 hibernate_release();
0126
0127 unlock_system_sleep();
0128
0129 return 0;
0130 }
0131
0132 static ssize_t snapshot_read(struct file *filp, char __user *buf,
0133 size_t count, loff_t *offp)
0134 {
0135 struct snapshot_data *data;
0136 ssize_t res;
0137 loff_t pg_offp = *offp & ~PAGE_MASK;
0138
0139 lock_system_sleep();
0140
0141 data = filp->private_data;
0142 if (!data->ready) {
0143 res = -ENODATA;
0144 goto Unlock;
0145 }
0146 if (!pg_offp) {
0147 res = snapshot_read_next(&data->handle);
0148 if (res <= 0)
0149 goto Unlock;
0150 } else {
0151 res = PAGE_SIZE - pg_offp;
0152 }
0153
0154 res = simple_read_from_buffer(buf, count, &pg_offp,
0155 data_of(data->handle), res);
0156 if (res > 0)
0157 *offp += res;
0158
0159 Unlock:
0160 unlock_system_sleep();
0161
0162 return res;
0163 }
0164
0165 static ssize_t snapshot_write(struct file *filp, const char __user *buf,
0166 size_t count, loff_t *offp)
0167 {
0168 struct snapshot_data *data;
0169 ssize_t res;
0170 loff_t pg_offp = *offp & ~PAGE_MASK;
0171
0172 if (need_wait) {
0173 wait_for_device_probe();
0174 need_wait = false;
0175 }
0176
0177 lock_system_sleep();
0178
0179 data = filp->private_data;
0180
0181 if (!pg_offp) {
0182 res = snapshot_write_next(&data->handle);
0183 if (res <= 0)
0184 goto unlock;
0185 } else {
0186 res = PAGE_SIZE;
0187 }
0188
0189 if (!data_of(data->handle)) {
0190 res = -EINVAL;
0191 goto unlock;
0192 }
0193
0194 res = simple_write_to_buffer(data_of(data->handle), res, &pg_offp,
0195 buf, count);
0196 if (res > 0)
0197 *offp += res;
0198 unlock:
0199 unlock_system_sleep();
0200
0201 return res;
0202 }
0203
0204 struct compat_resume_swap_area {
0205 compat_loff_t offset;
0206 u32 dev;
0207 } __packed;
0208
0209 static int snapshot_set_swap_area(struct snapshot_data *data,
0210 void __user *argp)
0211 {
0212 sector_t offset;
0213 dev_t swdev;
0214
0215 if (swsusp_swap_in_use())
0216 return -EPERM;
0217
0218 if (in_compat_syscall()) {
0219 struct compat_resume_swap_area swap_area;
0220
0221 if (copy_from_user(&swap_area, argp, sizeof(swap_area)))
0222 return -EFAULT;
0223 swdev = new_decode_dev(swap_area.dev);
0224 offset = swap_area.offset;
0225 } else {
0226 struct resume_swap_area swap_area;
0227
0228 if (copy_from_user(&swap_area, argp, sizeof(swap_area)))
0229 return -EFAULT;
0230 swdev = new_decode_dev(swap_area.dev);
0231 offset = swap_area.offset;
0232 }
0233
0234
0235
0236
0237
0238 data->swap = swap_type_of(swdev, offset);
0239 if (data->swap < 0)
0240 return swdev ? -ENODEV : -EINVAL;
0241 data->dev = swdev;
0242 return 0;
0243 }
0244
0245 static long snapshot_ioctl(struct file *filp, unsigned int cmd,
0246 unsigned long arg)
0247 {
0248 int error = 0;
0249 struct snapshot_data *data;
0250 loff_t size;
0251 sector_t offset;
0252
0253 if (need_wait) {
0254 wait_for_device_probe();
0255 need_wait = false;
0256 }
0257
0258 if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC)
0259 return -ENOTTY;
0260 if (_IOC_NR(cmd) > SNAPSHOT_IOC_MAXNR)
0261 return -ENOTTY;
0262 if (!capable(CAP_SYS_ADMIN))
0263 return -EPERM;
0264
0265 if (!mutex_trylock(&system_transition_mutex))
0266 return -EBUSY;
0267
0268 lock_device_hotplug();
0269 data = filp->private_data;
0270
0271 switch (cmd) {
0272
0273 case SNAPSHOT_FREEZE:
0274 if (data->frozen)
0275 break;
0276
0277 ksys_sync_helper();
0278
0279 error = freeze_processes();
0280 if (error)
0281 break;
0282
0283 error = create_basic_memory_bitmaps();
0284 if (error)
0285 thaw_processes();
0286 else
0287 data->frozen = true;
0288
0289 break;
0290
0291 case SNAPSHOT_UNFREEZE:
0292 if (!data->frozen || data->ready)
0293 break;
0294 pm_restore_gfp_mask();
0295 free_basic_memory_bitmaps();
0296 data->free_bitmaps = false;
0297 thaw_processes();
0298 data->frozen = false;
0299 break;
0300
0301 case SNAPSHOT_CREATE_IMAGE:
0302 if (data->mode != O_RDONLY || !data->frozen || data->ready) {
0303 error = -EPERM;
0304 break;
0305 }
0306 pm_restore_gfp_mask();
0307 error = hibernation_snapshot(data->platform_support);
0308 if (!error) {
0309 error = put_user(in_suspend, (int __user *)arg);
0310 data->ready = !freezer_test_done && !error;
0311 freezer_test_done = false;
0312 }
0313 break;
0314
0315 case SNAPSHOT_ATOMIC_RESTORE:
0316 snapshot_write_finalize(&data->handle);
0317 if (data->mode != O_WRONLY || !data->frozen ||
0318 !snapshot_image_loaded(&data->handle)) {
0319 error = -EPERM;
0320 break;
0321 }
0322 error = hibernation_restore(data->platform_support);
0323 break;
0324
0325 case SNAPSHOT_FREE:
0326 swsusp_free();
0327 memset(&data->handle, 0, sizeof(struct snapshot_handle));
0328 data->ready = false;
0329
0330
0331
0332
0333
0334
0335
0336
0337 thaw_kernel_threads();
0338 break;
0339
0340 case SNAPSHOT_PREF_IMAGE_SIZE:
0341 image_size = arg;
0342 break;
0343
0344 case SNAPSHOT_GET_IMAGE_SIZE:
0345 if (!data->ready) {
0346 error = -ENODATA;
0347 break;
0348 }
0349 size = snapshot_get_image_size();
0350 size <<= PAGE_SHIFT;
0351 error = put_user(size, (loff_t __user *)arg);
0352 break;
0353
0354 case SNAPSHOT_AVAIL_SWAP_SIZE:
0355 size = count_swap_pages(data->swap, 1);
0356 size <<= PAGE_SHIFT;
0357 error = put_user(size, (loff_t __user *)arg);
0358 break;
0359
0360 case SNAPSHOT_ALLOC_SWAP_PAGE:
0361 if (data->swap < 0 || data->swap >= MAX_SWAPFILES) {
0362 error = -ENODEV;
0363 break;
0364 }
0365 offset = alloc_swapdev_block(data->swap);
0366 if (offset) {
0367 offset <<= PAGE_SHIFT;
0368 error = put_user(offset, (loff_t __user *)arg);
0369 } else {
0370 error = -ENOSPC;
0371 }
0372 break;
0373
0374 case SNAPSHOT_FREE_SWAP_PAGES:
0375 if (data->swap < 0 || data->swap >= MAX_SWAPFILES) {
0376 error = -ENODEV;
0377 break;
0378 }
0379 free_all_swap_pages(data->swap);
0380 break;
0381
0382 case SNAPSHOT_S2RAM:
0383 if (!data->frozen) {
0384 error = -EPERM;
0385 break;
0386 }
0387
0388
0389
0390
0391 error = suspend_devices_and_enter(PM_SUSPEND_MEM);
0392 data->ready = false;
0393 break;
0394
0395 case SNAPSHOT_PLATFORM_SUPPORT:
0396 data->platform_support = !!arg;
0397 break;
0398
0399 case SNAPSHOT_POWER_OFF:
0400 if (data->platform_support)
0401 error = hibernation_platform_enter();
0402 break;
0403
0404 case SNAPSHOT_SET_SWAP_AREA:
0405 error = snapshot_set_swap_area(data, (void __user *)arg);
0406 break;
0407
0408 default:
0409 error = -ENOTTY;
0410
0411 }
0412
0413 unlock_device_hotplug();
0414 mutex_unlock(&system_transition_mutex);
0415
0416 return error;
0417 }
0418
0419 #ifdef CONFIG_COMPAT
0420 static long
0421 snapshot_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
0422 {
0423 BUILD_BUG_ON(sizeof(loff_t) != sizeof(compat_loff_t));
0424
0425 switch (cmd) {
0426 case SNAPSHOT_GET_IMAGE_SIZE:
0427 case SNAPSHOT_AVAIL_SWAP_SIZE:
0428 case SNAPSHOT_ALLOC_SWAP_PAGE:
0429 case SNAPSHOT_CREATE_IMAGE:
0430 case SNAPSHOT_SET_SWAP_AREA:
0431 return snapshot_ioctl(file, cmd,
0432 (unsigned long) compat_ptr(arg));
0433 default:
0434 return snapshot_ioctl(file, cmd, arg);
0435 }
0436 }
0437 #endif
0438
0439 static const struct file_operations snapshot_fops = {
0440 .open = snapshot_open,
0441 .release = snapshot_release,
0442 .read = snapshot_read,
0443 .write = snapshot_write,
0444 .llseek = no_llseek,
0445 .unlocked_ioctl = snapshot_ioctl,
0446 #ifdef CONFIG_COMPAT
0447 .compat_ioctl = snapshot_compat_ioctl,
0448 #endif
0449 };
0450
0451 static struct miscdevice snapshot_device = {
0452 .minor = SNAPSHOT_MINOR,
0453 .name = "snapshot",
0454 .fops = &snapshot_fops,
0455 };
0456
0457 static int __init snapshot_device_init(void)
0458 {
0459 return misc_register(&snapshot_device);
0460 };
0461
0462 device_initcall(snapshot_device_init);