linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] VFS/inotify: send netlink messages when an inotify watch has been set or removed.
@ 2012-01-07 13:36 Stef Bon
  2012-01-07 14:38 ` Al Viro
  0 siblings, 1 reply; 10+ messages in thread
From: Stef Bon @ 2012-01-07 13:36 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: rlove, eparis

from: Stef Bon

I would like to apply a patch to the kernel to enable the sending of a
netlink message when setting or removing an inotify watch. My goal is
to make FUSE filesystems notify aware.

Since inotify works in the kernel space, and FUSE filesystems are in
userspace, FUSE fs's do not "know" when a watch has been set or
removed.

I think it's a good thing the fs "knows" about a watch, since it can
then set a backend specific notify watch on the backend, and report
anything back to the kernel when something changes.

The new netlink.c file is almost a copy of the netlink.c file in
fs/quota.

I've got a testprogram which receives messages in the group
GENERIC/VFS_INOTIFY.
If you want to test please email me. It just gives the information a
watch has been set (by who, and where, which mask) and when removed
(pid/fd/wd).

Signed-off-by: Stef Bon <stef@bononline.nl>

---

diff --git a/fs/notify/inotify/Kconfig b/fs/notify/inotify/Kconfig
index b981fc0..07f9bfc 100644
--- a/fs/notify/inotify/Kconfig
+++ b/fs/notify/inotify/Kconfig
@@ -15,3 +15,11 @@ config INOTIFY_USER
          For more information, see
<file:Documentation/filesystems/inotify.txt>
 
          If unsure, say Y.
+
+config INOTIFY_USER_NETLINK_INTERFACE
+       bool "Report inotify add/remove watch messages through netlink
interface"
+       depends on INOTIFY_USER && NET
+       ---help---
+         If you say Y here, inotify messages (about a watch being set
or removed
+         , not the events!) will be reported through netlink interface.
If unsure,
+         say Y.
diff --git a/fs/notify/inotify/Makefile b/fs/notify/inotify/Makefile
index a380dab..f977eaa 100644
--- a/fs/notify/inotify/Makefile
+++ b/fs/notify/inotify/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_INOTIFY_USER)     += inotify_fsnotify.o inotify_user.o
+obj-$(CONFIG_INOTIFY_USER_NETLINK_INTERFACE)   += netlink.o
\ No newline at end of file
diff --git a/fs/notify/inotify/inotify_user.c
b/fs/notify/inotify/inotify_user.c
index 8445fbc..3f056b9 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -786,6 +786,9 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const
char __user *, pathname,
 
        /* create/update an inode mark */
        ret = inotify_update_watch(group, inode,
mask);                                                                
+                                                                                                                      

+       if ( ret>=0 ) inotify_send_add_message(fd, ret, mask,
pathname);                                               
+                                                                                                                      

       
path_put(&path);                                                                                               

 fput_and_out:                                                                                                         

        fput_light(filp, fput_needed);
@@ -822,6 +825,8 @@ SYSCALL_DEFINE2(inotify_rm_watch, int, fd, __s32, wd)
        /* match ref taken by inotify_idr_find */
        fsnotify_put_mark(&i_mark->fsn_mark);
 
+       inotify_send_remove_message(fd, wd);
+
 out:
        fput_light(filp, fput_needed);
        return ret;
diff --git a/fs/notify/inotify/netlink.c b/fs/notify/inotify/netlink.c
new file mode 100644
index 0000000..b965c7f
--- /dev/null
+++ b/fs/notify/inotify/netlink.c
@@ -0,0 +1,151 @@
+
+#include <linux/cred.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/inotify.h>
+#include <net/netlink.h>
+#include <net/genetlink.h>
+
+
+/* Netlink family structure for inotify */
+static struct genl_family inotify_genl_family = {
+       .id = GENL_ID_GENERATE,
+       .hdrsize = 0,
+       .name = "VFS_INOTIFY",
+       .version = 1,
+       .maxattr = INOTIFY_NL_A_MAX,
+};
+
+/**
+ * inotify_send_add_message
+ * @fd: inotify fd
+ * @wd: watch descriptor
+ * @mask: the mask
+ * @path: path
+ *
+ */
+
+void inotify_send_add_message(u32 fd, u32 wd, u32 mask, const char *path)
+{
+       static atomic_t seq;
+       struct sk_buff *skb;
+       void *msg_head;
+       int ret;
+       int msg_size = 4 * nla_total_size(sizeof(u32)) +
nla_total_size(strlen(path)) + 1;
+
+       skb = genlmsg_new(msg_size, GFP_KERNEL);
+
+       if (!skb) {
+
+               printk(KERN_ERR "VFS: Not enough memory to compose
inotify add wd netlink message.\n");
+               return;
+
+       }
+
+       msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq),
+                       &inotify_genl_family, 0, INOTIFY_NL_C_ADD_MESSAGE);
+
+       if (!msg_head) {
+
+               printk(KERN_ERR "VFS: Cannot store netlink header in
inotify add wd netlink message.\n");
+               goto err_out;
+
+       }
+
+       ret = nla_put_u32(skb, INOTIFY_NL_A_PID, current->pid);
+       if (ret) goto attr_err_out;
+
+       ret = nla_put_u32(skb, INOTIFY_NL_A_FD, fd);
+       if (ret) goto attr_err_out;
+
+       ret = nla_put_u32(skb, INOTIFY_NL_A_WD, wd);
+       if (ret) goto attr_err_out;
+
+
+       ret = nla_put_u32(skb, INOTIFY_NL_A_MASK, mask);
+       if (ret) goto attr_err_out;
+
+       ret = nla_put_string(skb, INOTIFY_NL_A_PATH, path);
+       if (ret) goto attr_err_out;
+
+       genlmsg_end(skb, msg_head);
+
+       genlmsg_multicast(skb, 0, inotify_genl_family.id, GFP_KERNEL);
+
+       return;
+attr_err_out:
+       printk(KERN_ERR "VFS: Error when writing attributes to inotify
add wd netlink message!\n");
+err_out:
+       kfree_skb(skb);
+}
+EXPORT_SYMBOL(inotify_send_add_message);
+
+/**
+ * inotify_send_remove_message
+ * @fd: inotify fd
+ * @wd: watch descriptor
+ *
+ */
+
+void inotify_send_remove_message(u32 fd, u32 wd)
+{
+       static atomic_t seq;
+       struct sk_buff *skb;
+       void *msg_head;
+       int ret;
+       int msg_size = 3 * nla_total_size(sizeof(u32));
+
+       skb = genlmsg_new(msg_size, GFP_KERNEL);
+
+       if (!skb) {
+
+               printk(KERN_ERR "VFS: Not enough memory to send inotify
remove wd netlink message.\n");
+               return;
+
+       }
+
+       msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq),
+                       &inotify_genl_family, 0,
INOTIFY_NL_C_REMOVE_MESSAGE);
+
+       if (!msg_head) {
+
+               printk(KERN_ERR "VFS: Cannot store netlink header in
inotify remove wd netlink message.\n");
+               goto err_out;
+
+       }
+
+       ret = nla_put_u32(skb, INOTIFY_NL_A_PID, current->pid);
+       if (ret) goto attr_err_out;
+
+       ret = nla_put_u32(skb, INOTIFY_NL_A_FD, fd);
+       if (ret) goto attr_err_out;
+
+       ret = nla_put_u32(skb, INOTIFY_NL_A_WD, wd);
+       if (ret) goto attr_err_out;
+
+       genlmsg_end(skb, msg_head);
+
+       genlmsg_multicast(skb, 0, inotify_genl_family.id, GFP_KERNEL);
+
+       return;
+attr_err_out:
+       printk(KERN_ERR "VFS: Error when writing attributes to inotify
remove wd netlink message\n");
+err_out:
+       kfree_skb(skb);
+}
+EXPORT_SYMBOL(inotify_send_remove_message);
+
+
+
+
+static int __init inotify_init(void)
+{
+       if (genl_register_family(&inotify_genl_family) != 0)
+               printk(KERN_ERR"VFS: Failed to create inotify_user
netlink interface.\n");
+       return 0;
+};
+
+module_init(inotify_init);
diff --git a/include/linux/inotify.h b/include/linux/inotify.h
index d33041e..4ad0b4f 100644
--- a/include/linux/inotify.h
+++ b/include/linux/inotify.h
@@ -84,4 +84,44 @@ extern struct ctl_table inotify_table[]; /* for sysctl */
 
 #endif
 
+/* commands */
+
+enum {
+       INOTIFY_NL_C_UNSPEC,
+       INOTIFY_NL_C_ADD_MESSAGE,
+       INOTIFY_NL_C_REMOVE_MESSAGE,
+       __INOTIFY_NL_C_MAX,
+};
+
+#define INOTIFY_NL_C_MAX (__INOTIFY_NL_C_MAX - 1)
+
+/* attributes */
+
+enum {
+       INOTIFY_NL_A_UNSPEC,
+       INOTIFY_NL_A_PID,
+       INOTIFY_NL_A_FD,
+       INOTIFY_NL_A_WD,
+       INOTIFY_NL_A_MASK,
+       INOTIFY_NL_A_PATH,
+       __INOTIFY_NL_A_MAX,
+};
+
+#define INOTIFY_NL_A_MAX (__INOTIFY_NL_A_MAX - 1)
+
+
+#ifdef CONFIG_INOTIFY_USER_NETLINK_INTERFACE
+extern void inotify_send_add_message(u32 fd, u32 wd, u32 mask, const
char *path);
+extern void inotify_send_remove_message(u32 fd, u32 wd);
+#else
+static inline void inotify_send_add_message(u32 fd, u32 wd, u32 mask,
const char *path)
+{
+       return;
+}
+static inline void inotify_send_remove_message(u32 fd, u32 wd);
+{
+       return;
+}
+#endif /* CONFIG_INOTIFY_USER_NETLINK_INTERFACE */
+
 #endif /* _LINUX_INOTIFY_H */

^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH] VFS/inotify: send netlink messages when an inotify watch has been set or removed.
@ 2012-01-05 20:56 Stef Bon
  2012-01-06 14:13 ` Stef Bon
  0 siblings, 1 reply; 10+ messages in thread
