diff -Nru a/fs/super.c b/fs/super.c --- a/fs/super.c 2004-09-05 03:54:23 +02:00 +++ b/fs/super.c 2004-09-05 03:54:23 +02:00 @@ -35,6 +35,7 @@ #include #include /* for the emergency remount stuff */ #include +#include #include @@ -633,6 +634,16 @@ return (void *)s->s_bdev == data; } +static void notify_device_claim(const char *action, struct block_device *bdev) +{ + if (bdev->bd_disk) { + if (bdev->bd_part) + kobj_notify(action, &bdev->bd_part->kobj, NULL); + else + kobj_notify(action, &bdev->bd_disk->kobj, NULL); + } +} + struct super_block *get_sb_bdev(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, int (*fill_super)(struct super_block *, void *, int)) @@ -675,8 +686,10 @@ up_write(&s->s_umount); deactivate_super(s); s = ERR_PTR(error); - } else + } else { s->s_flags |= MS_ACTIVE; + notify_device_claim("claim", bdev); + } } return s; @@ -691,6 +704,8 @@ void kill_block_super(struct super_block *sb) { struct block_device *bdev = sb->s_bdev; + + notify_device_claim("release", bdev); generic_shutdown_super(sb); set_blocksize(bdev, sb->s_old_blocksize); close_bdev_excl(bdev); @@ -717,6 +732,7 @@ return ERR_PTR(error); } s->s_flags |= MS_ACTIVE; + return s; } diff -Nru a/include/linux/kobj_notify.h b/include/linux/kobj_notify.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/linux/kobj_notify.h 2004-09-05 03:54:23 +02:00 @@ -0,0 +1,31 @@ +#ifndef _KOBJ_NOTIFY_H_ +#define _KOBJ_NOTIFY_H_ + +#ifdef __KERNEL__ +#ifdef CONFIG_KOBJ_NOTIFY + +extern int kobj_notify(const char *signal, struct kobject *kobj, + struct attribute *attr); + +extern int kobj_notify_atomic(const char *signal, struct kobject *kobj, + struct attribute *attr); + +#else + +static inline int kobj_notify(const char *signal, struct kobject *kobj, + struct attribute *attr) +{ + return 0; +} + +static inline int kobj_notify_atomic(const char *signal, struct kobject *kobj, + struct attribute *attr) +{ + return 0; +} + + +#endif /* CONFIG_KOBJ_NOTIFY */ +#endif /* __KERNEL__ */ + +#endif /* _KOBJ_NOTIFY_H_ */ diff -Nru a/include/linux/netlink.h b/include/linux/netlink.h --- a/include/linux/netlink.h 2004-09-05 03:54:23 +02:00 +++ b/include/linux/netlink.h 2004-09-05 03:54:23 +02:00 @@ -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_KOBJ_NOTIFY 15 /* Kernel messages to userspace */ #define NETLINK_TAPBASE 16 /* 16 to 31 are ethertap */ #define MAX_LINKS 32 diff -Nru a/init/Kconfig b/init/Kconfig --- a/init/Kconfig 2004-09-05 03:54:23 +02:00 +++ b/init/Kconfig 2004-09-05 03:54:23 +02:00 @@ -195,6 +195,21 @@ agent" (/sbin/hotplug) to load modules and set up software needed to use devices as you hotplug them. +config KOBJ_NOTIFY + bool "Kernel Events Layer" + depends on NET && HOTPLUG + 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 events system, that notifies userspace about kobject state + changes e.g. hotplug events, power state changes or block device + claiming (mount/unmount). + + Say Y, unless you are building a system requiring minimal memory + consumption. + config IKCONFIG bool "Kernel .config support" ---help--- diff -Nru a/kernel/Makefile b/kernel/Makefile --- a/kernel/Makefile 2004-09-05 03:54:23 +02:00 +++ b/kernel/Makefile 2004-09-05 03:54:23 +02:00 @@ -24,6 +24,7 @@ obj-$(CONFIG_AUDIT) += audit.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o obj-$(CONFIG_KPROBES) += kprobes.o +obj-$(CONFIG_KOBJ_NOTIFY) += kobj_notify.o ifneq ($(CONFIG_IA64),y) # According to Alan Modra , the -fno-omit-frame-pointer is diff -Nru a/kernel/kobj_notify.c b/kernel/kobj_notify.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/kernel/kobj_notify.c 2004-09-05 03:54:23 +02:00 @@ -0,0 +1,88 @@ +/* + * kernel/kobj_notify.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 + +static struct sock *kobj_notify_sock = NULL; + +static int do_kobj_notify(const char *signal, struct kobject *kobj, + struct attribute *attr, int gfp_mask) +{ + const char *path; + struct sk_buff *skb; + char *buffer; + int len; + + if (!kobj_notify_sock) + return -EIO; + + path = kobject_get_path(NULL, kobj, gfp_mask); + if (!path) + return -ENOMEM; + + len = strlen(signal) + 1; + len += strlen(path) + 1; + if (attr) + len += strlen(attr->name) + 1; + + skb = alloc_skb(len, gfp_mask); + if (!skb) + return -ENOMEM; + + buffer = skb_put(skb, len); + if (attr) + sprintf(buffer, "%s\n%s/%s", signal, path, attr->name); + else + sprintf(buffer, "%s\n%s", signal, path); + kfree(path); + + return netlink_broadcast(kobj_notify_sock, skb, 0, 1, gfp_mask); +} + +int kobj_notify(const char *signal, struct kobject *kobj, + struct attribute *attr) +{ + return do_kobj_notify(signal, kobj, attr, GFP_KERNEL); +} + +EXPORT_SYMBOL(kobj_notify); + +int kobj_notify_atomic(const char *signal, struct kobject *kobj, + struct attribute *attr) +{ + return do_kobj_notify(signal, kobj, attr, GFP_ATOMIC); +} + +EXPORT_SYMBOL(kobj_notify_atomic); + +static int __init kobj_notify_init(void) +{ + kobj_notify_sock = netlink_kernel_create(NETLINK_KOBJ_NOTIFY, NULL); + + if (!kobj_notify_sock) { + printk(KERN_ERR + "kobj_notify: unable to create netlink socket!\n"); + return -ENODEV; + } + + return 0; +} + +core_initcall(kobj_notify_init); diff -Nru a/lib/kobject.c b/lib/kobject.c --- a/lib/kobject.c 2004-09-05 03:54:23 +02:00 +++ b/lib/kobject.c 2004-09-05 03:54:23 +02:00 @@ -13,6 +13,7 @@ #undef DEBUG #include +#include #include #include #include @@ -202,6 +203,8 @@ goto exit; } } + + kobj_notify(action, kobj, NULL); pr_debug ("%s: %s %s %s %s %s %s %s\n", __FUNCTION__, argv[0], argv[1], envp[0], envp[1], envp[2], envp[3], envp[4]);