linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* file change notification
@ 2002-11-01 21:31 Colin Burnett
  2002-11-01 22:19 ` Chris Wright
  0 siblings, 1 reply; 19+ messages in thread
From: Colin Burnett @ 2002-11-01 21:31 UTC (permalink / raw)
  To: LKML

Is there notification to processes on file change?

If there is, I can't seem to find any good docs on the web.  If there's not,
what's the arguement for or against implementing it (or has no one got around to
doing it)? :)

-- 


Colin Burnett

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

* Re: file change notification
  2002-11-01 21:31 file " Colin Burnett
@ 2002-11-01 22:19 ` Chris Wright
  2002-11-02 15:43   ` Jamie Lokier
  0 siblings, 1 reply; 19+ messages in thread
From: Chris Wright @ 2002-11-01 22:19 UTC (permalink / raw)
  To: Colin Burnett; +Cc: LKML

* Colin Burnett (cburnett@fractal.candysporks.org) wrote:
> Is there notification to processes on file change?

have you looked at dnotify? Documentation/dnotify.txt

-chris

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

* Re: file change notification
  2002-11-01 22:19 ` Chris Wright
@ 2002-11-02 15:43   ` Jamie Lokier
  0 siblings, 0 replies; 19+ messages in thread
From: Jamie Lokier @ 2002-11-02 15:43 UTC (permalink / raw)
  To: Colin Burnett, LKML

Chris Wright wrote:
> * Colin Burnett (cburnett@fractal.candysporks.org) wrote:
> > Is there notification to processes on file change?
> 
> have you looked at dnotify? Documentation/dnotify.txt

dnotify is better than file notification if you're monitoring a lot of
files in a directory which change rarely.  On the other hand it's
quite bad if you're monitoring a few files and other files in the
directory are changing often.

Still, it works.

-- Jamie

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

* File change notification
@ 2003-12-31 16:42 Rüdiger Klaehn
  2003-12-31 18:20 ` Javier Fernandez-Ivern
                   ` (3 more replies)
  0 siblings, 4 replies; 19+ messages in thread
From: Rüdiger Klaehn @ 2003-12-31 16:42 UTC (permalink / raw)
  To: viro; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3476 bytes --]

Hi everybody.

This is my first post to lkml, so please be patient with me

I have been wondering for some time why there is no decent file change 
notification mechanism in linux. Is there some deep philosophical reason 
for this, or is it just that nobody has found the time to implement it? 
If it is the latter, I am willing to implement it as long there is a 
chance to get this accepted into the mainstream kernel.

Is there already somebody working on this problem? I know a few efforts 
that try to do something similar, but they all work by intercepting 
every single system call that has to do with files, and they are thus 
not very fast. See for example
<http://www.bangstate.com/software.html#changedfiles>
<http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/openxdsm/openxdsm/eventmodule/> 


The dnotify mechanism is very limited since it requires a file handle, 
it is not working for whole directory trees and it does not report much 
useful information. For example to watch for changes in the /home tree 
you would have to open every single directory in the tree, which would 
probably not even work since it would require more than the maximum 
number of file handles. If you have a directory with many files in it, 
the only thing dnotify tells you is that something has changed in the 
directory, so you have to rescan the whole directory to find out which 
file has changed. Kind of defeats the purpose of change notification...

What I would like to have would be some way to watch for certain changes 
anywhere in a whole tree or even the whole file system. This new 
mechanism should have no measurable performance impact and should log 
all information that is readily available. The amount of new code in 
kernel space should be as small as possible. So complicated stuff like 
pattern matching would have to happen in user space.

I wrote some experimental mechanism yesterday. Whenever a file is 
accessed or changed, I write all easily available information to a ring 
buffer which is presented to user space as a device. The information 
that is easily available is the inode number of the file or directory 
that has changed, the inode number of the directory in which the change 
took place, and in most cases the name of the dentry of the file that 
has changed.

Here is the struct I use for logging:

typedef struct
{
   unsigned long event; /* the type of change. As of now, I use the same 
constants as dnotify */
   unsigned long file_ino; /* the inode of the file that has changed (if 
available) */
   unsigned long src_ino; /* the inode of the directory in which the 
change took place (if available) */
   unsigned long dst_ino; /* the inode of the destination directory. 
This is only used when logging moves */
   unsigned char name[DNAME_LEN]; /* the name of the dentry of the 
changed file. This is simply truncated if it is too long. */
} inotify_info;

Information that is not easily available and therefore not logged 
includes the full path(s) of the changed file/directory. If you want or 
need that, you will have to look it up in user space.

Since I only log information that can be gathered at practically no 
cost, the logging does not take any noticeable time in kernel space.

I attached a patch containing the code I wrote yesterday. This is very 
preliminary and probably not bug-free. I would like to have feedback on 
the general approach before I spend more time refining this.

best regards,

    Rüdiger Klaehn



[-- Attachment #2: inotify-patch --]
[-- Type: text/plain, Size: 9744 bytes --]

diff -urN -X dontdiff vanilla/fs/dnotify.c develop/fs/dnotify.c
--- vanilla/fs/dnotify.c	2003-10-17 23:43:00.000000000 +0200
+++ develop/fs/dnotify.c	2003-12-31 16:59:36.000000000 +0100
@@ -153,8 +153,9 @@
 void dnotify_parent(struct dentry *dentry, unsigned long event)
 {
 	struct dentry *parent;
-
 	spin_lock(&dentry->d_lock);
+	/* call inotify for this dentry */
+	inotify_dentrychange(dentry,event);
 	parent = dentry->d_parent;
 	if (parent->d_inode->i_dnotify_mask & event) {
 		dget(parent);
diff -urN -X dontdiff vanilla/fs/inotify.c develop/fs/inotify.c
--- vanilla/fs/inotify.c	1970-01-01 01:00:00.000000000 +0100
+++ develop/fs/inotify.c	2003-12-31 16:59:39.000000000 +0100
@@ -0,0 +1,306 @@
+/*
+ * Inode notifications for Linux.
+ *
+ * Copyright (C) 2003,2004 Rüdiger Klaehn
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/smp_lock.h>
+#include <asm/segment.h>
+
+#define BUFFER_LEN 512
+#define DNAME_LEN 32
+#define IGNORE_LEN 16
+#define DEBUG 2
+
+typedef struct
+{
+	unsigned long event;
+	unsigned long file_ino;
+	unsigned long src_ino;
+	unsigned long dst_ino;
+	unsigned char name[DNAME_LEN];
+} in_info;
+
+/* The ring buffer. Statically allocated as of now */
+in_info in_buffer[BUFFER_LEN];
+int in_buffer_head = 0;
+int in_buffer_tail = 0;
+spinlock_t in_lock = SPIN_LOCK_UNLOCKED;
+unsigned long lock_flags;
+unsigned long in_ignore[IGNORE_LEN];
+
+/* device info for the in device */
+static int in_major = 40;
+
+int add_ignore_ino(unsigned long ino)
+{
+	int i;
+	for(i=0;i<IGNORE_LEN;i++)
+		if(in_ignore[i]==0) 
+		{
+			in_ignore[i]=ino;
+			return 1;
+		}
+	return 0;
+}
+
+int remove_ignore_ino(unsigned long ino)
+{
+	int i;
+	for(i=0;i<IGNORE_LEN;i++)
+		if(in_ignore[i]==ino)
+		{
+			in_ignore[i]=0;
+			return 1;
+		}
+	return 0;
+}
+
+int test_ignore_ino(unsigned long ino)
+{
+	int i;
+	if(!ino)
+		return 1;
+	for(i=0;i<IGNORE_LEN;i++)
+		if(in_ignore[i]==ino)
+			return 1;
+	return 0;		
+}
+
+int in_get_from_buffer(in_info *info)
+{
+	spin_lock_irqsave(&in_lock, lock_flags);
+	if (in_buffer_head == in_buffer_tail)
+	{
+		spin_unlock_irqrestore( &in_lock, lock_flags );
+		return 0;
+	}
+	memcpy(info,&in_buffer[in_buffer_head],sizeof(in_info));
+	memset(&in_buffer[in_buffer_head],0,sizeof(in_info));
+	in_buffer_head++;
+	if(in_buffer_head == BUFFER_LEN) in_buffer_head=0;
+	spin_unlock_irqrestore( &in_lock, lock_flags );
+	return 1;
+}
+
+int in_put_to_buffer(in_info *info)
+{
+	#if DEBUG>2
+	printk("in: put_to_buffer: %ld %ld %ld %ld\n",
+		info->event,info->file_ino,info->src_ino,info->dst_ino);
+	#endif
+	spin_lock_irqsave(&in_lock, lock_flags);
+	if((in_buffer_tail + 1) == in_buffer_head || (
+		((in_buffer_tail + 1) == BUFFER_LEN) &&
+		( in_buffer_head == 0 ) ))
+	{
+		/* Buffer overrun. Drop one entry! */
+		in_buffer_head++;
+		if ( in_buffer_head == BUFFER_LEN )
+		{
+			in_buffer_head = 0;
+		}
+		/*signal changedfiles_buffer overrun*/
+		/*strncpy( (char *)changedfiles_buffer[cf_buffer_head], "!", 2);*/
+	}
+	memcpy(&in_buffer[in_buffer_tail],info,sizeof(in_info));
+	in_buffer_tail++;
+	if ( in_buffer_tail == BUFFER_LEN )
+		in_buffer_tail=0;
+	spin_unlock_irqrestore( &in_lock, lock_flags );
+	return 1;
+}
+
+/*
+void in_zero_buffer()
+{
+	int i;
+	for (i=0; i < BUFFER_LEN; i++)
+	{
+		memset(&in_buffer[i], 0, sizeof(in_info));
+	}
+	return;
+}
+*/
+
+int in_open_dev( struct inode *in,struct file * fi )
+{
+	MOD_INC_USE_COUNT;
+	add_ignore_ino(in->i_ino);
+#if DEBUG > 1
+	printk("inotify: in_open_dev() %ld\n",in->i_ino);
+#endif
+	return 0;
+}
+
+int in_close_dev( struct inode *in,struct file * fi )
+{
+#if DEBUG > 1
+	printk("inotify: in_close_dev() %ld\n",in->i_ino);
+#endif
+	remove_ignore_ino(in->i_ino);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+/*ssize_t changedfiles_read_dev( struct inode *in,
+				  struct file *fi,
+				  char * buf,
+				  unsigned long count ) */
+ssize_t in_read_dev( struct file *filep, char *buf, size_t count,loff_t *f_pos )
+{
+	in_info read_buf;
+	if(!in_get_from_buffer(&read_buf))
+		return 0;
+#if DEBUG>2
+	printk("inotify: got info from buffer\n");
+#endif
+	if(count>sizeof(in_info))
+		count=sizeof(in_info);
+	if(copy_to_user(buf,&read_buf,count))
+	{
+		printk("inotify:  copy_to_user failed\n");
+		return -EFAULT;
+	}
+#if DEBUG>2
+	printk("inotify: changedfiles_read_dev() returning");
+#endif
+	return count;
+}
+
+static struct file_operations in_fop = {
+  read: in_read_dev,
+  open: in_open_dev,
+  release: in_close_dev,
+};
+
+/*
+ * This function should be called whenever something changes on an inode
+ * where we do not have the dentry, such as reading and writing
+*/
+void inotify_inodechange(struct inode *inode, unsigned long event)
+{
+	in_info info;
+	memset(&info,0,sizeof(in_info));
+	if(test_ignore_ino(inode->i_ino))
+		return;
+	info.event=event;
+	info.file_ino=inode->i_ino;
+	info.src_ino=0;
+	info.dst_ino=0;
+	in_put_to_buffer(&info);
+}
+
+/*
+ * This function should be called when something changes about a dentry, such
+ * as attributes, creating, deleting, renaming etc.
+ */
+void inotify_dentrychange(struct dentry *dentry,unsigned long event)
+{
+	in_info info;
+	struct dentry *parent;
+	memset(&info,0,sizeof(in_info));
+	info.event=event;
+	spin_lock(&dentry->d_lock);
+	if(dentry->d_inode)
+		info.file_ino=dentry->d_inode->i_ino;
+	else
+		info.file_ino=0;
+	if(test_ignore_ino(info.file_ino))
+		goto ignore;
+	parent=dentry->d_parent;
+	if(parent!=dentry)
+	{
+		dget(parent);
+		info.src_ino=parent->d_inode->i_ino;
+		dput(parent);
+	}
+	else
+		info.src_ino=0;
+	if(test_ignore_ino(info.src_ino))
+		goto ignore;
+	info.dst_ino=0;
+	strncpy(info.name,dentry->d_name.name,DNAME_LEN);
+	spin_unlock(&dentry->d_lock);
+	in_put_to_buffer(&info);
+	return;
+ignore:
+	spin_unlock(&dentry->d_lock);
+	return;
+}
+
+/*
+ * This function should be called whenever a dentry is moved (after it is moved)
+ * This one needs a lot of work!
+ */
+void inotify_dentrymove(struct dentry *dentry,struct dentry *dsrc,unsigned long event)
+{
+/*	in_info info;
+	struct dentry *parent;
+	memset(&info,0,sizeof(in_info));
+	info.event=event;
+	spin_lock(&dentry->d_lock);
+	if(dentry->d_inode)
+		info.file_ino=dentry->d_inode->i_ino;
+	else
+		info.file_ino=0;
+	parent=dentry->d_parent;
+	if(parent!=dentry)
+	{
+		dget(parent);
+		info.dst_ino=parent->d_inode->i_ino;
+		dput(parent);
+	}
+	else
+		info.dst_ino=0;
+	strncpy(info.name,dentry->d_name.name,DNAME_LEN);
+	spin_unlock(&dentry->d_lock);
+	spin_lock(&dsrc->d_lock);
+	if(dsrc->d_inode)
+		info.src_ino=dsrc->d_inode->i_ino;
+	else
+		info.dst_ino=0;
+	spin_unlock(&dsrc->d_lock);
+	in_put_to_buffer(&info);*/
+}
+
+static int __init inotify_init(void)
+{
+#ifdef DEBUG
+	printk("initializing inotify subsystem...\n");
+#endif
+	int i;
+	for (i=0; i < BUFFER_LEN; i++)
+	{
+		memset(&in_buffer[i], 0, sizeof(in_info));
+	}
+	memset(&in_ignore,0,sizeof(in_ignore));
+	if ( register_chrdev(in_major, "inotify", &in_fop))
+		return -EIO;
+	return 0;
+}
+
+module_init(inotify_init)
diff -urN -X dontdiff vanilla/fs/Makefile develop/fs/Makefile
--- vanilla/fs/Makefile	2003-08-23 01:56:59.000000000 +0200
+++ develop/fs/Makefile	2003-12-31 16:59:36.000000000 +0100
@@ -10,7 +10,7 @@
 		namei.o fcntl.o ioctl.o readdir.o select.o fifo.o locks.o \
 		dcache.o inode.o attr.o bad_inode.o file.o dnotify.o \
 		filesystems.o namespace.o seq_file.o xattr.o libfs.o \
-		fs-writeback.o mpage.o direct-io.o aio.o
+		fs-writeback.o mpage.o direct-io.o aio.o inotify.o
 
 obj-$(CONFIG_EPOLL)		+= eventpoll.o
 obj-$(CONFIG_COMPAT)		+= compat.o
diff -urN -X dontdiff vanilla/include/linux/dnotify.h develop/include/linux/dnotify.h
--- vanilla/include/linux/dnotify.h	2003-04-07 19:30:34.000000000 +0200
+++ develop/include/linux/dnotify.h	2003-12-31 16:59:43.000000000 +0100
@@ -22,6 +22,8 @@
 
 static inline void inode_dir_notify(struct inode *inode, unsigned long event)
 {
+	/* call inotify for this inode */
+	inotify_inodechange(inode,event);
 	if ((inode)->i_dnotify_mask & (event))
 		__inode_dir_notify(inode, event);
 }
diff -urN -X dontdiff vanilla/include/linux/inotify.h develop/include/linux/inotify.h
--- vanilla/include/linux/inotify.h	1970-01-01 01:00:00.000000000 +0100
+++ develop/include/linux/inotify.h	2003-12-31 16:59:43.000000000 +0100
@@ -0,0 +1,17 @@
+/*
+ * Inode notification for Linux
+ *
+ * Copyright (C) 2003,2004 Rüdiger Klaehn
+ */
+
+#include <linux/fs.h>
+#define IN_ACCESS	0x00000001	/* Node accessed */
+#define IN_MODIFY	0x00000002	/* Node modified */
+#define IN_CREATE	0x00000004	/* Node created */
+#define IN_DELETE	0x00000008	/* Node removed */
+#define IN_RENAME	0x00000010	/* Node renamed */
+#define IN_ATTRIB	0x00000020	/* Node changed attibutes */
+
+extern void inotify_inodechange(struct inode *inode, unsigned long event);
+extern void inotify_dentrychange(struct dentry *dentry,unsigned long event);
+extern void inotify_dentrymove(struct dentry *dentry,struct dentry *dsrc,unsigned long event);

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

* Re: File change notification
  2003-12-31 16:42 File change notification Rüdiger Klaehn
@ 2003-12-31 18:20 ` Javier Fernandez-Ivern
  2003-12-31 18:48   ` Rüdiger Klaehn
  2003-12-31 20:49 ` Javier Fernandez-Ivern
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 19+ messages in thread
From: Javier Fernandez-Ivern @ 2003-12-31 18:20 UTC (permalink / raw)
  To: rudi; +Cc: viro, linux-kernel

