linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Nigel Cunningham <nigel@tuxonice.net>
To: linux-pm@lists.linux-foundation.org,
	linux-kernel@vger.kernel.org, tuxonice-devel@lists.tuxonice.net
Cc: Nigel Cunningham <nigel@tuxonice.net>
Subject: [PATCH 9/19] TuxOnIce: Netlink support.
Date: Thu,  7 May 2009 00:39:05 +1000	[thread overview]
Message-ID: <1241620755-22133-10-git-send-email-nigel@tuxonice.net> (raw)
In-Reply-To: <1241620755-22133-1-git-send-email-nigel@tuxonice.net>

This patch adds support for communicating with a userspace helper via a
netlink socket. It is used by the userspace user interface support and
by the storage manager support.

Signed-off-by: Nigel Cunningham <nigel@tuxonice.net>
---
 kernel/power/Makefile           |    4 +
 kernel/power/tuxonice_netlink.c |  339 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 343 insertions(+), 0 deletions(-)
 create mode 100644 kernel/power/tuxonice_netlink.c

diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index 07efc8a..180b89a 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -10,6 +10,10 @@ tuxonice_core-objs := tuxonice_modules.o tuxonice_sysfs.o tuxonice_highlevel.o \
 
 obj-$(CONFIG_TOI)		+= tuxonice_builtin.o
 
+ifdef CONFIG_NET
+tuxonice_core-objs		+= tuxonice_netlink.o
+endif
+
 obj-$(CONFIG_TOI_CORE)		+= tuxonice_core.o
 
 obj-$(CONFIG_PM)		+= main.o
