user.c 10.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * linux/kernel/power/user.c
 *
 * This file provides the user space interface for software suspend/resume.
 *
 * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
 *
 * This file is released under the GPLv2.
 *
 */

#include <linux/suspend.h>
#include <linux/syscalls.h>
14
#include <linux/reboot.h>
15 16 17 18 19 20 21 22
#include <linux/string.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/swapops.h>
#include <linux/pm.h>
#include <linux/fs.h>
23
#include <linux/compat.h>
24
#include <linux/console.h>
25
#include <linux/cpu.h>
26
#include <linux/freezer.h>
27

28
#include <linux/uaccess.h>
29 30 31

#include "power.h"

32

33 34 35 36 37 38
#define SNAPSHOT_MINOR	231

static struct snapshot_data {
	struct snapshot_handle handle;
	int swap;
	int mode;
39 40 41
	bool frozen;
	bool ready;
	bool platform_support;
42
	bool free_bitmaps;
43 44
} snapshot_state;

45
atomic_t snapshot_device_available = ATOMIC_INIT(1);
46 47 48 49

static int snapshot_open(struct inode *inode, struct file *filp)
{
	struct snapshot_data *data;
50
	int error, nr_calls = 0;
51

52 53 54
	if (!hibernation_available())
		return -EPERM;

55
	lock_system_sleep();
56 57 58 59 60

	if (!atomic_add_unless(&snapshot_device_available, -1, 0)) {
		error = -EBUSY;
		goto Unlock;
	}
61

62
	if ((filp->f_flags & O_ACCMODE) == O_RDWR) {
63
		atomic_inc(&snapshot_device_available);
64 65
		error = -ENOSYS;
		goto Unlock;
66
	}
67 68 69 70 71
	nonseekable_open(inode, filp);
	data = &snapshot_state;
	filp->private_data = data;
	memset(&data->handle, 0, sizeof(struct snapshot_handle));
	if ((filp->f_flags & O_ACCMODE) == O_RDONLY) {
72
		/* Hibernating.  The image device should be accessible. */
73
		data->swap = swsusp_resume_device ?
74
			swap_type_of(swsusp_resume_device, 0, NULL) : -1;
75
		data->mode = O_RDONLY;
76
		data->free_bitmaps = false;
77
		error = __pm_notifier_call_chain(PM_HIBERNATION_PREPARE, -1, &nr_calls);
78
		if (error)
79
			__pm_notifier_call_chain(PM_POST_HIBERNATION, --nr_calls, NULL);
80
	} else {
81 82 83 84 85 86
		/*
		 * Resuming.  We may need to wait for the image device to
		 * appear.
		 */
		wait_for_device_probe();

87 88
		data->swap = -1;
		data->mode = O_WRONLY;
89
		error = __pm_notifier_call_chain(PM_RESTORE_PREPARE, -1, &nr_calls);
90 91 92
		if (!error) {
			error = create_basic_memory_bitmaps();
			data->free_bitmaps = !error;
93 94 95
		} else
			nr_calls--;

96
		if (error)
97
			__pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL);
98
	}
99
	if (error)
100
		atomic_inc(&snapshot_device_available);
101

102 103 104
	data->frozen = false;
	data->ready = false;
	data->platform_support = false;
105

106
 Unlock:
107
	unlock_system_sleep();
108 109

	return error;
110 111 112 113 114 115
}

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

116
	lock_system_sleep();
117

118 119
	swsusp_free();
	data = filp->private_data;
120
	free_all_swap_pages(data->swap);
121 122
	if (data->frozen) {
		pm_restore_gfp_mask();
123
		free_basic_memory_bitmaps();
124
		thaw_processes();
125 126
	} else if (data->free_bitmaps) {
		free_basic_memory_bitmaps();
127
	}
128
	pm_notifier_call_chain(data->mode == O_RDONLY ?
129
			PM_POST_HIBERNATION : PM_POST_RESTORE);
130
	atomic_inc(&snapshot_device_available);
131

132
	unlock_system_sleep();
133

134 135 136 137 138 139 140 141
	return 0;
}

static ssize_t snapshot_read(struct file *filp, char __user *buf,
                             size_t count, loff_t *offp)
{
	struct snapshot_data *data;
	ssize_t res;
J
Jiri Slaby 已提交
142
	loff_t pg_offp = *offp & ~PAGE_MASK;
143

144
	lock_system_sleep();
145

146
	data = filp->private_data;
147 148 149 150
	if (!data->ready) {
		res = -ENODATA;
		goto Unlock;
	}
J
Jiri Slaby 已提交
151 152 153 154 155 156
	if (!pg_offp) { /* on page boundary? */
		res = snapshot_read_next(&data->handle);
		if (res <= 0)
			goto Unlock;
	} else {
		res = PAGE_SIZE - pg_offp;
157
	}
158

J
Jiri Slaby 已提交
159 160 161 162 163
	res = simple_read_from_buffer(buf, count, &pg_offp,
			data_of(data->handle), res);
	if (res > 0)
		*offp += res;

164
 Unlock:
165
	unlock_system_sleep();
166

167 168 169 170 171 172 173 174
	return res;
}