Rüdiger Klaehn wrote:

> I have been wondering for some time why there is no decent file change 
> notification mechanism in linux. Is there some deep philosophical reason 
> for this, or is it just that nobody has found the time to implement it? 
> If it is the latter, I am willing to implement it as long there is a 
> chance to get this accepted into the mainstream kernel.

Well, there's fam.  But AFAIK that's all done in user space, and your 
approach would be significantly more efficient (as a matter of fact, fam 
could be modified to use your change device as a first level of 
notification.)

I'll be interested in testing this, or (if you wish) help get it done. 
I'm a kernel hacking newbie at the moment, but I have tinkered around 
enough with the VFS to be able to work on this.  Up to you.

-- 
Javier Fernandez-Ivern

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

* Re: File change notification
  2003-12-31 18:20 ` Javier Fernandez-Ivern
@ 2003-12-31 18:48   ` Rüdiger Klaehn
  2004-01-01  1:28     ` Michael Clark
  0 siblings, 1 reply; 19+ messages in thread
From: Rüdiger Klaehn @ 2003-12-31 18:48 UTC (permalink / raw)
  To: ivern; +Cc: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2460 bytes --]

Javier Fernandez-Ivern wrote:

> Rüdiger Klaehn wrote:
>
>> I have been wondering for some time why there is no decent file 
>> change notification mechanism in linux. Is there some deep 
>> philosophical reason for this, or is it just that nobody has found 
>> the time to implement it? If it is the latter, I am willing to 
>> implement it as long there is a chance to get this accepted into the 
>> mainstream kernel.
>
>
> Well, there's fam.  But AFAIK that's all done in user space, and your 
> approach would be significantly more efficient (as a matter of fact, 
> fam could be modified to use your change device as a first level of 
> notification.)
>
Fam is a user space library that has some nice features such as network 
transparent change notification. It currently uses the dnotify mechanism 
if the underlying kernel supports it, but as I mentioned the dnotify 
mechanism requires an open file handle and works only for single 
directories. If the underlying os does not support dnotify, fam resorts 
to polling for file changes (yuk!).

When I have the basics worked out for the new mechanism, one thing I 
would like to do is to modify the fam library to use it. That would be a 
good way to test it, and it would also immediately benefit the big 
desktop environments which use fam.

> I'll be interested in testing this, or (if you wish) help get it done. 
> I'm a kernel hacking newbie at the moment, but I have tinkered around 
> enough with the VFS to be able to work on this.  Up to you.
>
Any help is appreciated. At the moment I am quite happy about what is 
being logged, but I am not sure how to best expose this to the 
interested user space processes. A device was the easiest way, and so 
that is what I used. Other possibilities would be a file in /proc or 
something completely different. I got the impression that dbus might be 
useful for this, but I have no idea how to use it.

If you want to help me, just apply the patch and see wether it works for 
you. You could also take a look at the code and see if you see something 
completely broken.

best regards and a happy new year,

    Rüdiger

p.s. I attached a small test program. It just reads the contents of the 
/dev/inotify device and prints them in (somewhat) human readable form. 
For example to watch for changes in .txt files I would use inotify_test 
| grep txt. This would print out a line whenever a txt file anywhere on 
a system has been created or changed.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: inotify.h --]
[-- Type: text/x-chdr; name="inotify.h", Size: 562 bytes --]

/*
 * Inode notification for Linux
 *
 * Copyright (C) 2003,2004 Rüdiger Klaehn
 */

#define IN_ACCESS	0x00000001	/* Node accessed */
#define IN_MODIFY	0x00000002	/* Node modified */
#define IN_CREATE	0x00000004	/* Node created */
#define IN_DELETE	0x00000008	/* Node removed */
#define IN_RENAME	0x00000010	/* Node renamed */
#define IN_ATTRIB	0x00000020	/* Node changed attibutes */
#define DNAME_LEN 32

typedef struct
{
	unsigned long event;
	unsigned long file_ino;
	unsigned long src_ino;
	unsigned long dst_ino;
	unsigned char name[DNAME_LEN];
} in_info;

[-- Attachment #3: inotify_test.c --]
[-- Type: text/x-csrc, Size: 1001 bytes --]

#include <stdio.h>
#include "inotify.h"

void geteventname(unsigned long event,char *buffer,int n) 
{
	unsigned long events[6]=
	{
		IN_ACCESS,
		IN_MODIFY,
		IN_CREATE,
		IN_DELETE,
		IN_RENAME,
		IN_ATTRIB
	};
	const char *names[6]=
	{
		"IN_ACCESS",
		"IN_MODIFY",
		"IN_CREATE",
		"IN_DELETE",
		"IN_RENAME",
		"IN_ATTRIB"
	};
	int i;
	strncpy(buffer,"",n);
	for(i=0;i<6;i++)
	{
		if(event&events[i])
		{
			if(strlen(buffer)>0)
				strncat(buffer,"|",n);
			strncat(buffer,names[i],n);
		}
	}
}

int main()
{
	FILE *file;
	in_info info;
	int len;
	char eventname[256];
	file=fopen("/dev/inotify","rb");
	if(!file)
	{
		printf("Error: could not open /dev/inotify!\n");
		return -1;
	}

	while(1)
	{
		len=fread(&info,1,sizeof(info),file);
		if(len==sizeof(info)) {
			info.name[DNAME_LEN-1]=0;
			geteventname(info.event,eventname,255);	
			printf("%s %lu %lu %lu %s\n",
				eventname,
				info.file_ino,
				info.src_ino,
				info.dst_ino,
				info.name);
		}

		usleep(200);
	}
	fclose(file);
}

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

* Re: File change notification
       [not found]   ` <18TJE-1qL-3@gated-at.bofh.it>
