Skip to contentSkip to conversation

latest inotify.

PATCH In review Robert Love 3 participants 7 messages Jun 28, 2005 – Jun 30, 2005

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 latest inotify.

Below is the latest inotify patch, against 2.6.12.

I incorporated Andrew's FAQ patch from 2.6-mm, plus a couple of other documentation updates.

Also, skip over I_FREEING inodes on unmount.

Robert Love

inotify!

inotify is intended to correct the deficiencies of dnotify, particularly its inability to scale and its terrible user interface:

* dnotify requires the opening of one fd per each directory that you intend to watch. This quickly results in too many open files and pins removable media, preventing unmount.
* dnotify is directory-based. You only learn about changes to directories. Sure, a change to a file in a directory affects the directory, but you are then forced to keep a cache of stat structures.
* dnotify's interface to user-space is awful. Signals?

inotify provides a more usable, simple, powerful solution to file change notification:

* inotify's interface is a device node, not SIGIO. You open a single fd to the device node, which is select()-able.
* inotify has an event that says "the filesystem that the item you were watching is on was unmounted."
* inotify can watch directories or files.

Inotify is currently used by Beagle (a desktop search infrastructure), Gamin (a FAM replacement), and other projects.

See Documentation/filesystems/inotify.txt.

 Documentation/filesystems/inotify.txt |  155 +++++
 fs/Kconfig                            |   13 
 fs/Makefile                           |    1 
 fs/attr.c                             |   33 -
 fs/compat.c                           |   12 
 fs/file_table.c                       |    3 
 fs/inode.c                            |    6 
 fs/inotify.c                          |  984 ++++++++++++++++++++++++++++++++++
 fs/namei.c                            |   30 -
 fs/nfsd/vfs.c                         |    6 
 fs/open.c                             |    4 
 fs/read_write.c                       |   15 
 fs/sysfs/file.c                       |    7 
 fs/xattr.c                            |    5 
 include/linux/fs.h                    |    6 
 include/linux/fsnotify.h              |  257 ++++++++
 include/linux/inotify.h               |  124 ++++
 include/linux/sched.h                 |    4 
 kernel/user.c                         |    4 
 19 files changed, 1605 insertions(+), 64 deletions(-)
