[PATCH 2/9] PM: suspend_block: Add driver to access suspend blockers from user-space

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?=
Date: Thursday, April 22, 2010 - 6:08 pm

Add a misc device, "suspend_blocker", that allows user-space processes
to block auto suspend. The device has ioctls to create a suspend_blocker,
and to block and unblock suspend. To delete the suspend_blocker, close
the device.

Signed-off-by: Arve Hjønnevåg <arve@android.com>
---
 Documentation/power/suspend-blockers.txt |   17 ++++
 include/linux/suspend_block_dev.h        |   25 ++++++
 kernel/power/Kconfig                     |    9 ++
 kernel/power/Makefile                    |    1 +
 kernel/power/user_suspend_blocker.c      |  128 ++++++++++++++++++++++++++++++
 5 files changed, 180 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/suspend_block_dev.h
 create mode 100644 kernel/power/user_suspend_blocker.c

diff --git a/Documentation/power/suspend-blockers.txt b/Documentation/power/suspend-blockers.txt
index 1c48514..877bd8c 100644
--- a/Documentation/power/suspend-blockers.txt
+++ b/Documentation/power/suspend-blockers.txt
@@ -95,3 +95,20 @@ if (list_empty(&state->pending_work))
 else
 	suspend_block(&state->suspend_blocker);
 
