Commit ab7e9b06 authored by Domenico Andreoli's avatar Domenico Andreoli Committed by Rafael J. Wysocki
Browse files

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: default avatarDomenico Andreoli <domenico.andreoli@linux.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 3a4ccdb9
Loading
Loading
Loading
Loading
+16 −4
Original line number Diff line number Diff line
@@ -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);
+2 −2
Original line number Diff line number Diff line
@@ -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);
+4 −6
Original line number Diff line number Diff line
@@ -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();