Documentation/filesystems/inotify.txt +155 -0
diff -urN linux-2.6.12/Documentation/filesystems/inotify.txt linux/Documentation/filesystems/inotify.txt
@@ -0,0 +1,155 @@
+				    inotify
+	     a powerful yet simple file change notification system
+
+
+
+Document started 15 Mar 2005 by Robert Love <[email protected]>
+
+(i) User Interface
+
+Inotify is controlled by a device node, /dev/inotify.  If you do not use udev,
+this device may need to be created manually.
+
+First step in using inotify is to open the device file:
+
+	int dev_fd = open ("/dev/inotify", O_RDONLY);
+
+Change events are managed by "watches".  A watch is an (object,mask) pair where
+the object is a file or directory and the mask is a bitmask of one or more
+inotify events that the application wishes to receive.  See <linux/inotify.h>
+for valid events.  A watch is referenced by a watch descriptor, or wd.
+
+Watches are added via a file descriptor to the file.
+
+Watches on a directory will return events on any files inside of the directory.
+
+Adding a watch is simple,
+
+	/* 'wd' represents the watch on fd with mask */
+	struct inotify_request req = { fd, mask };
+	int wd = ioctl (dev_fd, INOTIFY_WATCH, &req);
+
+You can add a large number of files via something like
+
+	for each file to watch {
+		struct inotify_request req;
+		int file_fd;
+
+		file_fd = open (file, O_RDONLY);
+		if (fd < 0) {
+			perror ("open");
+			break;
+		}
+
+		req.fd = file_fd;
+		req.mask = mask;
+
+		wd = ioctl (dev_fd, INOTIFY_WATCH, &req);
+
+		close (fd);
+	}
+
+You can update an existing watch in the same manner, by passing in a new mask.
+
+An existing watch is removed via the INOTIFY_IGNORE ioctl, for example
+
+	ioctl (dev_fd, INOTIFY_IGNORE, wd);
+
+Events are provided in the form of an inotify_event structure that is read(2)
+from /dev/inotify.  The filename is of dynamic length and follows the struct.
+It is of size len.  The filename is padded with null bytes to ensure proper
+alignment.  This padding is reflected in len.
+
+You can slurp multiple events by passing a large buffer, for example
+
+	size_t len = read (fd, buf, BUF_LEN);
+
+Will return as many events as are available and fit in BUF_LEN.
+
+/dev/inotify is also select()- and poll()-able.
+
+You can find the size of the current event queue via the FIONREAD ioctl.
+
+All watches are destroyed and cleaned up on close.
+
+
+(ii) Internal Kernel Implementation
+
+Each open inotify device is associated with an inotify_device structure.
+
+Each watch is associated with an inotify_watch structure.  Watches are chained
+off of each associated device and each associated inode.
+
+See fs/inotify.c for the locking and lifetime rules.
+
+
+(iii) Rationale
+
+Q: What is the design decision behind not tying the watch to the open fd of
+   the watched object?
+
+A: Watches are associated with an open inotify device, not an open file.
+   This solves the primary problem with dnotify: keeping the file open pins
+   the file and thus, worse, pins the mount.  Dnotify is therefore infeasible
+   for use on a desktop system with removable media as the media cannot be
+   unmounted.
+
+Q: What is the design decision behind using an-fd-per-device as opposed to
+   an fd-per-watch?
+
+A: An fd-per-watch quickly consumes more file descriptors than are allowed,
+   more fd's than are feasible to manage, and more fd's than are optimally
+   select()-able.  Yes, root can bump the per-process fd limit and yes, users
+   can use epoll, but requiring both is a silly and extraneous requirement.
+   A watch consumes less memory than an open file, separating the number
+   spaces is thus sensible.  The current design is what user-space developers
+   want: Users open the device, once, and add n watches, requiring but one fd
+   and no twiddling with fd limits.  Opening /dev/inotify two thousand times
+   is silly.  If we can implement user-space's preferences cleanly--and we
+   can, the idr layer makes stuff like this trivial--then we should.
+
+   There are other good arguments.  With a single fd, there is a single
+   item to block on, which is mapped to a single queue of events.  The single
+   fd returns all watch events and also any potential out-of-band data.  If
+   every fd was a separate watch,
+
+   - There would be no way to get event ordering.  Events on file foo and
+     file bar would pop poll() on both fd's, but there would be no way to tell
+     which happened first.  A single queue trivially gives you ordering.  Such
+     ordering is crucial to existing applications such as Beagle.  Imagine
+     "mv a b ; mv b a" events without ordering.
+
+   - We'd have to maintain n fd's and n internal queues with state,
+     versus just one.  It is a lot messier in the kernel.  A single, linear
+     queue is the data structure that makes sense.
+
+   - User-space developers prefer the current API.  The Beagle guys, for
+     example, love it.  Trust me, I asked.  It is not a surprise: Who'd want
+     to manage and block on 1000 fd's via select?
+
+   - You'd have to manage the fd's, as an example: Call close() when you
+     received a delete event.
+
+   - No way to get out of band data.
+
+   - 1024 is still too low.  ;-)
+
+   When you talk about designing a file change notification system that
+   scales to 1000s of directories, juggling 1000s of fd's just does not seem
+   the right interface.  It is too heavy.
+
+Q: Why a device node?
+
+A: The second biggest problem with dnotify is that the user interface sucks
+   ass.  Signals are a terrible, terrible interface for file notification.  Or
+   for anything, for that matter.  The idea solution, from all perspectives,
+   is a file descriptor-based one that allows basic file I/O and poll/select.
+   Obtaining the fd and managing the watches could of been done either via a
+   device file or a family of new system calls.  We decided to implement a
+   device file because adding three or four new system calls that mirrored
+   open, close, and ioctl seemed silly.  A character device makes sense from
+   user-space and was easy to implement inside of the kernel.
+
+   Additionally, it _is_ possible to open /dev/inotify more than once and
+   juggle more than one queue and thus more than one associated fd.
+
fs/attr.c +4 -29
diff -urN linux-2.6.12/fs/attr.c linux/fs/attr.c
@@ -10,7 +10,7 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/smp_lock.h>
-#include <linux/dnotify.h>
+#include <linux/fsnotify.h>
 #include <linux/fcntl.h>
 #include <linux/quotaops.h>
 #include <linux/security.h>
@@ -107,31 +107,8 @@
 out:
 	return error;
 }
-
 EXPORT_SYMBOL(inode_setattr);
 