+User-space API
+==============
+
+To create a suspend_blocker from user-space, open the suspend_blocker device:
+    fd = open("/dev/suspend_blocker", O_RDWR | O_CLOEXEC);
+then call:
+    ioctl(fd, SUSPEND_BLOCKER_IOCTL_INIT(strlen(name)), name);
+
+To activate a suspend_blocker call:
+    ioctl(fd, SUSPEND_BLOCKER_IOCTL_BLOCK);
+
+To unblock call:
+    ioctl(fd, SUSPEND_BLOCKER_IOCTL_UNBLOCK);
+
+To destroy the suspend_blocker, close the device:
+    close(fd);
+
diff --git a/include/linux/suspend_block_dev.h b/include/linux/suspend_block_dev.h
new file mode 100644
index 0000000..24bc5c7
--- /dev/null
+++ b/include/linux/suspend_block_dev.h
@@ -0,0 +1,25 @@
+/* include/linux/suspend_block_dev.h
+ *
+ * Copyright (C) 2009 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_SUSPEND_BLOCK_DEV_H
+#define _LINUX_SUSPEND_BLOCK_DEV_H
+
+#include <linux/ioctl.h>
+
+#define SUSPEND_BLOCKER_IOCTL_INIT(len)		_IOC(_IOC_WRITE, 's', 0, len)
+#define SUSPEND_BLOCKER_IOCTL_BLOCK		_IO('s', 1)
+#define SUSPEND_BLOCKER_IOCTL_UNBLOCK		_IO('s', 2)
+
+#endif
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index f8fa246..1ac50ee 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -141,6 +141,15 @@ config SUSPEND_BLOCKERS
 	  state through /sys/power/state, the requested sleep state will be
 	  entered when no suspend blockers are active.
 
+config USER_SUSPEND_BLOCKERS
+	bool "Userspace suspend blockers"
+	depends on SUSPEND_BLOCKERS
+	default y
+	---help---
+	  User-space suspend block api. Creates a misc device with ioctls
+	  to create, block and unblock a suspend_blocker. The suspend_blocker
+	  will be deleted when the device is closed.
+
 config HIBERNATION_NVS
 	bool
 
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index f570801..80086c6 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_PM_SLEEP)		+= console.o
 obj-$(CONFIG_FREEZER)		+= process.o
 obj-$(CONFIG_SUSPEND)		+= suspend.o
 obj-$(CONFIG_SUSPEND_BLOCKERS)	+= suspend_blocker.o
+obj-$(CONFIG_USER_SUSPEND_BLOCKERS)	+= user_suspend_blocker.o
 obj-$(CONFIG_PM_TEST_SUSPEND)	+= suspend_test.o
 obj-$(CONFIG_HIBERNATION)	+= hibernate.o snapshot.o swap.o user.o
 obj-$(CONFIG_HIBERNATION_NVS)	+= hibernate_nvs.o
diff --git a/kernel/power/user_suspend_blocker.c b/kernel/power/user_suspend_blocker.c
new file mode 100644
index 0000000..a9be6f4
--- /dev/null
+++ b/kernel/power/user_suspend_blocker.c
@@ -0,0 +1,128 @@
+/* kernel/power/user_suspend_block.c
+ *
+ * Copyright (C) 2009-2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/suspend_blocker.h>
+#include <linux/suspend_block_dev.h>
+
+enum {
+	DEBUG_FAILURE	= BIT(0),
+};
+static int debug_mask = DEBUG_FAILURE;
+module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+static DEFINE_MUTEX(ioctl_lock);
+
+struct user_suspend_blocker {
+	struct suspend_blocker	blocker;
+	char			name[0];
+};
+
+static int create_user_suspend_blocker(struct file *file, void __user *name,
+				 size_t name_len)
+{
+	struct user_suspend_blocker *bl;
+	if (file->private_data)
+		return -EBUSY;
+	if (name_len > NAME_MAX)
+		return -ENAMETOOLONG;
+	bl = kzalloc(sizeof(*bl) + name_len + 1, GFP_KERNEL);
+	if (!bl)
+		return -ENOMEM;
+	if (copy_from_user(bl->name, name, name_len))
+		goto err_fault;
+	suspend_blocker_init(&bl->blocker, bl->name);
+	file->private_data = bl;
+	return 0;
+
+err_fault:
+	kfree(bl);
+	return -EFAULT;
+}
+
+static long user_suspend_blocker_ioctl(struct file *file, unsigned int cmd,
+				unsigned long _arg)
+{
+	void __user *arg = (void __user *)_arg;
+	struct user_suspend_blocker *bl;
+	long ret;
+
+	mutex_lock(&ioctl_lock);
+	if ((cmd & ~IOCSIZE_MASK) == SUSPEND_BLOCKER_IOCTL_INIT(0)) {
+		ret = create_user_suspend_blocker(file, arg, _IOC_SIZE(cmd));
+		goto done;
+	}
+	bl = file->private_data;
+	if (!bl) {
+		ret = -ENOENT;
+		goto done;
+	}
+	switch (cmd) {
+	case SUSPEND_BLOCKER_IOCTL_BLOCK:
+		suspend_block(&bl->blocker);
+		ret = 0;
+		break;
+	case SUSPEND_BLOCKER_IOCTL_UNBLOCK:
+		suspend_unblock(&bl->blocker);
+		ret = 0;
+		break;
+	default:
+		ret = -ENOTSUPP;
+	}
+done:
+	if (ret && debug_mask & DEBUG_FAILURE)
+		pr_err("user_suspend_blocker_ioctl: cmd %x failed, %ld\n",
+			cmd, ret);
+	mutex_unlock(&ioctl_lock);
+	return ret;
+}
+
+static int user_suspend_blocker_release(struct inode *inode, struct file *file)
+{
+	struct user_suspend_blocker *bl = file->private_data;
+	if (!bl)
+		return 0;
+	suspend_blocker_destroy(&bl->blocker);
+	kfree(bl);
+	return 0;
+}
+
+const struct file_operations user_suspend_blocker_fops = {
+	.release = user_suspend_blocker_release,
+	.unlocked_ioctl = user_suspend_blocker_ioctl,
+};
+
+struct miscdevice user_suspend_blocker_device = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "suspend_blocker",
+	.fops = &user_suspend_blocker_fops,
+};
+
+static int __init user_suspend_blocker_init(void)
+{
+	return misc_register(&user_suspend_blocker_device);
+}
+
+static void __exit user_suspend_blocker_exit(void)
+{
+	misc_deregister(&user_suspend_blocker_device);
+}
+
+module_init(user_suspend_blocker_init);
+module_exit(user_suspend_blocker_exit);
-- 
1.6.5.1

--
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[PATCH 0/9] Suspend block api (version 4), =?UTF-8?q?Arve=20Hj= ..., (Thu Apr 22, 6:08 pm)
[PATCH 1/9] PM: Add suspend block api., =?UTF-8?q?Arve=20Hj= ..., (Thu Apr 22, 6:08 pm)
[PATCH 2/9] PM: suspend_block: Add driver to access suspen ..., =?UTF-8?q?Arve=20Hj= ..., (Thu Apr 22, 6:08 pm)
[PATCH 3/9] PM: suspend_block: Abort task freezing if a su ..., =?UTF-8?q?Arve=20Hj= ..., (Thu Apr 22, 6:08 pm)
[PATCH 4/9] PM: suspend_block: Switch to list of active an ..., =?UTF-8?q?Arve=20Hj= ..., (Thu Apr 22, 6:08 pm)
[PATCH 5/9] PM: suspend_block: Add debugfs file, =?UTF-8?q?Arve=20Hj= ..., (Thu Apr 22, 6:08 pm)
[PATCH 6/9] PM: suspend_block: Add suspend_blocker stats, =?UTF-8?q?Arve=20Hj= ..., (Thu Apr 22, 6:08 pm)
[PATCH 7/9] PM: Add suspend blocking work., =?UTF-8?q?Arve=20Hj= ..., (Thu Apr 22, 6:08 pm)
[PATCH 8/9] Input: Block suspend while event queue is not ..., =?UTF-8?q?Arve=20Hj= ..., (Thu Apr 22, 6:08 pm)
[PATCH 9/9] power_supply: Block suspend while power supply ..., =?UTF-8?q?Arve=20Hj= ..., (Thu Apr 22, 6:08 pm)
Re: [PATCH 7/9] PM: Add suspend blocking work., Tejun Heo, (Fri Apr 23, 1:16 am)
Re: [PATCH 7/9] PM: Add suspend blocking work., Oleg Nesterov, (Fri Apr 23, 5:20 am)
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file, Randy Dunlap, (Fri Apr 23, 1:58 pm)
Re: [PATCH 7/9] PM: Add suspend blocking work., Arve Hjønnevåg, (Fri Apr 23, 3:49 pm)
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file, Arve Hjønnevåg, (Fri Apr 23, 8:23 pm)
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file, Randy Dunlap, (Fri Apr 23, 9:24 pm)
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file, Arve Hjønnevåg, (Fri Apr 23, 9:54 pm)
Re: [PATCH 8/9] Input: Block suspend while event queue is ..., Arve Hjønnevåg, (Fri Apr 23, 9:58 pm)
Re: [PATCH 8/9] Input: Block suspend while event queue is ..., Arve Hjønnevåg, (Fri Apr 23, 10:02 pm)
Re: [PATCH 7/9] PM: Add suspend blocking work., Arve Hjønnevåg, (Fri Apr 23, 10:21 pm)
Re: [PATCH 7/9] PM: Add suspend blocking work., Tejun Heo, (Fri Apr 23, 11:33 pm)
Re: [PATCH 7/9] PM: Add suspend blocking work., Arve Hjønnevåg, (Sat Apr 24, 12:21 am)
Re: [PATCH 7/9] PM: Add suspend blocking work., Tejun Heo, (Sat Apr 24, 12:43 am)
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file, Randy Dunlap, (Sun Apr 25, 12:53 pm)
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file, Randy Dunlap, (Sun Apr 25, 5:23 pm)
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file, Randy Dunlap, (Sun Apr 25, 5:50 pm)
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file, Brian Swetland, (Sun Apr 25, 11:24 pm)
Re: [PATCH 5/9] PM: suspend_block: Add debugfs file, Randy Dunlap, (Mon Apr 26, 6:28 am)
Re: [PATCH 7/9] PM: Add suspend blocking work., Oleg Nesterov, (Mon Apr 26, 7:06 am)