static ssize_t snapshot_write(struct file *filp, const char __user *buf,
                              size_t count, loff_t *offp)
{
	struct snapshot_data *data;
	ssize_t res;
J
Jiri Slaby 已提交
175
	loff_t pg_offp = *offp & ~PAGE_MASK;
176

177
	lock_system_sleep();
178

179
	data = filp->private_data;
J
Jiri Slaby 已提交
180 181 182 183 184 185 186

	if (!pg_offp) {
		res = snapshot_write_next(&data->handle);
		if (res <= 0)
			goto unlock;
	} else {
		res = PAGE_SIZE - pg_offp;
187
	}
188

J
Jiri Slaby 已提交
189 190 191 192 193
	res = simple_write_to_buffer(data_of(data->handle), res, &pg_offp,
			buf, count);
	if (res > 0)
		*offp += res;
unlock:
194
	unlock_system_sleep();
195

196 197 198
	return res;
}

199 200
static long snapshot_ioctl(struct file *filp, unsigned int cmd,
							unsigned long arg)
201 202 203
{
	int error = 0;
	struct snapshot_data *data;
204
	loff_t size;
205
	sector_t offset;
206 207 208 209 210 211 212 213

	if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC)
		return -ENOTTY;
	if (_IOC_NR(cmd) > SNAPSHOT_IOC_MAXNR)
		return -ENOTTY;
	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;

214 215
	if (!mutex_trylock(&pm_mutex))
		return -EBUSY;
216

217
	lock_device_hotplug();
218
	data = filp->private_data;
219

220 221 222 223 224
	switch (cmd) {

	case SNAPSHOT_FREEZE:
		if (data->frozen)
			break;
225

226
		printk("Syncing filesystems ... ");
227
		ksys_sync();
228 229
		printk("done.\n");

230
		error = freeze_processes();
231 232 233 234 235 236 237
		if (error)
			break;

		error = create_basic_memory_bitmaps();
		if (error)
			thaw_processes();
		else
238
			data->frozen = true;
239

240 241 242
		break;

	case SNAPSHOT_UNFREEZE:
243
		if (!data->frozen || data->ready)
244
			break;
245
		pm_restore_gfp_mask();
246
		free_basic_memory_bitmaps();
247
		data->free_bitmaps = false;
248
		thaw_processes();
249
		data->frozen = false;
250 251
		break;

252
	case SNAPSHOT_CREATE_IMAGE:
253 254 255 256
		if (data->mode != O_RDONLY || !data->frozen  || data->ready) {
			error = -EPERM;
			break;
		}
257
		pm_restore_gfp_mask();
258
		error = hibernation_snapshot(data->platform_support);
259
		if (!error) {
260
			error = put_user(in_suspend, (int __user *)arg);
261 262
			data->ready = !freezer_test_done && !error;
			freezer_test_done = false;
263
		}
264 265 266
		break;

	case SNAPSHOT_ATOMIC_RESTORE:
267
		snapshot_write_finalize(&data->handle);
268 269 270 271 272
		if (data->mode != O_WRONLY || !data->frozen ||
		    !snapshot_image_loaded(&data->handle)) {
			error = -EPERM;
			break;
		}
273
		error = hibernation_restore(data->platform_support);
274 275 276 277 278
		break;

	case SNAPSHOT_FREE:
		swsusp_free();
		memset(&data->handle, 0, sizeof(struct snapshot_handle));
279
		data->ready = false;
280 281 282 283 284 285 286 287 288
		/*
		 * It is necessary to thaw kernel threads here, because
		 * SNAPSHOT_CREATE_IMAGE may be invoked directly after
		 * SNAPSHOT_FREE.  In that case, if kernel threads were not
		 * thawed, the preallocation of memory carried out by
		 * hibernation_snapshot() might run into problems (i.e. it
		 * might fail or even deadlock).
		 */
		thaw_kernel_threads();
289 290
		break;

291
	case SNAPSHOT_PREF_IMAGE_SIZE:
292 293 294
		image_size = arg;
		break;

295 296 297 298 299 300 301 302 303 304
	case SNAPSHOT_GET_IMAGE_SIZE:
		if (!data->ready) {
			error = -ENODATA;
			break;
		}
		size = snapshot_get_image_size();
		size <<= PAGE_SHIFT;
		error = put_user(size, (loff_t __user *)arg);
		break;

305
	case SNAPSHOT_AVAIL_SWAP_SIZE:
306 307 308
		size = count_swap_pages(data->swap, 1);
		size <<= PAGE_SHIFT;
		error = put_user(size, (loff_t __user *)arg);
309 310
		break;

311
	case SNAPSHOT_ALLOC_SWAP_PAGE:
312 313 314 315
		if (data->swap < 0 || data->swap >= MAX_SWAPFILES) {
			error = -ENODEV;
			break;
		}
316
		offset = alloc_swapdev_block(data->swap);
317 318
		if (offset) {
			offset <<= PAGE_SHIFT;
319
			error = put_user(offset, (loff_t __user *)arg);
320 321 322 323 324 325 326 327 328 329
		} else {
			error = -ENOSPC;
		}
		break;

	case SNAPSHOT_FREE_SWAP_PAGES:
		if (data->swap < 0 || data->swap >= MAX_SWAPFILES) {
			error = -ENODEV;
			break;
		}
330
		free_all_swap_pages(data->swap);
331 332
		break;

333 334 335 336 337
	case SNAPSHOT_S2RAM:
		if (!data->frozen) {
			error = -EPERM;
			break;
		}
338 339 340 341 342
		/*
		 * Tasks are frozen and the notifiers have been called with
		 * PM_HIBERNATION_PREPARE
		 */
		error = suspend_devices_and_enter(PM_SUSPEND_MEM);
343
		data->ready = false;
344 345
		break;

346 347 348 349 350 351 352 353 354
	case SNAPSHOT_PLATFORM_SUPPORT:
		data->platform_support = !!arg;
		break;

	case SNAPSHOT_POWER_OFF:
		if (data->platform_support)
			error = hibernation_platform_enter();
		break;

355
	case SNAPSHOT_SET_SWAP_AREA:
356
		if (swsusp_swap_in_use()) {
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
			error = -EPERM;
		} else {
			struct resume_swap_area swap_area;
			dev_t swdev;

			error = copy_from_user(&swap_area, (void __user *)arg,
					sizeof(struct resume_swap_area));
			if (error) {
				error = -EFAULT;
				break;
			}

			/*
			 * User space encodes device types as two-byte values,
			 * so we need to recode them
			 */
373
			swdev = new_decode_dev(swap_area.dev);
374 375
			if (swdev) {
				offset = swap_area.offset;
376
				data->swap = swap_type_of(swdev, offset, NULL);
377 378 379 380 381 382 383 384 385
				if (data->swap < 0)
					error = -ENODEV;
			} else {
				data->swap = -1;
				error = -EINVAL;
			}
		}
		break;

386 387 388 389
	default:
		error = -ENOTTY;

	}
