Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0709db60 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Linus Torvalds
Browse files

swsusp: use GFP_KERNEL for creating basic data structures



Make swsusp call create_basic_memory_bitmaps() before processes are frozen, so
that GFP_KERNEL allocations can be made in it.  Additionally, ensure that the
swsusp's userland interface won't be used while either pm_suspend_disk() or
software_resume() is being executed.

Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
Acked-by: default avatarPavel Machek <pavel@ucw.cz>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 1525a2ad
Loading
Loading
Loading
Loading
+26 −11
Original line number Diff line number Diff line
@@ -130,28 +130,33 @@ int pm_suspend_disk(void)
{
	int error;

	/* The snapshot device should not be opened while we're running */
	if (!atomic_add_unless(&snapshot_device_available, -1, 0))
		return -EBUSY;

	/* Allocate memory management structures */
	error = create_basic_memory_bitmaps();
	if (error)
		goto Exit;

	error = prepare_processes();
	if (error)
		return error;
		goto Finish;

	if (pm_disk_mode == PM_DISK_TESTPROC) {
		printk("swsusp debug: Waiting for 5 seconds.\n");
		mdelay(5000);
		goto Thaw;
	}
	/* Allocate memory management structures */
	error = create_basic_memory_bitmaps();
	if (error)
		goto Thaw;

	/* Free memory before shutting down devices. */
	error = swsusp_shrink_memory();
	if (error)
		goto Finish;
		goto Thaw;

	error = platform_prepare();
	if (error)
		goto Finish;
		goto Thaw;

	suspend_console();
	error = device_suspend(PMSG_FREEZE);
@@ -186,7 +191,7 @@ int pm_suspend_disk(void)
			power_down();
		else {
			swsusp_free();
			goto Finish;
			goto Thaw;
		}
	} else {
		pr_debug("PM: Image restored successfully.\n");
@@ -199,10 +204,12 @@ int pm_suspend_disk(void)
	platform_finish();
	device_resume();
	resume_console();
 Finish:
	free_basic_memory_bitmaps();
 Thaw:
	unprepare_processes();
 Finish:
	free_basic_memory_bitmaps();
 Exit:
	atomic_inc(&snapshot_device_available);
	return error;
}

@@ -250,9 +257,15 @@ static int software_resume(void)
	if (error)
		goto Unlock;

	/* The snapshot device should not be opened while we're running */
	if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
		error = -EBUSY;
		goto Unlock;
	}

	error = create_basic_memory_bitmaps();
	if (error)
		goto Unlock;
		goto Finish;

	pr_debug("PM: Preparing processes for restore.\n");
	error = prepare_processes();
@@ -290,6 +303,8 @@ static int software_resume(void)
	unprepare_processes();
 Done:
	free_basic_memory_bitmaps();
 Finish:
	atomic_inc(&snapshot_device_available);
	/* For success case, the suspend path will release the lock */
 Unlock:
	mutex_unlock(&pm_mutex);
+3 −0
Original line number Diff line number Diff line
@@ -140,6 +140,9 @@ struct resume_swap_area {
#define PMOPS_ENTER	2
#define PMOPS_FINISH	3

/* If unset, the snapshot device cannot be open. */
extern atomic_t snapshot_device_available;

/**
 *	The bitmap is used for tracing allocated swap pages
 *
+4 −4
Original line number Diff line number Diff line
@@ -723,19 +723,19 @@ int create_basic_memory_bitmaps(void)

	BUG_ON(forbidden_pages_map || free_pages_map);

	bm1 = kzalloc(sizeof(struct memory_bitmap), GFP_ATOMIC);
	bm1 = kzalloc(sizeof(struct memory_bitmap), GFP_KERNEL);
	if (!bm1)
		return -ENOMEM;

	error = memory_bm_create(bm1, GFP_ATOMIC | __GFP_COLD, PG_ANY);
	error = memory_bm_create(bm1, GFP_KERNEL, PG_ANY);
	if (error)
		goto Free_first_object;

	bm2 = kzalloc(sizeof(struct memory_bitmap), GFP_ATOMIC);
	bm2 = kzalloc(sizeof(struct memory_bitmap), GFP_KERNEL);
	if (!bm2)
		goto Free_first_bitmap;

	error = memory_bm_create(bm2, GFP_ATOMIC | __GFP_COLD, PG_ANY);
	error = memory_bm_create(bm2, GFP_KERNEL, PG_ANY);
	if (error)
		goto Free_second_object;

+5 −5
Original line number Diff line number Diff line
@@ -40,21 +40,21 @@ static struct snapshot_data {
	char platform_suspend;
} snapshot_state;

static atomic_t device_available = ATOMIC_INIT(1);
atomic_t snapshot_device_available = ATOMIC_INIT(1);

static int snapshot_open(struct inode *inode, struct file *filp)
{
	struct snapshot_data *data;

	if (!atomic_add_unless(&device_available, -1, 0))
	if (!atomic_add_unless(&snapshot_device_available, -1, 0))
		return -EBUSY;

	if ((filp->f_flags & O_ACCMODE) == O_RDWR) {
		atomic_inc(&device_available);
		atomic_inc(&snapshot_device_available);
		return -ENOSYS;
	}
	if(create_basic_memory_bitmaps()) {
		atomic_inc(&device_available);
		atomic_inc(&snapshot_device_available);
		return -ENOMEM;
	}
	nonseekable_open(inode, filp);
@@ -92,7 +92,7 @@ static int snapshot_release(struct inode *inode, struct file *filp)
		enable_nonboot_cpus();
		mutex_unlock(&pm_mutex);
	}
	atomic_inc(&device_available);
	atomic_inc(&snapshot_device_available);
	return 0;
}