Commit 7a91bf7f5c22c8407a9991cbd9ce5bb87caa6b4a

Authored by John McCutchan
Committed by Linus Torvalds
1 parent 1963c907b2

[PATCH] fsnotify_name/inoderemove

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>

Showing 3 changed files with 27 additions and 3 deletions Side-by-side Diff

... ... @@ -19,6 +19,7 @@
19 19 #include <linux/string.h>
20 20 #include <linux/mm.h>
21 21 #include <linux/fs.h>
  22 +#include <linux/fsnotify.h>
22 23 #include <linux/slab.h>
23 24 #include <linux/init.h>
24 25 #include <linux/smp_lock.h>
... ... @@ -101,6 +102,7 @@
101 102 list_del_init(&dentry->d_alias);
102 103 spin_unlock(&dentry->d_lock);
103 104 spin_unlock(&dcache_lock);
  105 + fsnotify_inoderemove(inode);
104 106 if (dentry->d_op && dentry->d_op->d_iput)
105 107 dentry->d_op->d_iput(dentry, inode);
106 108 else
107 109  
108 110  
... ... @@ -1165,13 +1167,16 @@
1165 1167  
1166 1168 void d_delete(struct dentry * dentry)
1167 1169 {
  1170 + int isdir = 0;
1168 1171 /*
1169 1172 * Are we the only user?
1170 1173 */
1171 1174 spin_lock(&dcache_lock);
1172 1175 spin_lock(&dentry->d_lock);
  1176 + isdir = S_ISDIR(dentry->d_inode->i_mode);
1173 1177 if (atomic_read(&dentry->d_count) == 1) {
1174 1178 dentry_iput(dentry);
  1179 + fsnotify_nameremove(dentry, isdir);
1175 1180 return;
1176 1181 }
1177 1182  
... ... @@ -1180,6 +1185,8 @@
1180 1185  
1181 1186 spin_unlock(&dentry->d_lock);
1182 1187 spin_unlock(&dcache_lock);
  1188 +
  1189 + fsnotify_nameremove(dentry, isdir);
1183 1190 }
1184 1191  
1185 1192 static void __d_rehash(struct dentry * entry, struct hlist_head *list)
... ... @@ -1802,7 +1802,6 @@
1802 1802 up(&dentry->d_inode->i_sem);
1803 1803 if (!error) {
1804 1804 d_delete(dentry);
1805   - fsnotify_rmdir(dentry, dentry->d_inode, dir);
1806 1805 }
1807 1806 dput(dentry);
1808 1807  
1809 1808  
... ... @@ -1874,9 +1873,7 @@
1874 1873  
1875 1874 /* We don't d_delete() NFS sillyrenamed files--they still exist. */
1876 1875 if (!error && !(dentry->d_flags & DCACHE_NFSFS_RENAMED)) {
1877   - struct inode *inode = dentry->d_inode;
1878 1876 d_delete(dentry);
1879   - fsnotify_unlink(dentry, inode, dir);
1880 1877 }
1881 1878  
1882 1879 return error;
include/linux/fsnotify.h
... ... @@ -68,6 +68,26 @@
68 68 }
69 69  
70 70 /*
  71 + * fsnotify_nameremove - a filename was removed from a directory
  72 + */
  73 +static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
  74 +{
  75 + if (isdir)
  76 + isdir = IN_ISDIR;
  77 + dnotify_parent(dentry, DN_DELETE);
  78 + inotify_dentry_parent_queue_event(dentry, IN_DELETE|isdir, 0, dentry->d_name.name);
  79 +}
  80 +
  81 +/*
  82 + * fsnotify_inoderemove - an inode is going away
  83 + */
  84 +static inline void fsnotify_inoderemove(struct inode *inode)
  85 +{
  86 + inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL);
  87 + inotify_inode_is_dead(inode);
  88 +}
  89 +
  90 +/*
71 91 * fsnotify_create - 'name' was linked in
72 92 */
73 93 static inline void fsnotify_create(struct inode *inode, const char *name)