390

391
	unlock_device_hotplug();
392 393
	mutex_unlock(&pm_mutex);

394 395 396
	return error;
}

397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
#ifdef CONFIG_COMPAT

struct compat_resume_swap_area {
	compat_loff_t offset;
	u32 dev;
} __packed;

static long
snapshot_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	BUILD_BUG_ON(sizeof(loff_t) != sizeof(compat_loff_t));

	switch (cmd) {
	case SNAPSHOT_GET_IMAGE_SIZE:
	case SNAPSHOT_AVAIL_SWAP_SIZE:
	case SNAPSHOT_ALLOC_SWAP_PAGE: {
		compat_loff_t __user *uoffset = compat_ptr(arg);
		loff_t offset;
		mm_segment_t old_fs;
		int err;

		old_fs = get_fs();
		set_fs(KERNEL_DS);
		err = snapshot_ioctl(file, cmd, (unsigned long) &offset);
		set_fs(old_fs);
		if (!err && put_user(offset, uoffset))
			err = -EFAULT;
		return err;
	}

	case SNAPSHOT_CREATE_IMAGE:
		return snapshot_ioctl(file, cmd,
				      (unsigned long) compat_ptr(arg));

	case SNAPSHOT_SET_SWAP_AREA: {
		struct compat_resume_swap_area __user *u_swap_area =
			compat_ptr(arg);
		struct resume_swap_area swap_area;
		mm_segment_t old_fs;
		int err;

		err = get_user(swap_area.offset, &u_swap_area->offset);
		err |= get_user(swap_area.dev, &u_swap_area->dev);
		if (err)
			return -EFAULT;
		old_fs = get_fs();
		set_fs(KERNEL_DS);
		err = snapshot_ioctl(file, SNAPSHOT_SET_SWAP_AREA,
				     (unsigned long) &swap_area);
		set_fs(old_fs);
		return err;
	}

	default:
		return snapshot_ioctl(file, cmd, arg);
	}
}

#endif /* CONFIG_COMPAT */

457
static const struct file_operations snapshot_fops = {
458 459 460 461 462
	.open = snapshot_open,
	.release = snapshot_release,
	.read = snapshot_read,
	.write = snapshot_write,
	.llseek = no_llseek,
463
	.unlocked_ioctl = snapshot_ioctl,
464 465 466
#ifdef CONFIG_COMPAT
	.compat_ioctl = snapshot_compat_ioctl,
#endif
467 468 469 470 471 472 473 474 475 476 477 478 479 480
};

static struct miscdevice snapshot_device = {
	.minor = SNAPSHOT_MINOR,
	.name = "snapshot",
	.fops = &snapshot_fops,
};

static int __init snapshot_device_init(void)
{
	return misc_register(&snapshot_device);
};

device_initcall(snapshot_device_init);