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
next prev 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).