@ 2003-12-31 19:30     ` René Scharfe
  0 siblings, 0 replies; 19+ messages in thread
From: René Scharfe @ 2003-12-31 19:30 UTC (permalink / raw)
  To: linux-kernel

Rüdiger Klaehn wrote:
> Any help is appreciated. At the moment I am quite happy about what is 
> being logged, but I am not sure how to best expose this to the 
> interested user space processes. A device was the easiest way, and so 
> that is what I used. Other possibilities would be a file in /proc or 
> something completely different. I got the impression that dbus might be 
> useful for this, but I have no idea how to use it.

Maybe relayfs is suitable for this task: http://www.opersys.com/relayfs/

Regards,
René

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

* Re: File change notification
  2003-12-31 16:42 File change notification Rüdiger Klaehn
  2003-12-31 18:20 ` Javier Fernandez-Ivern
@ 2003-12-31 20:49 ` Javier Fernandez-Ivern
  2004-01-01  9:02 ` Juergen Hasch
  2004-01-01 10:47 ` jw schultz
  3 siblings, 0 replies; 19+ messages in thread
From: Javier Fernandez-Ivern @ 2003-12-31 20:49 UTC (permalink / raw)
  To: rudi; +Cc: linux-kernel

Rüdiger Klaehn wrote:

Rudiger, I've been reading your code to try and understand it, and I 
found one think I'm not so sure about:

> +++ develop/fs/dnotify.c	2003-12-31 16:59:36.000000000 +0100
> @@ -153,8 +153,9 @@
>  void dnotify_parent(struct dentry *dentry, unsigned long event)
>  {
>  	struct dentry *parent;
> -
>  	spin_lock(&dentry->d_lock);
> +	/* call inotify for this dentry */
> +	inotify_dentrychange(dentry,event);

...

> +/*
> + * This function should be called when something changes about a dentry, such
> + * as attributes, creating, deleting, renaming etc.
> + */
> +void inotify_dentrychange(struct dentry *dentry,unsigned long event)
> +{
> +	in_info info;
> +	struct dentry *parent;
> +	memset(&info,0,sizeof(in_info));
> +	info.event=event;
> +	spin_lock(&dentry->d_lock);

inotify_dentrychange() is called from dnotify_parent() with the 
dentry->d_lock spinlock held.  However, it also tries to attain the 
spinlock.  Wouldn't this deadlock?  I thought spinlocks were not recursive.

Please let me know if I'm not understanding this...I'm a locking newbie.

-- 
Javier Fernandez-Ivern

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

* Re: File change notification
  2003-12-31 18:48   ` Rüdiger Klaehn
@ 2004-01-01  1:28     ` Michael Clark
  2004-01-01  1:58       ` Dave Jones
  2004-01-01 13:11       ` Rüdiger Klaehn
  0 siblings, 2 replies; 19+ messages in thread
From: Michael Clark @ 2004-01-01  1:28 UTC (permalink / raw)
  To: rudi; +Cc: ivern, linux-kernel

On 01/01/04 02:48, Rüdiger Klaehn wrote:
> Javier Fernandez-Ivern wrote:
> 
>> Rüdiger Klaehn wrote:
>>
>>> I have been wondering for some time why there is no decent file 
>>> change notification mechanism in linux. Is there some deep 
>>> philosophical reason for this, or is it just that nobody has found 
>>> the time to implement it? If it is the latter, I am willing to 
>>> implement it as long there is a chance to get this accepted into the 
>>> mainstream kernel.
>>
>>
>>
>> Well, there's fam.  But AFAIK that's all done in user space, and your 
>> approach would be significantly more efficient (as a matter of fact, 
>> fam could be modified to use your change device as a first level of 
>> notification.)
>>
> Fam is a user space library that has some nice features such as network 
> transparent change notification. It currently uses the dnotify mechanism 
> if the underlying kernel supports it, but as I mentioned the dnotify 
> mechanism requires an open file handle and works only for single 
> directories. If the underlying os does not support dnotify, fam resorts 
> to polling for file changes (yuk!).

Have you had a look at dazuko. It provides a consistent file access
notification mechanism (and also intervention for denying access) across
linux and freebsd. It is currently being used by various on-access
virus scanners. It is under active development and supports 2.6 (and 2.4)

http://www.dazuko.org/about.shtml

Seems like a good idea. I've always thought it would be nice to use
something like this to maintain a dynamic locatedb (among many other
potential uses).

~mc


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

* Re: File change notification
  2004-01-01  1:28     ` Michael Clark
@ 2004-01-01  1:58       ` Dave Jones
  2004-01-01  2:18         ` Michael Clark
  2004-01-01 13:11       ` Rüdiger Klaehn
  1 sibling, 1 reply; 19+ messages in thread
From: Dave Jones @ 2004-01-01  1:58 UTC (permalink / raw)
  To: Michael Clark; +Cc: rudi, ivern, linux-kernel

On Thu, Jan 01, 2004 at 09:28:08AM +0800, Michael Clark wrote:
 > Have you had a look at dazuko. It provides a consistent file access
 > notification mechanism (and also intervention for denying access) across
 > linux and freebsd. It is currently being used by various on-access
 > virus scanners. It is under active development and supports 2.6 (and 2.4)

Candidate for "Wackiest sys_call_table patching 2004".
In a word "ick". Code not to be read on a full stomach.

		Dave

-- 
 Dave Jones     http://www.codemonkey.org.uk

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

* Re: File change notification
  2004-01-01  1:58       ` Dave Jones
@ 2004-01-01  2:18         ` Michael Clark
  2004-01-01  2:30           ` Javier Fernandez-Ivern
  0 siblings, 1 reply; 19+ messages in thread
From: Michael Clark @ 2004-01-01  2:18 UTC (permalink / raw)
  To: Dave Jones; +Cc: rudi, ivern, linux-kernel

