PM: hibernate: Incorporate concurrency handling
Hibernation concurrency handling is currently delegated to user.c, where it's also used for regulating the access to the snapshot device. In the prospective of making user.c a separate configuration option, such mutual exclusion is brought into hibernate.c and made available through accessor helpers hereby introduced. Signed-off-by: Domenico Andreoli <domenico.andreoli@linux.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
3a4ccdb92e
commit
ab7e9b067f
3 changed files with 22 additions and 12 deletions
|
@ -67,6 +67,18 @@ bool freezer_test_done;
|
|||
|
||||
static const struct platform_hibernation_ops *hibernation_ops;
|
||||
|
||||
static atomic_t hibernate_atomic = ATOMIC_INIT(1);
|
||||
|
||||
bool hibernate_acquire(void)
|
||||
{
|
||||
return atomic_add_unless(&hibernate_atomic, -1, 0);
|
||||
}
|
||||
|
||||
void hibernate_release(void)
|
||||
{
|
||||
atomic_inc(&hibernate_atomic);
|
||||
}
|
||||
|
||||
bool hibernation_available(void)
|
||||
{
|
||||
return nohibernate == 0 && !security_locked_down(LOCKDOWN_HIBERNATION);
|
||||
|
@ -704,7 +716,7 @@ int hibernate(void)
|
|||
|
||||
lock_system_sleep();
|
||||
/* The snapshot device should not be opened while we're running */
|
||||
if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
|
||||
if (!hibernate_acquire()) {
|
||||
error = -EBUSY;
|
||||
goto Unlock;
|
||||
}
|
||||
|
@ -775,7 +787,7 @@ int hibernate(void)
|
|||
Exit:
|
||||
__pm_notifier_call_chain(PM_POST_HIBERNATION, nr_calls, NULL);
|
||||
pm_restore_console();
|
||||
atomic_inc(&snapshot_device_available);
|
||||
hibernate_release();
|
||||
Unlock:
|
||||
unlock_system_sleep();
|
||||
pr_info("hibernation exit\n");
|
||||
|
@ -880,7 +892,7 @@ static int software_resume(void)
|
|||
goto Unlock;
|
||||
|
||||
/* The snapshot device should not be opened while we're running */
|
||||
if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
|
||||
if (!hibernate_acquire()) {
|
||||
error = -EBUSY;
|
||||
swsusp_close(FMODE_READ);
|
||||
goto Unlock;
|
||||
|
@ -911,7 +923,7 @@ static int software_resume(void)
|
|||
__pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL);
|
||||
pm_restore_console();
|
||||
pr_info("resume failed (%d)\n", error);
|
||||
atomic_inc(&snapshot_device_available);
|
||||
hibernate_release();
|
||||
/* For success case, the suspend path will release the lock */
|
||||
Unlock:
|
||||
mutex_unlock(&system_transition_mutex);
|
||||
|
|
|
@ -154,8 +154,8 @@ extern int snapshot_write_next(struct snapshot_handle *handle);
|
|||
extern void snapshot_write_finalize(struct snapshot_handle *handle);
|
||||
extern int snapshot_image_loaded(struct snapshot_handle *handle);
|
||||
|
||||
/* If unset, the snapshot device cannot be open. */
|
||||
extern atomic_t snapshot_device_available;
|
||||
extern bool hibernate_acquire(void);
|
||||
extern void hibernate_release(void);
|
||||
|
||||
extern sector_t alloc_swapdev_block(int swap);
|
||||
extern void free_all_swap_pages(int swap);
|
||||
|
|
|
@ -37,8 +37,6 @@ static struct snapshot_data {
|
|||
bool free_bitmaps;
|
||||
} snapshot_state;
|
||||
|
||||
atomic_t snapshot_device_available = ATOMIC_INIT(1);
|
||||
|
||||
static int snapshot_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct snapshot_data *data;
|
||||
|
@ -49,13 +47,13 @@ static int snapshot_open(struct inode *inode, struct file *filp)
|
|||
|
||||
lock_system_sleep();
|
||||
|
||||
if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
|
||||
if (!hibernate_acquire()) {
|
||||
error = -EBUSY;
|
||||
goto Unlock;
|
||||
}
|
||||
|
||||
if ((filp->f_flags & O_ACCMODE) == O_RDWR) {
|
||||
atomic_inc(&snapshot_device_available);
|
||||
hibernate_release();
|
||||
error = -ENOSYS;
|
||||
goto Unlock;
|
||||
}
|
||||
|
@ -92,7 +90,7 @@ static int snapshot_open(struct inode *inode, struct file *filp)
|
|||
__pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL);
|
||||
}
|
||||
if (error)
|
||||
atomic_inc(&snapshot_device_available);
|
||||
hibernate_release();
|
||||
|
||||
data->frozen = false;
|
||||
data->ready = false;
|
||||
|
@ -122,7 +120,7 @@ static int snapshot_release(struct inode *inode, struct file *filp)
|
|||
}
|
||||
pm_notifier_call_chain(data->mode == O_RDONLY ?
|
||||
PM_POST_HIBERNATION : PM_POST_RESTORE);
|
||||
atomic_inc(&snapshot_device_available);
|
||||
hibernate_release();
|
||||
|
||||
unlock_system_sleep();
|
||||
|
||||
|
|
Loading…
Reference in a new issue