user.c (9e8238020c5beba64e7ffafbb7ea0fb02fe68270) | user.c (70d932985757fbe978024db313001218e9f8fe5c) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * linux/kernel/power/user.c 4 * 5 * This file provides the user space interface for software suspend/resume. 6 * 7 * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl> 8 */ --- 21 unchanged lines hidden (view full) --- 30static struct snapshot_data { 31 struct snapshot_handle handle; 32 int swap; 33 int mode; 34 bool frozen; 35 bool ready; 36 bool platform_support; 37 bool free_bitmaps; | 1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * linux/kernel/power/user.c 4 * 5 * This file provides the user space interface for software suspend/resume. 6 * 7 * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl> 8 */ --- 21 unchanged lines hidden (view full) --- 30static struct snapshot_data { 31 struct snapshot_handle handle; 32 int swap; 33 int mode; 34 bool frozen; 35 bool ready; 36 bool platform_support; 37 bool free_bitmaps; |
38 struct inode *bd_inode; |
|
38} snapshot_state; 39 | 39} snapshot_state; 40 |
40atomic_t snapshot_device_available = ATOMIC_INIT(1); | 41int is_hibernate_resume_dev(const struct inode *bd_inode) 42{ 43 return hibernation_available() && snapshot_state.bd_inode == bd_inode; 44} |
41 42static int snapshot_open(struct inode *inode, struct file *filp) 43{ 44 struct snapshot_data *data; | 45 46static int snapshot_open(struct inode *inode, struct file *filp) 47{ 48 struct snapshot_data *data; |
45 int error, nr_calls = 0; | 49 int error; |
46 47 if (!hibernation_available()) 48 return -EPERM; 49 50 lock_system_sleep(); 51 | 50 51 if (!hibernation_available()) 52 return -EPERM; 53 54 lock_system_sleep(); 55 |
52 if (!atomic_add_unless(&snapshot_device_available, -1, 0)) { | 56 if (!hibernate_acquire()) { |
53 error = -EBUSY; 54 goto Unlock; 55 } 56 57 if ((filp->f_flags & O_ACCMODE) == O_RDWR) { | 57 error = -EBUSY; 58 goto Unlock; 59 } 60 61 if ((filp->f_flags & O_ACCMODE) == O_RDWR) { |
58 atomic_inc(&snapshot_device_available); | 62 hibernate_release(); |
59 error = -ENOSYS; 60 goto Unlock; 61 } 62 nonseekable_open(inode, filp); 63 data = &snapshot_state; 64 filp->private_data = data; 65 memset(&data->handle, 0, sizeof(struct snapshot_handle)); 66 if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { 67 /* Hibernating. The image device should be accessible. */ 68 data->swap = swsusp_resume_device ? 69 swap_type_of(swsusp_resume_device, 0, NULL) : -1; 70 data->mode = O_RDONLY; 71 data->free_bitmaps = false; | 63 error = -ENOSYS; 64 goto Unlock; 65 } 66 nonseekable_open(inode, filp); 67 data = &snapshot_state; 68 filp->private_data = data; 69 memset(&data->handle, 0, sizeof(struct snapshot_handle)); 70 if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { 71 /* Hibernating. The image device should be accessible. */ 72 data->swap = swsusp_resume_device ? 73 swap_type_of(swsusp_resume_device, 0, NULL) : -1; 74 data->mode = O_RDONLY; 75 data->free_bitmaps = false; |
72 error = __pm_notifier_call_chain(PM_HIBERNATION_PREPARE, -1, &nr_calls); 73 if (error) 74 __pm_notifier_call_chain(PM_POST_HIBERNATION, --nr_calls, NULL); | 76 error = pm_notifier_call_chain_robust(PM_HIBERNATION_PREPARE, PM_POST_HIBERNATION); |
75 } else { 76 /* 77 * Resuming. We may need to wait for the image device to 78 * appear. 79 */ 80 wait_for_device_probe(); 81 82 data->swap = -1; 83 data->mode = O_WRONLY; | 77 } else { 78 /* 79 * Resuming. We may need to wait for the image device to 80 * appear. 81 */ 82 wait_for_device_probe(); 83 84 data->swap = -1; 85 data->mode = O_WRONLY; |
84 error = __pm_notifier_call_chain(PM_RESTORE_PREPARE, -1, &nr_calls); | 86 error = pm_notifier_call_chain_robust(PM_RESTORE_PREPARE, PM_POST_RESTORE); |
85 if (!error) { 86 error = create_basic_memory_bitmaps(); 87 data->free_bitmaps = !error; | 87 if (!error) { 88 error = create_basic_memory_bitmaps(); 89 data->free_bitmaps = !error; |
88 } else 89 nr_calls--; 90 91 if (error) 92 __pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL); | 90 } |
93 } 94 if (error) | 91 } 92 if (error) |
95 atomic_inc(&snapshot_device_available); | 93 hibernate_release(); |
96 97 data->frozen = false; 98 data->ready = false; 99 data->platform_support = false; | 94 95 data->frozen = false; 96 data->ready = false; 97 data->platform_support = false; |
98 data->bd_inode = NULL; |
|
100 101 Unlock: 102 unlock_system_sleep(); 103 104 return error; 105} 106 107static int snapshot_release(struct inode *inode, struct file *filp) 108{ 109 struct snapshot_data *data; 110 111 lock_system_sleep(); 112 113 swsusp_free(); 114 data = filp->private_data; | 99 100 Unlock: 101 unlock_system_sleep(); 102 103 return error; 104} 105 106static int snapshot_release(struct inode *inode, struct file *filp) 107{ 108 struct snapshot_data *data; 109 110 lock_system_sleep(); 111 112 swsusp_free(); 113 data = filp->private_data; |
114 data->bd_inode = NULL; |
|
115 free_all_swap_pages(data->swap); 116 if (data->frozen) { 117 pm_restore_gfp_mask(); 118 free_basic_memory_bitmaps(); 119 thaw_processes(); 120 } else if (data->free_bitmaps) { 121 free_basic_memory_bitmaps(); 122 } 123 pm_notifier_call_chain(data->mode == O_RDONLY ? 124 PM_POST_HIBERNATION : PM_POST_RESTORE); | 115 free_all_swap_pages(data->swap); 116 if (data->frozen) { 117 pm_restore_gfp_mask(); 118 free_basic_memory_bitmaps(); 119 thaw_processes(); 120 } else if (data->free_bitmaps) { 121 free_basic_memory_bitmaps(); 122 } 123 pm_notifier_call_chain(data->mode == O_RDONLY ? 124 PM_POST_HIBERNATION : PM_POST_RESTORE); |
125 atomic_inc(&snapshot_device_available); | 125 hibernate_release(); |
126 127 unlock_system_sleep(); 128 129 return 0; 130} 131 132static ssize_t snapshot_read(struct file *filp, char __user *buf, 133 size_t count, loff_t *offp) --- 65 unchanged lines hidden (view full) --- 199struct compat_resume_swap_area { 200 compat_loff_t offset; 201 u32 dev; 202} __packed; 203 204static int snapshot_set_swap_area(struct snapshot_data *data, 205 void __user *argp) 206{ | 126 127 unlock_system_sleep(); 128 129 return 0; 130} 131 132static ssize_t snapshot_read(struct file *filp, char __user *buf, 133 size_t count, loff_t *offp) --- 65 unchanged lines hidden (view full) --- 199struct compat_resume_swap_area { 200 compat_loff_t offset; 201 u32 dev; 202} __packed; 203 204static int snapshot_set_swap_area(struct snapshot_data *data, 205 void __user *argp) 206{ |
207 struct block_device *bdev; |
|
207 sector_t offset; 208 dev_t swdev; 209 210 if (swsusp_swap_in_use()) 211 return -EPERM; 212 213 if (in_compat_syscall()) { 214 struct compat_resume_swap_area swap_area; --- 14 unchanged lines hidden (view full) --- 229 /* 230 * User space encodes device types as two-byte values, 231 * so we need to recode them 232 */ 233 if (!swdev) { 234 data->swap = -1; 235 return -EINVAL; 236 } | 208 sector_t offset; 209 dev_t swdev; 210 211 if (swsusp_swap_in_use()) 212 return -EPERM; 213 214 if (in_compat_syscall()) { 215 struct compat_resume_swap_area swap_area; --- 14 unchanged lines hidden (view full) --- 230 /* 231 * User space encodes device types as two-byte values, 232 * so we need to recode them 233 */ 234 if (!swdev) { 235 data->swap = -1; 236 return -EINVAL; 237 } |
237 data->swap = swap_type_of(swdev, offset, NULL); | 238 data->swap = swap_type_of(swdev, offset, &bdev); |
238 if (data->swap < 0) 239 return -ENODEV; | 239 if (data->swap < 0) 240 return -ENODEV; |
241 242 data->bd_inode = bdev->bd_inode; 243 bdput(bdev); |
|
240 return 0; 241} 242 243static long snapshot_ioctl(struct file *filp, unsigned int cmd, 244 unsigned long arg) 245{ 246 int error = 0; 247 struct snapshot_data *data; --- 208 unchanged lines hidden --- | 244 return 0; 245} 246 247static long snapshot_ioctl(struct file *filp, unsigned int cmd, 248 unsigned long arg) 249{ 250 int error = 0; 251 struct snapshot_data *data; --- 208 unchanged lines hidden --- |