On 01/01/04 09:58, Dave Jones wrote:
> On Thu, Jan 01, 2004 at 09:28:08AM +0800, Michael Clark wrote:
>  > Have you had a look at dazuko. It provides a consistent file access
>  > notification mechanism (and also intervention for denying access) across
>  > linux and freebsd. It is currently being used by various on-access
>  > virus scanners. It is under active development and supports 2.6 (and 2.4)
> 
> Candidate for "Wackiest sys_call_table patching 2004".
> In a word "ick". Code not to be read on a full stomach.

Oh well, hadn't read the kernel code yet. Although certainly the *goal* is
a good one - a cross platform interface for file change notification.

Yes I see what you mean after having a look. Would make sense to convert
this over to use only LSM hooks (which it appears to use already) if that
was possible - or maybe could be done using a VFS proxy filesystem that
monitors/relays calls to an underlying fs.

The userspace interface appears relatively sane with its chardev interface
although due to it's ability to intervene on file access, it creates a
single point of failure that can livelock the machine if the userspace
monitoring proccess dies. This could be worked around if the poilicy
was to go unmonitored in the case that the userspace process dies.

~mc


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

* Re: File change notification
  2004-01-01  2:18         ` Michael Clark
@ 2004-01-01  2:30           ` Javier Fernandez-Ivern
  0 siblings, 0 replies; 19+ messages in thread
From: Javier Fernandez-Ivern @ 2004-01-01  2:30 UTC (permalink / raw)
  To: Michael Clark; +Cc: Dave Jones, rudi, linux-kernel

Michael Clark wrote:

> Yes I see what you mean after having a look. Would make sense to convert
> this over to use only LSM hooks (which it appears to use already) if that
> was possible - or maybe could be done using a VFS proxy filesystem that
> monitors/relays calls to an underlying fs.

I don't think using LSM hooks for this is a good idea.  While it makes 
the changes less invasive, it forces you to enable LSM just to get file 
  change modifications.

-- 
Javier Fernandez-Ivern

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

* Re: File change notification
  2003-12-31 16:42 File change notification Rüdiger Klaehn
  2003-12-31 18:20 ` Javier Fernandez-Ivern
  2003-12-31 20:49 ` Javier Fernandez-Ivern
@ 2004-01-01  9:02 ` Juergen Hasch
  2004-01-01 10:47 ` jw schultz
  3 siblings, 0 replies; 19+ messages in thread
From: Juergen Hasch @ 2004-01-01  9:02 UTC (permalink / raw)
  To: rudi; +Cc: linux-kernel

Hi Rudi,

Am Mittwoch, 31. Dezember 2003 17:42 schrieb Rüdiger Klaehn:
>
> I wrote some experimental mechanism yesterday. Whenever a file is
> accessed or changed, I write all easily available information to a ring
> buffer which is presented to user space as a device. The information
> that is easily available is the inode number of the file or directory
> that has changed, the inode number of the directory in which the change
> took place, and in most cases the name of the dentry of the file that
> has changed.

I'm also interested in receiving file change notifications, especially
as I would like to get this working for Samba in a sane way.

However I don't think your approach would help me much. I simply don't
want to get every file being changed on the whole machine getting 
reported to me.
I don't want to look up the inode every time, just to know if it belongs
to a directory I'm interested in.

Actually I *like* dnotify being local to a given directory and having
a fd so I know where the signal I receive belongs to.

So my selfish reasoning makes me want either
- dnotify being able to pass some more information if requested
  (I actually tried this and it basically works, it is just too
   crappy to post here)
or
- make poll()/epoll() work for file/directory access

So much for what I want :-)

...Juergen


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

* Re: File change notification
  2003-12-31 16:42 File change notification Rüdiger Klaehn
                   ` (2 preceding siblings ...)
  2004-01-01  9:02 ` Juergen Hasch
@ 2004-01-01 10:47 ` jw schultz
  2004-01-01 12:44   ` Rüdiger Klaehn
  3 siblings, 1 reply; 19+ messages in thread
From: jw schultz @ 2004-01-01 10:47 UTC (permalink / raw)
  To: linux-kernel

