PM: hibernate: Incorporate concurrency handling
authorDomenico Andreoli <domenico.andreoli@linux.com>
Thu, 7 May 2020 07:19:52 +0000 (09:19 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 19 May 2020 15:48:08 +0000 (17:48 +0200)
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>
kernel/power/hibernate.c
kernel/power/power.h
kernel/power/user.c

index 30bd28d1d418cce6d785d1b65e68f429a253845d..02ec716a492713877caa67ff51b2d83a5d495b3e 100644 (file)
@@ -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);
index 7cdc64dc237312a109aeb0b49f0e62524c183ce7..ba2094db62949446f5fca3e4f46edbc559f1cce3 100644 (file)
@@ -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);
index 7959449765d9a557822d6932e8471c02daf5653c..98548d1cf8a659122998fc10fa56f2229452279d 100644 (file)
@@ -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();