From: Stef Bon @ 2012-01-05 20:56 UTC (permalink / raw)
  To: linux-fsdevel; +Cc: Robert Love, Eric Paris

from: Stef Bon

I would like to apply a patch to the kernel to enable the sending of a
netlink message when setting or removing an inotify watch. My goal is
to make FUSE filesystems notify aware.

Since inotify works in the kernel space, and FUSE filesystems are in
userspace, FUSE fs's do not "know" when a watch has been set or
removed.

I think it's a good thing the fs "knows" about a watch, since it can
then set a backend specific notify watch on the backend, and report
anything back to the kernel when something changes.

The new netlink.c file is almost a copy of the netlink.c file in
fs/quota.

I've got a testprogram which receives messages in the group GENERIC/VFS_INOTIFY.
If you want to test please email me. It just gives the information a
watch has been set (by who, and where, which mask) and when removed
(pid/fd/wd).

Signed-off-by: Stef Bon <stefbon@gmail.com>

---

diff --git a/fs/notify/inotify/Kconfig b/fs/notify/inotify/Kconfig
index b981fc0..07f9bfc 100644
--- a/fs/notify/inotify/Kconfig
+++ b/fs/notify/inotify/Kconfig
@@ -15,3 +15,11 @@ config INOTIFY_USER
          For more information, see <file:Documentation/filesystems/inotify.txt>

          If unsure, say Y.