-int setattr_mask(unsigned int ia_valid)
-{
-	unsigned long dn_mask = 0;
-
-	if (ia_valid & ATTR_UID)
-		dn_mask |= DN_ATTRIB;
-	if (ia_valid & ATTR_GID)
-		dn_mask |= DN_ATTRIB;
-	if (ia_valid & ATTR_SIZE)
-		dn_mask |= DN_MODIFY;
-	/* both times implies a utime(s) call */
-	if ((ia_valid & (ATTR_ATIME|ATTR_MTIME)) == (ATTR_ATIME|ATTR_MTIME))
-		dn_mask |= DN_ATTRIB;
-	else if (ia_valid & ATTR_ATIME)
-		dn_mask |= DN_ACCESS;
-	else if (ia_valid & ATTR_MTIME)
-		dn_mask |= DN_MODIFY;
-	if (ia_valid & ATTR_MODE)
-		dn_mask |= DN_ATTRIB;
-	return dn_mask;
-}
-
 int notify_change(struct dentry * dentry, struct iattr * attr)
 {
 	struct inode *inode = dentry->d_inode;
@@ -197,11 +174,9 @@
 	if (ia_valid & ATTR_SIZE)
 		up_write(&dentry->d_inode->i_alloc_sem);
 
-	if (!error) {
-		unsigned long dn_mask = setattr_mask(ia_valid);
-		if (dn_mask)
-			dnotify_parent(dentry, dn_mask);
-	}
+	if (!error)
+		fsnotify_change(dentry, ia_valid);
+
 	return error;
 }
 
fs/compat.c +8 -4
diff -urN linux-2.6.12/fs/compat.c linux/fs/compat.c
@@ -37,7 +37,7 @@
 #include <linux/ctype.h>
 #include <linux/module.h>
 #include <linux/dirent.h>
-#include <linux/dnotify.h>
+#include <linux/fsnotify.h>
 #include <linux/highuid.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
@@ -1307,9 +1307,13 @@
 out:
 	if (iov != iovstack)
 		kfree(iov);
-	if ((ret + (type == READ)) > 0)
-		dnotify_parent(file->f_dentry,
-				(type == READ) ? DN_ACCESS : DN_MODIFY);
+	if ((ret + (type == READ)) > 0) {
+		struct dentry *dentry = file->f_dentry;
+		if (type == READ)
+			fsnotify_access(dentry);
+		else
+			fsnotify_modify(dentry);
+	}
 	return ret;
 }
 
fs/file_table.c +3 -0
diff -urN linux-2.6.12/fs/file_table.c linux/fs/file_table.c
@@ -16,6 +16,7 @@
 #include <linux/eventpoll.h>
 #include <linux/mount.h>
 #include <linux/cdev.h>
+#include <linux/fsnotify.h>
 
 /* sysctl tunables... */
 struct files_stat_struct files_stat = {
@@ -123,6 +124,8 @@
 	struct inode *inode = dentry->d_inode;
 
 	might_sleep();
+
+	fsnotify_close(file);
 	/*
 	 * The function eventpoll_release() should be the first called
 	 * in the file cleanup chain.
fs/inode.c +6 -0
diff -urN linux-2.6.12/fs/inode.c linux/fs/inode.c
@@ -21,6 +21,7 @@
 #include <linux/pagemap.h>
 #include <linux/cdev.h>
 #include <linux/bootmem.h>
+#include <linux/inotify.h>
 
 /*
  * This is needed for the following functions:
@@ -202,6 +203,10 @@
 	INIT_LIST_HEAD(&inode->i_data.i_mmap_nonlinear);
 	spin_lock_init(&inode->i_lock);
 	i_size_ordered_init(inode);
+#ifdef CONFIG_INOTIFY
+	INIT_LIST_HEAD(&inode->inotify_watches);
+	sema_init(&inode->inotify_sem, 1);
+#endif
 }
 
 EXPORT_SYMBOL(inode_init_once);
@@ -346,6 +351,7 @@
 
 	down(&iprune_sem);
 	spin_lock(&inode_lock);
+	inotify_unmount_inodes(&sb->s_inodes);
 	busy = invalidate_list(&sb->s_inodes, &throw_away);
 	spin_unlock(&inode_lock);
 

Files linux-2.6.12/fs/.inode.c.swp and linux/fs/.inode.c.swp differ

fs/inotify.c +984 -0

984 lines not on this page · raw message

Files linux-2.6.12/fs/.inotify.c.swp and linux/fs/.inotify.c.swp differ

fs/Kconfig +13 -0
diff -urN linux-2.6.12/fs/Kconfig linux/fs/Kconfig
@@ -339,6 +339,19 @@
 	  If you don't know whether you need it, then you don't need it:
 	  answer N.
 
+config INOTIFY
+	bool "Inotify file change notification support"
+	default y
+	---help---
+	  Say Y here to enable inotify support and the /dev/inotify character
+	  device.  Inotify is a file change notification system and a
+	  replacement for dnotify.  Inotify fixes numerous shortcomings in
+	  dnotify and introduces several new features.  It allows monitoring
+	  of both files and directories via a single open fd.  Multiple file
+	  events are supported.
+
+	  If unsure, say Y.
+
 config QUOTA
 	bool "Quota support"
 	help
fs/Makefile +1 -0
diff -urN linux-2.6.12/fs/Makefile linux/fs/Makefile
@@ -11,6 +11,7 @@
 		attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \
 		seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \
 
+obj-$(CONFIG_INOTIFY)		+= inotify.o
 obj-$(CONFIG_EPOLL)		+= eventpoll.o
 obj-$(CONFIG_COMPAT)		+= compat.o
 
fs/namei.c +16 -14
diff -urN linux-2.6.12/fs/namei.c linux/fs/namei.c
@@ -21,7 +21,7 @@
 #include <linux/namei.h>
 #include <linux/quotaops.h>
 #include <linux/pagemap.h>
-#include <linux/dnotify.h>
+#include <linux/fsnotify.h>
 #include <linux/smp_lock.h>
 #include <linux/personality.h>
 #include <linux/security.h>
@@ -1312,7 +1312,7 @@
 	DQUOT_INIT(dir);
 	error = dir->i_op->create(dir, dentry, mode, nd);
 	if (!error) {
-		inode_dir_notify(dir, DN_CREATE);
+		fsnotify_create(dir, dentry->d_name.name);
 		security_inode_post_create(dir, dentry, mode);
 	}
 	return error;
@@ -1621,7 +1621,7 @@
 	DQUOT_INIT(dir);
 	error = dir->i_op->mknod(dir, dentry, mode, dev);
 	if (!error) {
-		inode_dir_notify(dir, DN_CREATE);
+		fsnotify_create(dir, dentry->d_name.name);
 		security_inode_post_mknod(dir, dentry, mode, dev);
 	}
 	return error;
@@ -1694,7 +1694,7 @@
 	DQUOT_INIT(dir);
 	error = dir->i_op->mkdir(dir, dentry, mode);
 	if (!error) {
-		inode_dir_notify(dir, DN_CREATE);
+		fsnotify_mkdir(dir, dentry->d_name.name);
 		security_inode_post_mkdir(dir,dentry, mode);
 	}
 	return error;
@@ -1785,7 +1785,7 @@
 	}
 	up(&dentry->d_inode->i_sem);
 	if (!error) {
-		inode_dir_notify(dir, DN_DELETE);
+		fsnotify_rmdir(dentry, dentry->d_inode, dir);
 		d_delete(dentry);
 	}
 	dput(dentry);
@@ -1858,9 +1858,10 @@
 
 	/* We don't d_delete() NFS sillyrenamed files--they still exist. */
 	if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) {
+		fsnotify_unlink(dentry, dir);
 		d_delete(dentry);
-		inode_dir_notify(dir, DN_DELETE);
 	}
+
 	return error;
 }
 
@@ -1934,7 +1935,7 @@
 	DQUOT_INIT(dir);
 	error = dir->i_op->symlink(dir, dentry, oldname);
 	if (!error) {
-		inode_dir_notify(dir, DN_CREATE);
+		fsnotify_create(dir, dentry->d_name.name);
 		security_inode_post_symlink(dir, dentry, oldname);
 	}
 	return error;
@@ -2007,7 +2008,7 @@
 	error = dir->i_op->link(old_dentry, dir, new_dentry);
 	up(&old_dentry->d_inode->i_sem);
 	if (!error) {
-		inode_dir_notify(dir, DN_CREATE);
+		fsnotify_create(dir, new_dentry->d_name.name);
 		security_inode_post_link(old_dentry, dir, new_dentry);
 	}
 	return error;
@@ -2171,6 +2172,7 @@
 {
 	int error;
 	int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
+	const char *old_name;
 
 	if (old_dentry->d_inode == new_dentry->d_inode)
  		return 0;
@@ -2192,18 +2194,18 @@
 	DQUOT_INIT(old_dir);
 	DQUOT_INIT(new_dir);
 
+	old_name = fsnotify_oldname_init(old_dentry->d_name.name);
+
 	if (is_dir)
 		error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
 	else
 		error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
 	if (!error) {
-		if (old_dir == new_dir)
-			inode_dir_notify(old_dir, DN_RENAME);
-		else {
-			inode_dir_notify(old_dir, DN_DELETE);
-			inode_dir_notify(new_dir, DN_CREATE);
-		}
+		const char *new_name = old_dentry->d_name.name;
+		fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir);
 	}
+	fsnotify_oldname_free(old_name);
+
 	return error;
 }
 
fs/nfsd/vfs.c +3 -3
diff -urN linux-2.6.12/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
@@ -45,7 +45,7 @@
 #endif /* CONFIG_NFSD_V3 */
 #include <linux/nfsd/nfsfh.h>
 #include <linux/quotaops.h>
-#include <linux/dnotify.h>
+#include <linux/fsnotify.h>
 #ifdef CONFIG_NFSD_V4
 #include <linux/posix_acl.h>
 #include <linux/posix_acl_xattr.h>
@@ -861,7 +861,7 @@
 		nfsdstats.io_read += err;
 		*count = err;
 		err = 0;
-		dnotify_parent(file->f_dentry, DN_ACCESS);
+		fsnotify_access(file->f_dentry);
 	} else 
 		err = nfserrno(err);
 out:
@@ -917,7 +917,7 @@
 	set_fs(oldfs);
 	if (err >= 0) {
 		nfsdstats.io_write += cnt;
-		dnotify_parent(file->f_dentry, DN_MODIFY);
+		fsnotify_modify(file->f_dentry);
 	}
 
 	/* clear setuid/setgid flag after write */
fs/open.c +3 -1
diff -urN linux-2.6.12/fs/open.c linux/fs/open.c
@@ -10,7 +10,7 @@
 #include <linux/file.h>
 #include <linux/smp_lock.h>
 #include <linux/quotaops.h>
-#include <linux/dnotify.h>
+#include <linux/fsnotify.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/tty.h>
@@ -944,9 +944,11 @@
 		fd = get_unused_fd();
 		if (fd >= 0) {
 			struct file *f = filp_open(tmp, flags, mode);
+
 			error = PTR_ERR(f);
 			if (IS_ERR(f))
 				goto out_error;
+			fsnotify_open(f->f_dentry);
 			fd_install(fd, f);
 		}
 out:
fs/read_write.c +9 -6
diff -urN linux-2.6.12/fs/read_write.c linux/fs/read_write.c
@@ -10,7 +10,7 @@
 #include <linux/file.h>
 #include <linux/uio.h>
 #include <linux/smp_lock.h>
-#include <linux/dnotify.h>
+#include <linux/fsnotify.h>
 #include <linux/security.h>
 #include <linux/module.h>
 #include <linux/syscalls.h>
@@ -239,7 +239,7 @@
 			else
 				ret = do_sync_read(file, buf, count, pos);
 			if (ret > 0) {
-				dnotify_parent(file->f_dentry, DN_ACCESS);
+				fsnotify_access(file->f_dentry);
 				current->rchar += ret;
 			}
 			current->syscr++;
@@ -287,7 +287,7 @@
 			else
 				ret = do_sync_write(file, buf, count, pos);
 			if (ret > 0) {
-				dnotify_parent(file->f_dentry, DN_MODIFY);
+				fsnotify_modify(file->f_dentry);
 				current->wchar += ret;
 			}
 			current->syscw++;
@@ -523,9 +523,12 @@
 out:
 	if (iov != iovstack)
 		kfree(iov);
-	if ((ret + (type == READ)) > 0)
-		dnotify_parent(file->f_dentry,
-				(type == READ) ? DN_ACCESS : DN_MODIFY);
+	if ((ret + (type == READ)) > 0) {
+		if (type == READ)
+			fsnotify_access(file->f_dentry);
+		else
+			fsnotify_modify(file->f_dentry);
+	}
 	return ret;
 Efault:
 	ret = -EFAULT;
fs/sysfs/file.c +2 -5
diff -urN linux-2.6.12/fs/sysfs/file.c linux/fs/sysfs/file.c
@@ -3,7 +3,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/dnotify.h>
+#include <linux/fsnotify.h>
 #include <linux/kobject.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
@@ -389,9 +389,6 @@
  * sysfs_update_file - update the modified timestamp on an object attribute.
  * @kobj: object we're acting for.
  * @attr: attribute descriptor.
- *
- * Also call dnotify for the dentry, which lots of userspace programs
- * use.
  */
 int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
 {
@@ -406,7 +403,7 @@
 		if (victim->d_inode && 
 		    (victim->d_parent->d_inode == dir->d_inode)) {
 			victim->d_inode->i_mtime = CURRENT_TIME;
-			dnotify_parent(victim, DN_MODIFY);
+			fsnotify_modify(victim);
 
 			/**
 			 * Drop reference from initial sysfs_get_dentry().
fs/xattr.c +4 -1
diff -urN linux-2.6.12/fs/xattr.c linux/fs/xattr.c
@@ -16,6 +16,7 @@
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/module.h>
+#include <linux/fsnotify.h>
 #include <asm/uaccess.h>
 
 /*
@@ -57,8 +58,10 @@
 		if (error)
 			goto out;
 		error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
-		if (!error)
+		if (!error) {
+			fsnotify_xattr(d);
 			security_inode_post_setxattr(d, kname, kvalue, size, flags);
+		}
 out:
 		up(&d->d_inode->i_sem);
 	}
include/linux/fs.h +5 -1
diff -urN linux-2.6.12/include/linux/fs.h linux/include/linux/fs.h
@@ -471,6 +471,11 @@
 	struct dnotify_struct	*i_dnotify; /* for directory notifications */
 #endif
 
+#ifdef CONFIG_INOTIFY
+	struct list_head	inotify_watches; /* watches on this inode */
+	struct semaphore	inotify_sem;	/* protects the watches list */
+#endif
+
 	unsigned long		i_state;
 	unsigned long		dirtied_when;	/* jiffies of first dirtying */
 
@@ -1369,7 +1374,6 @@
 extern int do_remount_sb(struct super_block *sb, int flags,
 			 void *data, int force);
 extern sector_t bmap(struct inode *, sector_t);
-extern int setattr_mask(unsigned int);
 extern int notify_change(struct dentry *, struct iattr *);
 extern int permission(struct inode *, int, struct nameidata *);
 extern int generic_permission(struct inode *, int,
include/linux/fsnotify.h +257 -0

257 lines not on this page · raw message

include/linux/inotify.h +124 -0

124 lines not on this page · raw message

include/linux/sched.h +4 -0
diff -urN linux-2.6.12/include/linux/sched.h linux/include/linux/sched.h
@@ -404,6 +404,10 @@
 	atomic_t processes;	/* How many processes does this user have? */
 	atomic_t files;		/* How many open files does this user have? */
 	atomic_t sigpending;	/* How many pending signals does this user have? */
+#ifdef CONFIG_INOTIFY
+	atomic_t inotify_watches; /* How many inotify watches does this user have? */
+	atomic_t inotify_devs;	/* How many inotify devs does this user have opened? */
+#endif
 	/* protected by mq_lock	*/
 	unsigned long mq_bytes;	/* How many bytes can be allocated to mqueue? */
 	unsigned long locked_shm; /* How many pages of mlocked shm ? */
kernel/user.c +4 -0
diff -urN linux-2.6.12/kernel/user.c linux/kernel/user.c
@@ -120,6 +120,10 @@
 		atomic_set(&new->processes, 0);
 		atomic_set(&new->files, 0);
 		atomic_set(&new->sigpending, 0);
+#ifdef CONFIG_INOTIFY
+		atomic_set(&new->inotify_watches, 0);
+		atomic_set(&new->inotify_devs, 0);
+#endif
 
 		new->mq_bytes = 0;
 		new->locked_shm = 0;
#1 lore raw

Hi,

Are you aware of the following:

Jun 21 18:34:04 kangur ------------[ cut here ]------------
Jun 21 18:34:04 kangur kernel BUG at fs/inode.c:1100!
Jun 21 18:34:04 kangur invalid operand: 0000 [#1]
Jun 21 18:34:04 kangur PREEMPT
Jun 21 18:34:04 kangur Modules linked in: nls_iso8859_2 ntfs nls_base pppoatm snd_seq_midi snd_emu10k1_synth snd_emux_synth snd_seq_virmidi snd_seq_midi_emul snd_pcm_oss snd_mixer_oss snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq psmouse 8250_pnp 8250 serial_core floppy pcspkr rtc nvidia 8139too mii emu10k1_gp gameport snd_emu10k1 snd_rawmidi snd_seq_device snd_ac97_codec snd_pcm snd_timer snd_page_alloc snd_util_mem snd_hwdep snd soundcore tuner tvaudio bttv video_buf i2c_algo_bit v4l2_common btcx_risc tveeprom videodev speedtch firmware_class usb_atm atm via686a i2c_sensor i2c_core uhci_hcd parport_pc parport evdev usbcore nvram cpuid edd msr loop button ppp_generic slhc unix
Jun 21 18:34:04 kangur CPU:    0
Jun 21 18:34:04 kangur EIP:    0060:[<b0173342>]    Tainted: P      VLI
Jun 21 18:34:04 kangur EFLAGS: 00010246   (2.6.12-rc6-ck2-gk1)
Jun 21 18:34:04 kangur EIP is at iput+0x62/0x70
Jun 21 18:34:04 kangur eax: d11fbc00   ebx: c65a20dc   ecx: c65a20e4 edx: c0ede000
Jun 21 18:34:04 kangur esi: c65a21e8   edi: c65a21e8   ebp: c65a20dc esp: c0edeeec
Jun 21 18:34:04 kangur ds: 007b   es: 007b   ss: 0068
Jun 21 18:34:04 kangur Process umount (pid: 10472, threadinfo=c0ede000 task=cac79a40)
Jun 21 18:34:04 kangur Stack: cf63bc74 b017feff 00000000 00000000 c0ede000 c65a21f0 c65a20dc cf63bc74
Jun 21 18:34:04 kangur cf63bc74 c0ede000 c0edef20 c0ede000 b01722ea c0edef20 c0edef20 c8fcea8c
Jun 21 18:34:04 kangur cf63bc00 d11fbc00 b015e3b3 0804d35c b14df3c0 cf63bc00 0804d35c b015efa5
Jun 21 18:34:04 kangur Call Trace:
Jun 21 18:34:04 kangur [<b017feff>] inotify_unmount_inodes+0xcf/0x110
Jun 21 18:34:04 kangur [<b01722ea>] invalidate_inodes+0x3a/0x80
Jun 21 18:34:04 kangur [<b015e3b3>] generic_shutdown_super+0x63/0x160
Jun 21 18:34:04 kangur [<b015efa5>] kill_block_super+0x25/0x40
Jun 21 18:34:04 kangur [<b015e240>] deactivate_super+0x50/0x80
Jun 21 18:34:04 kangur [<b0175515>] sys_umount+0x35/0x80
Jun 21 18:34:04 kangur [<b014c708>] do_munmap+0xe8/0x150
Jun 21 18:34:04 kangur [<b0175577>] sys_oldumount+0x17/0x20
Jun 21 18:34:04 kangur [<b01030cb>] sysenter_past_esp+0x54/0x75
Jun 21 18:34:04 kangur Code: 94 00 00 00 ba c0 32 17 b0 8b 40 24 85 c0 74 08 8b 40 18 85 c0 0f 45 d0 89 d8 ff d2 5b c3 89 d8 ff d2 8d b4 26 00 00 00 00 eb c2 <0f> 0b 4c 04 6c 6d 2d b0 eb ad 8d 74 26 00 83 ec 08 89 74 24 04
Jun 21 18:34:04 kangur Badness in do_exit at kernel/exit.c:781
Jun 21 18:34:04 kangur [<b011be0c>] do_exit+0x3cc/0x3e0
Jun 21 18:34:04 kangur [<b01043db>] die+0x16b/0x170
Jun 21 18:34:04 kangur [<b0104700>] do_invalid_op+0x0/0xa0
Jun 21 18:34:04 kangur [<b0104790>] do_invalid_op+0x90/0xa0
Jun 21 18:34:04 kangur [<b0144342>] pagevec_lookup+0x22/0x30
Jun 21 18:34:04 kangur [<b0173342>] iput+0x62/0x70
Jun 21 18:34:04 kangur [<b017c343>] write_inode_now+0x73/0xe0
Jun 21 18:34:04 kangur [<d11eb764>] __ntfs_clear_inode+0x54/0x160 [ntfs]
Jun 21 18:34:04 kangur [<d11eb909>] ntfs_clear_big_inode+0x59/0xc0 [ntfs]
Jun 21 18:34:04 kangur [<b0187b00>] dquot_drop+0x0/0x70
Jun 21 18:34:04 kangur [<b01720ae>] clear_inode+0xae/0x130
Jun 21 18:34:04 kangur [<b01447f7>] truncate_inode_pages+0x17/0x20
Jun 21 18:34:04 kangur [<b0103c23>] error_code+0x4f/0x54
Jun 21 18:34:04 kangur [<b0173342>] iput+0x62/0x70
Jun 21 18:34:04 kangur [<b017feff>] inotify_unmount_inodes+0xcf/0x110
Jun 21 18:34:04 kangur [<b01722ea>] invalidate_inodes+0x3a/0x80
Jun 21 18:34:04 kangur [<b015e3b3>] generic_shutdown_super+0x63/0x160
Jun 21 18:34:04 kangur [<b015efa5>] kill_block_super+0x25/0x40
Jun 21 18:34:04 kangur [<b015e240>] deactivate_super+0x50/0x80
Jun 21 18:34:04 kangur [<b0175515>] sys_umount+0x35/0x80
Jun 21 18:34:04 kangur [<b014c708>] do_munmap+0xe8/0x150
Jun 21 18:34:04 kangur [<b0175577>] sys_oldumount+0x17/0x20
Jun 21 18:34:04 kangur [<b01030cb>] sysenter_past_esp+0x54/0x75

I know that the kernel was tainted but I am afraid that this can be easily reproduced with any 2.6.12 like kernel + inotify after mounting and using NTFS for a while (maybe even mounting and reading of single file and then trying to umount suffices). This breaks the box pretty bad and I needed to reboot with SysRq because init could not.

This was with kernel:

kangur ~ # uname -a
Linux kangur 2.6.12-rc6-ck2-gk1 #1 Mon Jun 6 21:07:12 CEST 2005 i686 Unknown CPU Type AuthenticAMD GNU/Linux

probably with this:

0aa3dfb1940a12a4245ec87b4246db85b55abe40 inotify-0.23-rml-2.6.12-rc4-8.patch

inoftify patch.

Are you aware of this bug (or maybe you already fixed it)?

Thanks,

Grzegorz Kulewski

#2 lore raw
Quoted 1 line · Grzegorz Kulewski

0aa3dfb1940a12a4245ec87b4246db85b55abe40 inotify-0.23-rml-2.6.12-rc4-8.patch

Oh, I just noticed this.

Can you please try with this latest release
(inotify-0.23-rml-2.6.12-14.patch)?

There is some code that might fix this for you, or reveal further what is going on.

Robert Love

#3 lore raw
Quoted 11 lines · Robert Love
Quoted 1 line · Grzegorz Kulewski

0aa3dfb1940a12a4245ec87b4246db85b55abe40 inotify-0.23-rml-2.6.12-rc4-8.patch

Oh, I just noticed this.

Can you please try with this latest release
(inotify-0.23-rml-2.6.12-14.patch)?

There is some code that might fix this for you, or reveal further what is going on.

I will try that as fast as I can. I am not using -mm's since 2.6.2-mm2 because they are usually too broken for me :-(.

IIRC, similar bug was discussed on #gentoo-bugs recently and is probably somewhere in Gentoo Bugzilla (http://bugs.gentoo.org). Several people noticed this. So probably if you can mount and use NTFS for a while and then umount it without problems this is probably fixed. If not - you can reproduce it simply (it is 100% reproductible and occurs only on inotified kernels).

Thanks,

Grzegorz Kulewski

#4 lore raw
Quoted 2 lines · Grzegorz Kulewski

I will try that as fast as I can. I am not using -mm's since 2.6.2-mm2 because they are usually too broken for me :-(.

Okay. Please let me know how it goes.

And you don't need 2.6-mm, just grab 2.6.12 + inotify if you want.

Robert Love

#6 lore raw
In reply to Robert Love
Quoted 8 lines · Robert Love

Below is the latest inotify patch, against 2.6.12.

[...]
+/*
+ * fsnotify_oldname_init - save off the old filename before we change it
+ *
+ * XXX: This could be kstrdup if only we could add that to lib/string.c
+ */

I knew you were waiting for this, so I just wanted to let you know that the kstrdup function is already available in Linus tree 2.6.13-rc1. It is declared linux/string.h and implemented in mm/slab.c.

It is not implemented in lib/string.c because some architectures use lib functions in their bootloading code where the allocation functions are not available, and the linking stage then fails because of the kmalloc reference :P

Signature · 5 lines
Paulo Marques - www.grupopie.com

It is a mistake to think you can solve any major problems
just with potatoes.
Douglas Adams