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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add a misc device, "suspend_blocker", that allows user-space processesto block auto suspend. The device has ioctls to create a suspend_blocker,and to block and unblock suspend. To delete the suspend_blocker, closethe device.
Signed-off-by: Arve Hjønnevåg <arve@xxxxxxxxxxx>--- 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      |  125 ++++++++++++++++++++++++++++++ 5 files changed, 177 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.txtindex 9248aa9..d81e20e 100644--- a/Documentation/power/suspend-blockers.txt+++ b/Documentation/power/suspend-blockers.txt@@ -93,3 +93,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.hnew file mode 100644index 0000000..a7c0bf9--- /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', 3)++#endifdiff --git a/kernel/power/Kconfig b/kernel/power/Kconfigindex a3587d3..84b423f 100644--- a/kernel/power/Kconfig+++ b/kernel/power/Kconfig@@ -126,6 +126,15 @@ config SUSPEND_BLOCKERS 	  through /sys/power/request_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 	bool "Hibernation (aka 'suspend to disk')" 	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLEdiff --git a/kernel/power/Makefile b/kernel/power/Makefileindex e8c7f85..24ade91 100644--- a/kernel/power/Makefile+++ b/kernel/power/Makefile@@ -7,6 +7,7 @@ obj-$(CONFIG_PM)		+= main.o obj-$(CONFIG_PM_SLEEP)		+= console.o obj-$(CONFIG_FREEZER)		+= process.o obj-$(CONFIG_SUSPEND_BLOCKERS)	+= suspend_blocker.o+obj-$(CONFIG_USER_SUSPEND_BLOCKERS)	+= user_suspend_blocker.o obj-$(CONFIG_HIBERNATION)	+= swsusp.o disk.o snapshot.o swap.o user.o  obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.odiff --git a/kernel/power/user_suspend_blocker.c b/kernel/power/user_suspend_blocker.cnew file mode 100644index 0000000..69b3ddb--- /dev/null+++ b/kernel/power/user_suspend_blocker.c@@ -0,0 +1,125 @@+/* kernel/power/user_suspend_block.c+ *+ * 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.+ *+ */++#include <linux/fs.h>+#include <linux/miscdevice.h>+#include <linux/module.h>+#include <linux/uaccess.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;+	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.1
_______________________________________________linux-pm mailing listlinux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx://lists.linux-foundation.org/mailman/listinfo/linux-pm


[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux