From: Robert Love Here is the Kernel Events Layer rewritten as more of an asynchronous sysfs change notifier. The concept of object and payload have been removed. Instead, events are modeled as signals emitting from kobjects. It is pretty simple. The interface is now: int send_kevent(enum kevent type, struct kset *kset, struct kobject *kobj, const char *signal) Say your processor (with kobject "kobj") is overheating. You might do send_kevent(KEVENT_POWER, NULL, kobj, "overheating"); We could get rid of signal and just require passing a specific attribute file in sysfs, which would presumably explain the reason for the event, but I think having a single signal value is acceptable. The rest of the payload has been ditched. The basic idea here is to represent to user-space events as changes to sysfs. Media was changed? Then that block device in sysfs emits a "media_change" event. This patch includes two example events: file system mount and unmount. Kay has some utilities and examples at http://vrfy.org/projects/kevents/ and http://vrfy.org/projects/kdbusd/ The intention of this work is to hook the kernel into D-BUS, although the implementation is agnostic and should work with any user-space setup. Signed-Off-By: Robert Love Signed-off-by: Andrew Morton --- 25-akpm/fs/super.c | 11 ++++ 25-akpm/include/linux/kevent.h | 42 ++++++++++++++++ 25-akpm/include/linux/netlink.h | 1 25-akpm/init/Kconfig | 14 +++++ 25-akpm/kernel/Makefile | 1 25-akpm/kernel/kevent.c | 100 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 168 insertions(+), 1 deletion(-) diff -puN fs/super.c~kernel-sysfs-events-layer fs/super.c --- 25/fs/super.c~kernel-sysfs-events-layer Tue Aug 31 15:34:11 2004 +++ 25-akpm/fs/super.c Tue Aug 31 15:34:11 2004 @@ -35,6 +35,7 @@ #include #include /* for the emergency remount stuff */ #include +#include #include @@ -875,8 +876,12 @@ struct super_block *get_sb_bdev(struct f up_write(&s->s_umount); deactivate_super(s); s = ERR_PTR(error); - } else + } else { s->s_flags |= MS_ACTIVE; + if (bdev->bd_disk) + send_kevent(KEVENT_FS, NULL, + &bdev->bd_disk->kobj, "mount"); + } } return s; @@ -891,6 +896,10 @@ EXPORT_SYMBOL(get_sb_bdev); void kill_block_super(struct super_block *sb) { struct block_device *bdev = sb->s_bdev; + + if (bdev->bd_disk) + send_kevent(KEVENT_FS, NULL, &bdev->bd_disk->kobj, "umount"); + generic_shutdown_super(sb); set_blocksize(bdev, sb->s_old_blocksize); close_bdev_excl(bdev); diff -puN /dev/null include/linux/kevent.h --- /dev/null Thu Apr 11 07:25:15 2002 +++ 25-akpm/include/linux/kevent.h Tue Aug 31 15:34:11 2004 @@ -0,0 +1,42 @@ +#ifndef _LINUX_KEVENT_H +#define _LINUX_KEVENT_H + +#include +#include + +/* kevent types - these are used as the multicast group */ +enum kevent { + KEVENT_GENERAL = 0, + KEVENT_STORAGE = 1, + KEVENT_POWER = 2, + KEVENT_FS = 3, + KEVENT_HOTPLUG = 4, +}; + +#ifdef __KERNEL__ +#ifdef CONFIG_KERNEL_EVENTS + +int send_kevent(enum kevent type, struct kset *kset, + struct kobject *kobj, const char *signal); + +int send_kevent_atomic(enum kevent type, struct kset *kset, + struct kobject *kobj, const char *signal); + +#else + +static inline int send_kevent(enum kevent type, struct kset *kset, + struct kobject *kobj, const char *signal) +{ + return 0; +} + +static inline int send_kevent_atomic(enum kevent type, struct kset *kset, + struct kobject *kobj, const char *signal) +{ + return 0; +} + +#endif /* CONFIG_KERNEL_EVENTS */ +#endif /* __KERNEL__ */ + +#endif /* _LINUX_KEVENT_H */ diff -puN include/linux/netlink.h~kernel-sysfs-events-layer include/linux/netlink.h --- 25/include/linux/netlink.h~kernel-sysfs-events-layer Tue Aug 31 15:34:11 2004 +++ 25-akpm/include/linux/netlink.h Tue Aug 31 15:34:11 2004 @@ -17,6 +17,7 @@ #define NETLINK_ROUTE6 11 /* af_inet6 route comm channel */ #define NETLINK_IP6_FW 13 #define NETLINK_DNRTMSG 14 /* DECnet routing messages */ +#define NETLINK_KEVENT 15 /* Kernel messages to userspace */ #define NETLINK_TAPBASE 16 /* 16 to 31 are ethertap */ #define MAX_LINKS 32 diff -puN init/Kconfig~kernel-sysfs-events-layer init/Kconfig --- 25/init/Kconfig~kernel-sysfs-events-layer Tue Aug 31 15:34:11 2004 +++ 25-akpm/init/Kconfig Tue Aug 31 15:34:11 2004 @@ -149,6 +149,20 @@ config AUDIT logging of avc messages output). Does not do system-call auditing without CONFIG_AUDITSYSCALL. +config KERNEL_EVENTS + bool "Kernel Events Layer" + depends on NET + default y + help + This option enables the kernel events layer, which is a simple + mechanism for kernel-to-user communication over a netlink socket. + The goal of the kernel events layer is to provide a simple and + efficient logging, error, and events system. Specifically, code + is available to link the events into D-BUS. Say Y, unless you + are building a system requiring minimal memory consumption. + + D-BUS is available at http://dbus.freedesktop.org/ + config AUDITSYSCALL bool "Enable system-call auditing support" depends on AUDIT && (X86 || PPC64 || ARCH_S390 || IA64) diff -puN /dev/null kernel/kevent.c --- /dev/null Thu Apr 11 07:25:15 2002 +++ 25-akpm/kernel/kevent.c Tue Aug 31 15:34:11 2004 @@ -0,0 +1,100 @@ +/* + * kernel/kevent.c - sysfs event delivery via netlink socket + * + * Copyright (C) 2004 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004 Novell, Inc. All rights reserved. + * + * Licensed under the GNU GPL v2. + * + * Authors: + * Robert Love + * Kay Sievers + * Arjan van de Ven + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct sock *kevent_sock = NULL; /* kevent's global netlink socket */ + +/** + * send_kevent - send a message to user-space via the kernel events layer + */ +static int do_send_kevent(enum kevent type, int gfp_mask, + const char *object, const char *signal) +{ + struct sk_buff *skb; + char *buffer; + int len; + + if (!kevent_sock) + return -EIO; + + if (!object || !signal) + return -EINVAL; + + len = strlen(object) + 1 + strlen(signal) + 1; + + skb = alloc_skb(len, gfp_mask); + if (!skb) + return -ENOMEM; + + buffer = skb_put(skb, len); + + sprintf(buffer, "%s\n%s", object, signal); + + return netlink_broadcast(kevent_sock, skb, 0, (1 << type), gfp_mask); +} + +static int __send_kevent(enum kevent type, struct kset *kset, + struct kobject *kobj, const char *signal, + int gfp_flags) +{ + const char *path; + int ret; + + path = kobject_get_path(kset, kobj, gfp_flags); + if (!path) + return -ENOMEM; + + ret = do_send_kevent(type, gfp_flags, path, signal); + kfree(path); + + return ret; +} + +int send_kevent(enum kevent type, struct kset *kset, + struct kobject *kobj, const char *signal) +{ + return __send_kevent(type, kset, kobj, signal, GFP_KERNEL); +} +EXPORT_SYMBOL_GPL(send_kevent); + +int send_kevent_atomic(enum kevent type, struct kset *kset, + struct kobject *kobj, const char *signal) +{ + return __send_kevent(type, kset, kobj, signal, GFP_ATOMIC); +} +EXPORT_SYMBOL_GPL(send_kevent_atomic); + +static int kevent_init(void) +{ + kevent_sock = netlink_kernel_create(NETLINK_KEVENT, NULL); + + if (!kevent_sock) { + printk(KERN_ERR + "kevent: unable to create netlink socket!\n"); + return -ENODEV; + } + + return 0; +} + +module_init(kevent_init); diff -puN kernel/Makefile~kernel-sysfs-events-layer kernel/Makefile --- 25/kernel/Makefile~kernel-sysfs-events-layer Tue Aug 31 15:34:11 2004 +++ 25-akpm/kernel/Makefile Tue Aug 31 15:34:11 2004 @@ -27,6 +27,7 @@ obj-$(CONFIG_STOP_MACHINE) += stop_machi obj-$(CONFIG_AUDIT) += audit.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o obj-$(CONFIG_KPROBES) += kprobes.o +obj-$(CONFIG_KERNEL_EVENTS) += kevent.o ifneq ($(CONFIG_IA64),y) # According to Alan Modra , the -fno-omit-frame-pointer is _