Skip to content

Commit

Permalink
[PATCH] fsnotify_name/inoderemove
Browse files Browse the repository at this point in the history
The patch below unhooks fsnotify from vfs_unlink & vfs_rmdir.  It
introduces two new fsnotify calls, that are hooked in at the dcache
level.  This not only more closely matches how the VFS layer works, it
also avoids the problem with locking and inode lifetimes.

The two functions are

 - fsnotify_nameremove -- called when a directory entry is going away.
   It notifies the PARENT of the deletion.  This is called from
   d_delete().

 - inoderemove -- called when the files inode itself is going away.  It
   notifies the inode that is being deleted.  This is called from
   dentry_iput().

Signed-off-by: John McCutchan <ttb@tentacle.dhs.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
John McCutchan authored and Linus Torvalds committed Aug 8, 2005
1 parent 1963c90 commit 7a91bf7
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 3 deletions.
7 changes: 7 additions & 0 deletions fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/fsnotify.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
Expand Down Expand Up @@ -101,6 +102,7 @@ static inline void dentry_iput(struct dentry * dentry)
list_del_init(&dentry->d_alias);
spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);
fsnotify_inoderemove(inode);
if (dentry->d_op && dentry->d_op->d_iput)
dentry->d_op->d_iput(dentry, inode);
else
Expand Down Expand Up @@ -1165,13 +1167,16 @@ int d_validate(struct dentry *dentry, struct dentry *dparent)

void d_delete(struct dentry * dentry)
{
int isdir = 0;
/*
* Are we the only user?
*/
spin_lock(&dcache_lock);
spin_lock(&dentry->d_lock);
isdir = S_ISDIR(dentry->d_inode->i_mode);
if (atomic_read(&dentry->d_count) == 1) {
dentry_iput(dentry);
fsnotify_nameremove(dentry, isdir);
return;
}

Expand All @@ -1180,6 +1185,8 @@ void d_delete(struct dentry * dentry)

spin_unlock(&dentry->d_lock);
spin_unlock(&dcache_lock);

fsnotify_nameremove(dentry, isdir);
}

static void __d_rehash(struct dentry * entry, struct hlist_head *list)
Expand Down
3 changes: 0 additions & 3 deletions fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -1802,7 +1802,6 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
up(&dentry->d_inode->i_sem);
if (!error) {
d_delete(dentry);
fsnotify_rmdir(dentry, dentry->d_inode, dir);
}
dput(dentry);

Expand Down Expand Up @@ -1874,9 +1873,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)

/* We don't d_delete() NFS sillyrenamed files--they still exist. */
if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) {
struct inode *inode = dentry->d_inode;
d_delete(dentry);
fsnotify_unlink(dentry, inode, dir);
}

return error;
Expand Down
20 changes: 20 additions & 0 deletions include/linux/fsnotify.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,26 @@ static inline void fsnotify_rmdir(struct dentry *dentry, struct inode *inode,
inotify_inode_is_dead(inode);
}

/*
* fsnotify_nameremove - a filename was removed from a directory
*/
static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
{
if (isdir)
isdir = IN_ISDIR;
dnotify_parent(dentry, DN_DELETE);
inotify_dentry_parent_queue_event(dentry, IN_DELETE|isdir, 0, dentry->d_name.name);
}

/*
* fsnotify_inoderemove - an inode is going away
*/
static inline void fsnotify_inoderemove(struct inode *inode)
{
inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL);
inotify_inode_is_dead(inode);
}

/*
* fsnotify_create - 'name' was linked in
*/
Expand Down

0 comments on commit 7a91bf7

Please sign in to comment.