+
+config INOTIFY_USER_NETLINK_INTERFACE
+       bool "Report inotify add/remove watch messages through netlink
interface"
+       depends on INOTIFY_USER && NET
+       ---help---
+         If you say Y here, inotify messages (about a watch being set
or removed
+         , not the events!) will be reported through netlink
interface. If unsure,
+         say Y.
diff --git a/fs/notify/inotify/Makefile b/fs/notify/inotify/Makefile
index a380dab..f977eaa 100644
--- a/fs/notify/inotify/Makefile
+++ b/fs/notify/inotify/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_INOTIFY_USER)     += inotify_fsnotify.o inotify_user.o
+obj-$(CONFIG_INOTIFY_USER_NETLINK_INTERFACE)   += netlink.o
\ No newline at end of file
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 8445fbc..3f056b9 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -786,6 +786,9 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const
char __user *, pathname,

        /* create/update an inode mark */
        ret = inotify_update_watch(group, inode, mask);
+
+       if ( ret>=0 ) inotify_send_add_message(fd, ret, mask, pathname);
+
        path_put(&path);
 fput_and_out:
        fput_light(filp, fput_needed);
@@ -822,6 +825,8 @@ SYSCALL_DEFINE2(inotify_rm_watch, int, fd, __s32, wd)
        /* match ref taken by inotify_idr_find */
        fsnotify_put_mark(&i_mark->fsn_mark);