On Wed, Dec 31, 2003 at 05:42:45PM +0100, Rüdiger Klaehn wrote:
> Hi everybody.
> 
> This is my first post to lkml, so please be patient with me
> 
> I have been wondering for some time why there is no decent file change 
> notification mechanism in linux. Is there some deep philosophical reason 
> for this, or is it just that nobody has found the time to implement it? 
> If it is the latter, I am willing to implement it as long there is a 
> chance to get this accepted into the mainstream kernel.
> 
> Is there already somebody working on this problem? I know a few efforts 
> that try to do something similar, but they all work by intercepting 
> every single system call that has to do with files, and they are thus 
> not very fast. See for example
> <http://www.bangstate.com/software.html#changedfiles>
> <http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/openxdsm/openxdsm/eventmodule/> 
> 
> 
> The dnotify mechanism is very limited since it requires a file handle, 
> it is not working for whole directory trees and it does not report much 
> useful information. For example to watch for changes in the /home tree 
> you would have to open every single directory in the tree, which would 
> probably not even work since it would require more than the maximum 
> number of file handles. If you have a directory with many files in it, 
> the only thing dnotify tells you is that something has changed in the 
> directory, so you have to rescan the whole directory to find out which 
> file has changed. Kind of defeats the purpose of change notification...
> 
> What I would like to have would be some way to watch for certain changes 
> anywhere in a whole tree or even the whole file system. This new 
> mechanism should have no measurable performance impact and should log 
> all information that is readily available. The amount of new code in 
> kernel space should be as small as possible. So complicated stuff like 
> pattern matching would have to happen in user space.
> 
> I wrote some experimental mechanism yesterday. Whenever a file is 
> accessed or changed, I write all easily available information to a ring 
> buffer which is presented to user space as a device. The information 
> that is easily available is the inode number of the file or directory 
> that has changed, the inode number of the directory in which the change 
> took place, and in most cases the name of the dentry of the file that 
> has changed.

hmm...


#ln tree1/sub/dir/file tree2/sub/dir/file
#watch_tree tree1 &
#do_something_to tree2/sub/dir/file

A dnotify can potentially know about open, chown, chmod,
utimes and possibly link of the files by watching the paths
and cwd; meaning it won't know about alternate paths.  How
is it to know about read, write, fchown, fchmod and
truncate?

Perhaps someone else has a more fertile imagination but
short of looking up all the file inode numbers of the tree
in question and watching that whole list this sounds futile.

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

* Re: File change notification
  2004-01-01 10:47 ` jw schultz
@ 2004-01-01 12:44   ` Rüdiger Klaehn
  2004-01-03  6:32     ` Jan Harkes
  0 siblings, 1 reply; 19+ messages in thread
From: Rüdiger Klaehn @ 2004-01-01 12:44 UTC (permalink / raw)
  To: jw schultz; +Cc: linux-kernel

jw schultz wrote:

[snip]

>hmm...
>
>
>#ln tree1/sub/dir/file tree2/sub/dir/file
>#watch_tree tree1 &
>#do_something_to tree2/sub/dir/file
>
>A dnotify can potentially know about open, chown, chmod,
>utimes and possibly link of the files by watching the paths
>and cwd; meaning it won't know about alternate paths.  How
>is it to know about read, write, fchown, fchmod and
>truncate?
>
>  
>
Take a look at fs/read_write.c. There are calls to dnotify_parent in all 
file operation functions. There is a comment in fs/dnotify.c which says 
that dnotify_parent is "hopelessly wrong, but unfixable without API 
changes". Another good reason for a new file change notification api...

The only thing I am not so sure about is mmap. I think a mmapped file 
will not create change notifications.

>Perhaps someone else has a more fertile imagination but
>short of looking up all the file inode numbers of the tree
>in question and watching that whole list this sounds futile.
>  
>
Whats wrong with that? You would just have to know the inode numbers of 
all directories in the subtree you are interested in. Then you can do a 
really fast inode->name translation using a hashtable or something. At 
least it is much more lightweight than having to open all directories :-)

I think that it is much cleaner and faster to report the inode numbers 
of the changed files since inode numbers are unique per filesystem and 
they are immediately available. The complicated mapping of inodes to 
path names should happen in user space only for the files the userspace 
process is interested in.


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

* Re: File change notification
  2004-01-01  1:28     ` Michael Clark
  2004-01-01  1:58       ` Dave Jones
@ 2004-01-01 13:11       ` Rüdiger Klaehn
  1 sibling, 0 replies; 19+ messages in thread
From: Rüdiger Klaehn @ 2004-01-01 13:11 UTC (permalink / raw)
  To: Michael Clark; +Cc: linux-kernel

Michael Clark wrote:

> On 01/01/04 02:48, Rüdiger Klaehn wrote:
>
>> Javier Fernandez-Ivern wrote:
>>
>>> Rüdiger Klaehn wrote:
>>>
>>>> I have been wondering for some time why there is no decent file 
>>>> change notification mechanism in linux. Is there some deep 
>>>> philosophical reason for this, or is it just that nobody has found 
>>>> the time to implement it? If it is the latter, I am willing to 
>>>> implement it as long there is a chance to get this accepted into 
>>>> the mainstream kernel.
>>>
>>>
>>>
>>>
>>> Well, there's fam.  But AFAIK that's all done in user space, and 
>>> your approach would be significantly more efficient (as a matter of 
>>> fact, fam could be modified to use your change device as a first 
>>> level of notification.)
>>>
>> Fam is a user space library that has some nice features such as 
>> network transparent change notification. It currently uses the 
>> dnotify mechanism if the underlying kernel supports it, but as I 
>> mentioned the dnotify mechanism requires an open file handle and 
>> works only for single directories. If the underlying os does not 
>> support dnotify, fam resorts to polling for file changes (yuk!).
>
>
> Have you had a look at dazuko. It provides a consistent file access
> notification mechanism (and also intervention for denying access) across
> linux and freebsd. It is currently being used by various on-access
> virus scanners. It is under active development and supports 2.6 (and 2.4) 