diff --git a/kernel/power/tuxonice_netlink.c b/kernel/power/tuxonice_netlink.c
new file mode 100644
index 0000000..c394f79
--- /dev/null
+++ b/kernel/power/tuxonice_netlink.c
@@ -0,0 +1,339 @@
+/*
+ * kernel/power/tuxonice_netlink.c
+ *
+ * Copyright (C) 2004-2008 Nigel Cunningham (nigel at tuxonice net)
+ *
+ * This file is released under the GPLv2.
+ *
+ * Functions for communicating with a userspace helper via netlink.
+ */
+
+
+#include <linux/suspend.h>
+#include "tuxonice_netlink.h"
+#include "tuxonice.h"
+#include "tuxonice_modules.h"
+#include "tuxonice_alloc.h"
+
+static struct user_helper_data *uhd_list;
+
+/*
+ * Refill our pool of SKBs for use in emergencies (eg, when eating memory and
+ * none can be allocated).
+ */
+static void toi_fill_skb_pool(struct user_helper_data *uhd)
+{
+	while (uhd->pool_level < uhd->pool_limit) {
+		struct sk_buff *new_skb =
+			alloc_skb(NLMSG_SPACE(uhd->skb_size), TOI_ATOMIC_GFP);
+
+		if (!new_skb)
+			break;
+
+		new_skb->next = uhd->emerg_skbs;
+		uhd->emerg_skbs = new_skb;
+		uhd->pool_level++;
+	}
+}
+
+/*
+ * Try to allocate a single skb. If we can't get one, try to use one from
+ * our pool.
+ */
+static struct sk_buff *toi_get_skb(struct user_helper_data *uhd)
+{
+	struct sk_buff *skb =
+		alloc_skb(NLMSG_SPACE(uhd->skb_size), TOI_ATOMIC_GFP);
+
+	if (skb)
+		return skb;
+
+	skb = uhd->emerg_skbs;
+	if (skb) {
+		uhd->pool_level--;
+		uhd->emerg_skbs = skb->next;
+		skb->next = NULL;
+	}
+
+	return skb;
+}
+
+static void put_skb(struct user_helper_data *uhd, struct sk_buff *skb)
+{
+	if (uhd->pool_level < uhd->pool_limit) {
+		skb->next = uhd->emerg_skbs;
+		uhd->emerg_skbs = skb;
+	} else
+		kfree_skb(skb);
+}
+
+void toi_send_netlink_message(struct user_helper_data *uhd,
+		int type, void *params, size_t len)
+{
+	struct sk_buff *skb;
+	struct nlmsghdr *nlh;
+	void *dest;
+	struct task_struct *t;
+
+	if (uhd->pid == -1)
+		return;
+
+	if (uhd->debug)
+		printk(KERN_ERR "toi_send_netlink_message: Send "
+				"message type %d.\n", type);
+
+	skb = toi_get_skb(uhd);
+	if (!skb) {
+		printk(KERN_INFO "toi_netlink: Can't allocate skb!\n");
+		return;
+	}
+
+	/* NLMSG_PUT contains a hidden goto nlmsg_failure */
+	nlh = NLMSG_PUT(skb, 0, uhd->sock_seq, type, len);
+	uhd->sock_seq++;
+
+	dest = NLMSG_DATA(nlh);
+	if (params && len > 0)
+		memcpy(dest, params, len);
+
+	netlink_unicast(uhd->nl, skb, uhd->pid, 0);
+
+	read_lock(&tasklist_lock);
+	t = find_task_by_pid_type_ns(PIDTYPE_PID, uhd->pid, &init_pid_ns);
+	if (!t) {
+		read_unlock(&tasklist_lock);
+		if (uhd->pid > -1)
+			printk(KERN_INFO "Hmm. Can't find the userspace task"
+				" %d.\n", uhd->pid);
+		return;
+	}
+	wake_up_process(t);
+	read_unlock(&tasklist_lock);
+
+	yield();
+
+	return;
+
+nlmsg_failure:
+	if (skb)
+		put_skb(uhd, skb);
+
+	if (uhd->debug)
+		printk(KERN_ERR "toi_send_netlink_message: Failed to send "
+				"message type %d.\n", type);
+}
+
+static void send_whether_debugging(struct user_helper_data *uhd)
+{
+	static u8 is_debugging = 1;
+
+	toi_send_netlink_message(uhd, NETLINK_MSG_IS_DEBUGGING,
+			&is_debugging, sizeof(u8));
+}
+
+/*
+ * Set the PF_NOFREEZE flag on the given process to ensure it can run whilst we
+ * are hibernating.
+ */
+static int nl_set_nofreeze(struct user_helper_data *uhd, __u32 pid)
+{
+	struct task_struct *t;
+
+	if (uhd->debug)
+		printk(KERN_ERR "nl_set_nofreeze for pid %d.\n", pid);
+
+	read_lock(&tasklist_lock);
+	t = find_task_by_pid_type_ns(PIDTYPE_PID, pid, &init_pid_ns);
+	if (!t) {
+		read_unlock(&tasklist_lock);
+		printk(KERN_INFO "Strange. Can't find the userspace task %d.\n",
+				pid);
+		return -EINVAL;
+	}
+
+	t->flags |= PF_NOFREEZE;
+
+	read_unlock(&tasklist_lock);
+	uhd->pid = pid;
+
+	toi_send_netlink_message(uhd, NETLINK_MSG_NOFREEZE_ACK, NULL, 0);
+
+	return 0;
+}
+
+/*
+ * Called when the userspace process has informed us that it's ready to roll.
+ */
+static int nl_ready(struct user_helper_data *uhd, u32 version)
+{
+	if (version != uhd->interface_version) {
+		printk(KERN_INFO "%s userspace process using invalid interface"
+				" version (%d - kernel wants %d). Trying to "
+				"continue without it.\n",
+				uhd->name, version, uhd->interface_version);
+		if (uhd->not_ready)
+			uhd->not_ready();
+		return -EINVAL;
+	}
+
+	complete(&uhd->wait_for_process);
+
+	return 0;
+}
+
+void toi_netlink_close_complete(struct user_helper_data *uhd)
+{
+	if (uhd->nl) {
+		netlink_kernel_release(uhd->nl);
+		uhd->nl = NULL;
+	}
+
+	while (uhd->emerg_skbs) {
+		struct sk_buff *next = uhd->emerg_skbs->next;
+		kfree_skb(uhd->emerg_skbs);
+		uhd->emerg_skbs = next;
+	}
+
+	uhd->pid = -1;
+}
+
+static int toi_nl_gen_rcv_msg(struct user_helper_data *uhd,
+		struct sk_buff *skb, struct nlmsghdr *nlh)
+{
+	int type = nlh->nlmsg_type;
+	int *data;
+	int err;
+
+	if (uhd->debug)
+		printk(KERN_ERR "toi_user_rcv_skb: Received message %d.\n",
+				type);
+
+	/* Let the more specific handler go first. It returns
+	 * 1 for valid messages that it doesn't know. */
+	err = uhd->rcv_msg(skb, nlh);
+	if (err != 1)
+		return err;
+
+	/* Only allow one task to receive NOFREEZE privileges */
+	if (type == NETLINK_MSG_NOFREEZE_ME && uhd->pid != -1) {
+		printk(KERN_INFO "Received extra nofreeze me requests.\n");
+		return -EBUSY;
+	}
+
+	data = NLMSG_DATA(nlh);
+
+	switch (type) {
+	case NETLINK_MSG_NOFREEZE_ME:
+		return nl_set_nofreeze(uhd, nlh->nlmsg_pid);
+	case NETLINK_MSG_GET_DEBUGGING:
+		send_whether_debugging(uhd);
+		return 0;
+	case NETLINK_MSG_READY:
+		if (nlh->nlmsg_len != NLMSG_LENGTH(sizeof(u32))) {
+			printk(KERN_INFO "Invalid ready mesage.\n");
+			if (uhd->not_ready)
+				uhd->not_ready();
+			return -EINVAL;
+		}
+		return nl_ready(uhd, (u32) *data);
+	case NETLINK_MSG_CLEANUP:
+		toi_netlink_close_complete(uhd);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static void toi_user_rcv_skb(struct sk_buff *skb)
+{
+	int err;
+	struct nlmsghdr *nlh;
+	struct user_helper_data *uhd = uhd_list;
+
+	while (uhd && uhd->netlink_id != skb->sk->sk_protocol)
+		uhd = uhd->next;
+
+	if (!uhd)
+		return;
+
+	while (skb->len >= NLMSG_SPACE(0)) {
+		u32 rlen;
+
+		nlh = (struct nlmsghdr *) skb->data;
+		if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
+			return;
+
+		rlen = NLMSG_ALIGN(nlh->nlmsg_len);
+		if (rlen > skb->len)
+			rlen = skb->len;
+
+		err = toi_nl_gen_rcv_msg(uhd, skb, nlh);
+		if (err)
+			netlink_ack(skb, nlh, err);
+		else if (nlh->nlmsg_flags & NLM_F_ACK)
+			netlink_ack(skb, nlh, 0);
+		skb_pull(skb, rlen);
+	}
+}
+
+static int netlink_prepare(struct user_helper_data *uhd)
+{
+	uhd->next = uhd_list;
+	uhd_list = uhd;
+
+	uhd->sock_seq = 0x42c0ffee;
+	uhd->nl = netlink_kernel_create(&init_net, uhd->netlink_id, 0,
+			toi_user_rcv_skb, NULL, THIS_MODULE);
+	if (!uhd->nl) {
+		printk(KERN_INFO "Failed to allocate netlink socket for %s.\n",
+				uhd->name);
+		return -ENOMEM;
+	}
+
+	toi_fill_skb_pool(uhd);
+
+	return 0;
+}
+
+void toi_netlink_close(struct user_helper_data *uhd)
+{
+	struct task_struct *t;
+
+	read_lock(&tasklist_lock);
+	t = find_task_by_pid_type_ns(PIDTYPE_PID, uhd->pid, &init_pid_ns);
+	if (t)
+		t->flags &= ~PF_NOFREEZE;
+	read_unlock(&tasklist_lock);
+
+	toi_send_netlink_message(uhd, NETLINK_MSG_CLEANUP, NULL, 0);
+}
+
+int toi_netlink_setup(struct user_helper_data *uhd)
+{
+	/* In case userui didn't cleanup properly on us */
+	toi_netlink_close_complete(uhd);
+
+	if (netlink_prepare(uhd) < 0) {
+		printk(KERN_INFO "Netlink prepare failed.\n");
+		return 1;
+	}
+
+	if (toi_launch_userspace_program(uhd->program, uhd->netlink_id,
+				UMH_WAIT_EXEC, uhd->debug) < 0) {
+		printk(KERN_INFO "Launch userspace program failed.\n");
+		toi_netlink_close_complete(uhd);
+		return 1;
+	}
+
+	/* Wait 2 seconds for the userspace process to make contact */
+	wait_for_completion_timeout(&uhd->wait_for_process, 2*HZ);
+
+	if (uhd->pid == -1) {
+		printk(KERN_INFO "%s: Failed to contact userspace process.\n",
+				uhd->name);
+		toi_netlink_close_complete(uhd);
+		return 1;
+	}
+
+	return 0;
+}
-- 
1.5.6.3


  parent reply	other threads:[~2009-05-06 14:52 UTC|newest]

Thread overview: 141+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-06 14:38 [RFC] TuxOnIce Nigel Cunningham
2009-05-06 14:38 ` [PATCH 1/19] TuxOnIce: Documentation Nigel Cunningham
2009-05-16 20:10   ` Vegard Nossum
2009-05-16 22:18     ` Nigel Cunningham
2009-05-06 14:38 ` [PATCH 2/19] TuxOnIce: GEMS support Nigel Cunningham
2009-05-06 14:38 ` [PATCH 3/19] TuxOnIce: Make drop_pagecache non-static and declared in mm.h Nigel Cunningham
2009-05-06 14:39 ` [PATCH 4/19] TuxOnIce: Add support for just thawing kernel threads Nigel Cunningham
2009-05-06 14:39 ` [PATCH 5/19] TuxOnIce: Create means of determining how many pages can be allocated Nigel Cunningham
2009-05-06 14:39 ` [PATCH 6/19] TuxOnIce: Make functions and variables shared with swsusp non-static Nigel Cunningham
2009-05-06 14:39 ` [PATCH 7/19] TuxOnIce: Modify swsusp bitmaps to allow modification during scanning Nigel Cunningham
2009-05-06 14:39 ` [PATCH 8/19] TuxOnIce: Add core TuxOnIce code Nigel Cunningham
2009-05-06 14:39 ` Nigel Cunningham [this message]
2009-05-06 21:03   ` [PATCH 9/19] TuxOnIce: Netlink support Sam Ravnborg
2009-05-06 21:35     ` Nigel Cunningham
2009-05-07  4:34       ` Sam Ravnborg
2009-05-06 14:39 ` [PATCH 10/19] TuxOnIce: Storage manager support Nigel Cunningham
2009-05-06 14:39 ` [PATCH 11/19] TuxOnIce: Block I/O engine Nigel Cunningham
2009-05-06 14:39 ` [PATCH 12/19] TuxOnIce: Compression support Nigel Cunningham
2009-05-06 14:39 ` [PATCH 13/19] TuxOnIce: File allocator Nigel Cunningham
2009-05-06 14:39 ` [PATCH 14/19] TuxOnIce: Swap support Nigel Cunningham
2009-05-06 14:39 ` [PATCH 15/19] TuxOnIce: Userspace user interface support Nigel Cunningham
2009-05-06 14:39 ` [PATCH 16/19] TuxOnIce: Warn user if an initrd doesn't include an attempt at resuming Nigel Cunningham
2009-05-06 14:39 ` [PATCH 17/19] TuxOnIce: Support for replacing swsusp Nigel Cunningham
2009-05-06 14:39 ` [PATCH 18/19] TuxOnIce: Provide a means of determining the freezer state Nigel Cunningham
2009-05-06 14:39 ` [PATCH 19/19] TuxOnIce: Don't try to wake kswapd if the freezer is on Nigel Cunningham
2009-05-07 12:09 ` [RFC] TuxOnIce Pavel Machek
2009-05-07 15:28   ` [TuxOnIce-devel] " Kenneth Crudup
2009-05-07 17:05     ` Kenneth Crudup
2009-05-09  9:10       ` Stefan Richter
2009-05-10  5:37       ` Pavel Machek
2009-05-10  5:37     ` Pavel Machek
2009-05-07 16:55   ` U Kuehn
2009-05-07 17:45     ` Rafael J. Wysocki
2009-05-07 17:49       ` Kenneth Crudup
2009-05-07 18:54         ` Fabio Comolli
2009-05-07 18:57           ` Kenneth Crudup
2009-05-07 17:52       ` Matt Price
2009-05-07 18:22         ` Rafael J. Wysocki
2009-05-07 18:57           ` Fabio Comolli
2009-05-07 19:27             ` Rafael J. Wysocki
2009-05-07 20:41               ` Nigel Cunningham
2009-05-07 23:14                 ` Jesse Barnes
2009-05-07 23:32                   ` Nigel Cunningham
2009-05-07 23:43                     ` Jesse Barnes
2009-05-08  0:13                       ` Nigel Cunningham
2009-05-08  0:39                         ` Jesse Barnes
2009-05-08  0:49                           ` Nigel Cunningham
2009-05-08  0:18                       ` Rafael J. Wysocki
2009-05-07 21:46             ` Pavel Machek
2009-05-08  7:11               ` Fabio Comolli
2009-05-07 21:42     ` Pavel Machek
2009-05-08  0:11     ` Alex Goebel
2009-05-07 17:42   ` Rafael J. Wysocki
2009-05-07 20:37     ` Nigel Cunningham
2009-05-07 21:51     ` Pavel Machek
2009-05-08  1:34       ` [TuxOnIce-devel] " Nigel Cunningham
2009-05-08 14:11         ` Rafael J. Wysocki
2009-05-08 21:52           ` Nigel Cunningham
2009-05-08 22:46             ` Rafael J. Wysocki
2009-05-08 23:30               ` Nigel Cunningham
2009-05-08 23:43                 ` Rafael J. Wysocki
2009-05-25 10:05                   ` Nigel Cunningham
2009-05-25 12:43                     ` Pavel Machek
2009-05-25 13:15                       ` Nigel Cunningham
2009-05-25 21:43                     ` Rafael J. Wysocki
     [not found]                       ` <1243288705.16743.129.camel@nigel-laptop>
2009-05-25 22:39                         ` Rafael J. Wysocki
2009-05-26  0:39                           ` Nigel Cunningham
2009-05-26 22:27                             ` Rafael J. Wysocki
2009-05-27  0:02                               ` Nigel Cunningham
2009-05-27 18:26                                 ` [linux-pm] " Len Brown
2009-05-25 22:45                       ` Oliver Neukum
2009-05-25 22:58                         ` Rafael J. Wysocki
2009-05-25 23:13                           ` Oliver Neukum
2009-05-27 14:38                             ` Martin Steigerwald
2009-05-26  0:42                           ` Nigel Cunningham
2009-05-26  9:19                           ` Pavel Machek
2009-05-26 11:07                             ` Oliver Neukum
2009-05-26 21:33                               ` Nigel Cunningham
2009-05-26 21:56                                 ` [linux-pm] " Alan Stern
2009-05-26 22:24                                   ` Oliver Neukum
2009-05-27  0:00                                     ` Nigel Cunningham
2009-05-26 23:59                                   ` Nigel Cunningham
2009-05-26 21:36                               ` Pavel Machek
2009-05-26 21:29                             ` Nigel Cunningham
2009-05-26 22:51                           ` Oliver Neukum
2009-05-26 23:10                             ` Rafael J. Wysocki
2009-05-26  0:42                         ` Nigel Cunningham
2009-05-08 23:44                 ` Ray Lee
2009-05-27 19:10                   ` Len Brown
2009-05-27 23:43                     ` Nigel Cunningham
2009-05-09 13:54                 ` Pavel Machek
2009-05-25  9:53                   ` Nigel Cunningham
2009-05-25 22:02                     ` Rafael J. Wysocki
2009-05-26  0:19                       ` Nigel Cunningham
2009-05-26 22:37                         ` Rafael J. Wysocki
2009-05-27  0:06                           ` Nigel Cunningham
2009-05-28 11:50                     ` Pavel Machek
2009-05-09 13:27               ` Pavel Machek
2009-05-09 19:32                 ` Rafael J. Wysocki
2009-05-09 22:22                   ` Nigel Cunningham
2009-05-14  9:16                   ` Pavel Machek
2009-05-16 23:11                     ` Nigel Cunningham
2009-05-09 13:03           ` Pavel Machek
2009-05-08 19:44         ` Bartlomiej Zolnierkiewicz
2009-05-08 21:03           ` Rafael J. Wysocki
2009-05-08 22:37             ` Nigel Cunningham
2009-05-08 21:59           ` Nigel Cunningham
2009-05-08 23:05             ` Bartlomiej Zolnierkiewicz
2009-05-08 23:15               ` Nigel Cunningham
2009-05-09 13:58                 ` Pavel Machek
2009-05-25  9:27                   ` Nigel Cunningham
2009-05-25 12:32                     ` Pavel Machek
2009-05-25 13:22                       ` Oliver Neukum
2009-05-25 13:26                         ` Pavel Machek
2009-05-25 21:50                           ` Nigel Cunningham
2009-05-25 21:39                       ` Nigel Cunningham
2009-05-25 22:29                         ` Oliver Neukum
2009-05-26  0:28                           ` Nigel Cunningham
2009-05-26  0:35                           ` david
2009-05-26  0:47                             ` Nigel Cunningham
2009-05-26  8:43                           ` Pavel Machek
2009-05-26 10:56                             ` Oliver Neukum
2009-05-09 11:12             ` Pekka Enberg
2009-05-07 22:37   ` trekker.dk
2009-05-08  1:17     ` Shannon McMackin
2009-05-08 21:47       ` Fabio Comolli
2009-05-10  5:38       ` Pavel Machek
2009-05-11 20:10         ` Vladislav Bolkhovitin
2009-05-10  5:38     ` Pavel Machek
2009-05-11 21:19       ` trekker.dk
2009-05-11 21:23         ` Pavel Machek
2009-05-13 20:19           ` trekker.dk
2009-05-13 20:24             ` Pavel Machek
2009-05-13 22:07               ` trekker.dk
2009-05-11 23:23         ` Alex Goebel
2009-05-16 19:07 ` Martin Steigerwald
2009-05-17  2:53   ` Matt Price
2009-05-17  3:06     ` Nigel Cunningham
2009-05-17  3:24       ` Matt Price
2009-05-17  3:57 ` Benjamin Herrenschmidt
2009-05-17  5:02   ` Nigel Cunningham

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1241620755-22133-10-git-send-email-nigel@tuxonice.net \
    --to=nigel@tuxonice.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@lists.linux-foundation.org \
    --cc=tuxonice-devel@lists.tuxonice.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).