+       inotify_send_remove_message(fd, wd);
+
 out:
        fput_light(filp, fput_needed);
        return ret;
diff --git a/fs/notify/inotify/netlink.c b/fs/notify/inotify/netlink.c
new file mode 100644
index 0000000..b965c7f
--- /dev/null
+++ b/fs/notify/inotify/netlink.c
@@ -0,0 +1,151 @@
+
+#include <linux/cred.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/inotify.h>
+#include <net/netlink.h>
+#include <net/genetlink.h>
+
+
+/* Netlink family structure for inotify */
+static struct genl_family inotify_genl_family = {
+       .id = GENL_ID_GENERATE,
+       .hdrsize = 0,
+       .name = "VFS_INOTIFY",
+       .version = 1,
+       .maxattr = INOTIFY_NL_A_MAX,
+};
+
+/**
+ * inotify_send_add_message
+ * @fd: inotify fd
+ * @wd: watch descriptor
+ * @mask: the mask
+ * @path: path
+ *
+ */
+
+void inotify_send_add_message(u32 fd, u32 wd, u32 mask, const char *path)
+{
+       static atomic_t seq;
+       struct sk_buff *skb;
+       void *msg_head;
+       int ret;
+       int msg_size = 4 * nla_total_size(sizeof(u32)) +
nla_total_size(strlen(path)) + 1;
+
+       skb = genlmsg_new(msg_size, GFP_KERNEL);
+
+       if (!skb) {
+
+               printk(KERN_ERR "VFS: Not enough memory to compose
inotify add wd netlink message.\n");
+               return;
+
+       }
+
+       msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq),
+                       &inotify_genl_family, 0, INOTIFY_NL_C_ADD_MESSAGE);
+
+       if (!msg_head) {
+
+               printk(KERN_ERR "VFS: Cannot store netlink header in
inotify add wd netlink message.\n");
+               goto err_out;
+
+       }
+
+       ret = nla_put_u32(skb, INOTIFY_NL_A_PID, current->pid);
+       if (ret) goto attr_err_out;
+
+       ret = nla_put_u32(skb, INOTIFY_NL_A_FD, fd);
+       if (ret) goto attr_err_out;
+
+       ret = nla_put_u32(skb, INOTIFY_NL_A_WD, wd);
+       if (ret) goto attr_err_out;
+
+
+       ret = nla_put_u32(skb, INOTIFY_NL_A_MASK, mask);
+       if (ret) goto attr_err_out;
+
+       ret = nla_put_string(skb, INOTIFY_NL_A_PATH, path);
+       if (ret) goto attr_err_out;
+
+       genlmsg_end(skb, msg_head);
+
+       genlmsg_multicast(skb, 0, inotify_genl_family.id, GFP_KERNEL);
+
+       return;
+attr_err_out:
+       printk(KERN_ERR "VFS: Error when writing attributes to inotify
add wd netlink message!\n");
+err_out:
+       kfree_skb(skb);
+}
+EXPORT_SYMBOL(inotify_send_add_message);
+
+/**
+ * inotify_send_remove_message
+ * @fd: inotify fd
+ * @wd: watch descriptor
+ *
+ */
+
+void inotify_send_remove_message(u32 fd, u32 wd)
+{
+       static atomic_t seq;
+       struct sk_buff *skb;
+       void *msg_head;
+       int ret;
+       int msg_size = 3 * nla_total_size(sizeof(u32));
+
+       skb = genlmsg_new(msg_size, GFP_KERNEL);
+
+       if (!skb) {
+
+               printk(KERN_ERR "VFS: Not enough memory to send
inotify remove wd netlink message.\n");
+               return;
+
+       }
+
+       msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq),
+                       &inotify_genl_family, 0, INOTIFY_NL_C_REMOVE_MESSAGE);
+
+       if (!msg_head) {
+
+               printk(KERN_ERR "VFS: Cannot store netlink header in
inotify remove wd netlink message.\n");
+               goto err_out;
+
+       }
+
+       ret = nla_put_u32(skb, INOTIFY_NL_A_PID, current->pid);
+       if (ret) goto attr_err_out;
+
+       ret = nla_put_u32(skb, INOTIFY_NL_A_FD, fd);
+       if (ret) goto attr_err_out;
+
+       ret = nla_put_u32(skb, INOTIFY_NL_A_WD, wd);
+       if (ret) goto attr_err_out;
+
+       genlmsg_end(skb, msg_head);
+
+       genlmsg_multicast(skb, 0, inotify_genl_family.id, GFP_KERNEL);
+
+       return;
+attr_err_out:
+       printk(KERN_ERR "VFS: Error when writing attributes to inotify
remove wd netlink message\n");
+err_out:
+       kfree_skb(skb);
+}
+EXPORT_SYMBOL(inotify_send_remove_message);
+
+
+
+
+static int __init inotify_init(void)
+{
+       if (genl_register_family(&inotify_genl_family) != 0)
+               printk(KERN_ERR"VFS: Failed to create inotify_user
netlink interface.\n");
+       return 0;
+};
+
+module_init(inotify_init);
diff --git a/include/linux/inotify.h b/include/linux/inotify.h
index d33041e..4ad0b4f 100644
--- a/include/linux/inotify.h
+++ b/include/linux/inotify.h
@@ -84,4 +84,44 @@ extern struct ctl_table inotify_table[]; /* for sysctl */

 #endif

+/* commands */
+
+enum {
+       INOTIFY_NL_C_UNSPEC,
+       INOTIFY_NL_C_ADD_MESSAGE,
+       INOTIFY_NL_C_REMOVE_MESSAGE,
+       __INOTIFY_NL_C_MAX,
+};
+
+#define INOTIFY_NL_C_MAX (__INOTIFY_NL_C_MAX - 1)
+
+/* attributes */
+
+enum {
+       INOTIFY_NL_A_UNSPEC,
+       INOTIFY_NL_A_PID,
+       INOTIFY_NL_A_FD,
+       INOTIFY_NL_A_WD,
+       INOTIFY_NL_A_MASK,
+       INOTIFY_NL_A_PATH,
+       __INOTIFY_NL_A_MAX,
+};
+
+#define INOTIFY_NL_A_MAX (__INOTIFY_NL_A_MAX - 1)
+
+
+#ifdef CONFIG_INOTIFY_USER_NETLINK_INTERFACE
+extern void inotify_send_add_message(u32 fd, u32 wd, u32 mask, const
char *path);
+extern void inotify_send_remove_message(u32 fd, u32 wd);
+#else
+static inline void inotify_send_add_message(u32 fd, u32 wd, u32 mask,
const char *path)
+{
+       return;
+}
+static inline void inotify_send_remove_message(u32 fd, u32 wd);
+{
+       return;
+}
+#endif /* CONFIG_INOTIFY_USER_NETLINK_INTERFACE */
+
 #endif /* _LINUX_INOTIFY_H */

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2012-01-07 21:13 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-07 13:36 [PATCH] VFS/inotify: send netlink messages when an inotify watch has been set or removed Stef Bon
2012-01-07 14:38 ` Al Viro
2012-01-07 15:03   ` Stef Bon
2012-01-07 15:42     ` Al Viro
2012-01-07 15:57     ` Al Viro
2012-01-07 16:59       ` Stef Bon
2012-01-07 19:05         ` Al Viro
2012-01-07 21:13           ` Stef Bon
  -- strict thread matches above, loose matches on Subject: below --
2012-01-05 20:56 Stef Bon
2012-01-06 14:13 ` Stef Bon

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