This seems to be a descendant of this one: 
<http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/openxdsm/openxdsm/eventmodule/>

It works, but it is a slow and ugly hack to just hook into every syscall 
that does something with files. And it is quite slow and ambiguous to 
log paths instead of inodes since file paths are not unique (hard links 
etc).

But I will take a look at that code to see how they get the events to 
user space.

>
> Seems like a good idea. I've always thought it would be nice to use
> something like this to maintain a dynamic locatedb (among many other
> potential uses).
>
File change notification would be immensely useful. I think there is a 
consensus about that.



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

* Re: File change notification
  2004-01-01 12:44   ` Rüdiger Klaehn
@ 2004-01-03  6:32     ` Jan Harkes
  0 siblings, 0 replies; 19+ messages in thread
From: Jan Harkes @ 2004-01-03  6:32 UTC (permalink / raw)
  To: linux-kernel

On Thu, Jan 01, 2004 at 01:44:01PM +0100, R?diger Klaehn wrote:
> I think that it is much cleaner and faster to report the inode numbers 
> of the changed files since inode numbers are unique per filesystem and 
> they are immediately available. The complicated mapping of inodes to 

Inode number are not necessarily unique per filesystem. Any filesystem
that uses iget4 can have several objects that have the same inode
number. For instance, Coda uses 128-bit file-identifiers and the i_ino
number is a simple hash that is 'typically' unique. There are also
filesystems that invent inode numbers whenever inodes are brought into
the cache, but which have no persistency when the inode_cache is pruned.
So the next time you see the same object, it could have a different
(unique) inode number.

Returning paths is probably also not quite that easy when you only have
the inode. Because of hardlinks we can have several paths (aliases) that
lead to the same object, but the kernel does not necessarily have all of
those paths available in the dcache.

Jan

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

* Re: File change notification
@ 2004-02-07  8:29 John Ogness
  2004-02-07 14:01 ` Christoph Hellwig
  0 siblings, 1 reply; 19+ messages in thread
From: John Ogness @ 2004-02-07  8:29 UTC (permalink / raw)
  To: Dave Jones; +Cc: Michael Clark, linux-kernel

On 01/01/04 09:58, Dave Jones wrote:
 > On Thu, Jan 01, 2004 at 09:28:08AM +0800, Michael Clark wrote:
 > > Have you had a look at dazuko. It provides a consistent file access
 > > notification mechanism (and also intervention for denying access)
 > > across linux and freebsd. It is currently being used by various
 > > on-access virus scanners. It is under active development and
 > > supports 2.6 (and 2.4)
 >
 > Candidate for "Wackiest sys_call_table patching 2004".
 > In a word "ick". Code not to be read on a full stomach.

Hi,

I am the current maintainer of Dazuko. Could you please explain your 
"wackiest 2004" comment? Do you know of a better way to intercept system 
calls for 2.2/2.4 kernels *without* patching the kernel source?

System call hooking is all-around ugly, but unfortunately most operating 
systems don't provide a real mechanism for file access control. With the 
2.6 kernel, Dazuko uses LSM. This is much more elegant and much safer. 
Yes, users have to turn LSM on, but this does not require kernel patches 
(and many distributions are turning this feature on by default).

I would appreciate any feedback you may have about how it could be 
improved. Keep in mind, I refuse to do anything that requires kernel 
source patching.

John Ogness

-- 
Dazuko Maintainer


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

* Re: File change notification
  2004-02-07  8:29 John Ogness
@ 2004-02-07 14:01 ` Christoph Hellwig
  0 siblings, 0 replies; 19+ messages in thread
From: Christoph Hellwig @ 2004-02-07 14:01 UTC (permalink / raw)
  To: John Ogness; +Cc: Dave Jones, Michael Clark, linux-kernel

On Sat, Feb 07, 2004 at 09:29:12AM +0100, John Ogness wrote:
> I am the current maintainer of Dazuko. Could you please explain your 
> "wackiest 2004" comment? Do you know of a better way to intercept system 
> calls for 2.2/2.4 kernels *without* patching the kernel source?

better implies it's good - it isn't.  In fact it's plain wrong for any
kernel.  Do a stackable filesystem if you want to intercept filesystem
calls.


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

end of thread, other threads:[~2004-02-07 14:01 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-12-31 16:42 File change notification Rüdiger Klaehn
2003-12-31 18:20 ` Javier Fernandez-Ivern
2003-12-31 18:48   ` Rüdiger Klaehn
2004-01-01  1:28     ` Michael Clark
2004-01-01  1:58       ` Dave Jones
2004-01-01  2:18         ` Michael Clark
2004-01-01  2:30           ` Javier Fernandez-Ivern
2004-01-01 13:11       ` Rüdiger Klaehn
2003-12-31 20:49 ` Javier Fernandez-Ivern
2004-01-01  9:02 ` Juergen Hasch
2004-01-01 10:47 ` jw schultz
2004-01-01 12:44   ` Rüdiger Klaehn
2004-01-03  6:32     ` Jan Harkes
  -- strict thread matches above, loose matches on Subject: below --
2004-02-07  8:29 John Ogness
2004-02-07 14:01 ` Christoph Hellwig
     [not found] <18PG9-4og-27@gated-at.bofh.it>
     [not found] ` <18TgF-QJ-7@gated-at.bofh.it>
     [not found]   ` <18TJE-1qL-3@gated-at.bofh.it>
2003-12-31 19:30     ` René Scharfe
2002-11-01 21:31 file " Colin Burnett
2002-11-01 22:19 ` Chris Wright
2002-11-02 15:43   ` Jamie Lokier

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