fsnotify: store struct file not struct path
authorEric Paris <eparis@redhat.com>
Wed, 28 Jul 2010 14:18:37 +0000 (10:18 -0400)
committerEric Paris <eparis@redhat.com>
Wed, 28 Jul 2010 14:18:51 +0000 (10:18 -0400)
Al explains that calling dentry_open() with a mnt/dentry pair is only
garunteed to be safe if they are already used in an open struct file.  To
make sure this is the case don't store and use a struct path in fsnotify,
always use a struct file.

Signed-off-by: Eric Paris <eparis@redhat.com>
fs/notify/fanotify/fanotify.c
fs/notify/fanotify/fanotify_user.c
fs/notify/fsnotify.c
fs/notify/inotify/inotify_fsnotify.c
fs/notify/notification.c
include/linux/fsnotify.h
include/linux/fsnotify_backend.h
kernel/audit_watch.c

index f3c40c0e2b867c0ee7f552a034a506c741f3c015..c2a3029052bca2fa520cec5832f3545cc08a1ac9 100644 (file)
@@ -17,9 +17,9 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new)
            old->data_type == new->data_type &&
            old->tgid == new->tgid) {
                switch (old->data_type) {
-               case (FSNOTIFY_EVENT_PATH):
-                       if ((old->path.mnt == new->path.mnt) &&
-                           (old->path.dentry == new->path.dentry))
+               case (FSNOTIFY_EVENT_FILE):
+                       if ((old->file->f_path.mnt == new->file->f_path.mnt) &&
+                           (old->file->f_path.dentry == new->file->f_path.dentry))
                                return true;
                case (FSNOTIFY_EVENT_NONE):
                        return true;
@@ -226,7 +226,7 @@ static bool fanotify_should_send_event(struct fsnotify_group *group, struct inod
                return false;
 
        /* if we don't have enough info to send an event to userspace say no */
-       if (data_type != FSNOTIFY_EVENT_PATH)
+       if (data_type != FSNOTIFY_EVENT_FILE)
                return false;
 
        if (mnt)
index 7182c83be90ef88c3cd5a0808621a70a1e7d5701..50cea74bf1c8cfa4cb6d02e8863779ccb4ef427e 100644 (file)
@@ -65,7 +65,7 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event)
        if (client_fd < 0)
                return client_fd;
 
-       if (event->data_type != FSNOTIFY_EVENT_PATH) {
+       if (event->data_type != FSNOTIFY_EVENT_FILE) {
                WARN_ON(1);
                put_unused_fd(client_fd);
                return -EINVAL;
@@ -75,8 +75,8 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event)
         * we need a new file handle for the userspace program so it can read even if it was
         * originally opened O_WRONLY.
         */
-       dentry = dget(event->path.dentry);
-       mnt = mntget(event->path.mnt);
+       dentry = dget(event->file->f_path.dentry);
+       mnt = mntget(event->file->f_path.mnt);
        /* it's possible this event was an overflow event.  in that case dentry and mnt
         * are NULL;  That's fine, just don't call dentry open */
        if (dentry && mnt)
index 72aae40453147bb37400bdd854e3725417e80628..4788c866473a1d1f97376af47de0c16b9f06b751 100644 (file)
@@ -84,7 +84,7 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
 }
 
 /* Notify this dentry's parent about a child's events. */
-void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
+void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask)
 {
        struct dentry *parent;
        struct inode *p_inode;
@@ -92,7 +92,7 @@ void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
        bool should_update_children = false;
 
        if (!dentry)
-               dentry = path->dentry;
+               dentry = file->f_path.dentry;
 
        if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED))
                return;
@@ -124,8 +124,8 @@ void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
                 * specifies these are events which came from a child. */
                mask |= FS_EVENT_ON_CHILD;
 
-               if (path)
-                       fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH,
+               if (file)
+                       fsnotify(p_inode, mask, file, FSNOTIFY_EVENT_FILE,
                                 dentry->d_name.name, 0);
                else
                        fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE,
@@ -154,10 +154,10 @@ void __fsnotify_flush_ignored_mask(struct inode *inode, void *data, int data_is)
                spin_unlock(&inode->i_lock);
        }
 
-       if (data_is == FSNOTIFY_EVENT_PATH) {
+       if (data_is == FSNOTIFY_EVENT_FILE) {
                struct vfsmount *mnt;
 
-               mnt = ((struct path *)data)->mnt;
+               mnt = ((struct file *)data)->f_path.mnt;
                if (mnt && !hlist_empty(&mnt->mnt_fsnotify_marks)) {
                        spin_lock(&mnt->mnt_root->d_lock);
                        hlist_for_each_entry(mark, node, &mnt->mnt_fsnotify_marks, m.m_list) {
@@ -228,8 +228,8 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
            !(test_mask & fsnotify_vfsmount_mask))
                return 0;
  
-       if (data_is == FSNOTIFY_EVENT_PATH)
-               mnt = ((struct path *)data)->mnt;
+       if (data_is == FSNOTIFY_EVENT_FILE)
+               mnt = ((struct file *)data)->f_path.mnt;
 
        /* if this inode's directed listeners don't care and nothing on the vfsmount
         * listeners list cares, nothing to do */
index 73a1106b3542d0b09290b462e764b24b6119ddcb..3c506e0364cc4cb87d6308335d03d9afaa30ddfe 100644 (file)
@@ -52,9 +52,9 @@ static bool event_compare(struct fsnotify_event *old, struct fsnotify_event *new
                            !strcmp(old->file_name, new->file_name))
                                return true;
                        break;
-               case (FSNOTIFY_EVENT_PATH):
-                       if ((old->path.mnt == new->path.mnt) &&
-                           (old->path.dentry == new->path.dentry))
+               case (FSNOTIFY_EVENT_FILE):
+                       if ((old->file->f_path.mnt == new->file->f_path.mnt) &&
+                           (old->file->f_path.dentry == new->file->f_path.dentry))
                                return true;
                        break;
                case (FSNOTIFY_EVENT_NONE):
@@ -165,10 +165,10 @@ static bool inotify_should_send_event(struct fsnotify_group *group, struct inode
        send = (fsn_mark->mask & mask);
 
        if (send && (fsn_mark->mask & FS_EXCL_UNLINK) &&
-           (data_type == FSNOTIFY_EVENT_PATH)) {
-               struct path *path  = data;
+           (data_type == FSNOTIFY_EVENT_FILE)) {
+               struct file *file  = data;
 
-               if (d_unlinked(path->dentry))
+               if (d_unlinked(file->f_path.dentry))
                        send = false;
        }
 
index f39260f8f8656e42feac01e728497cd05650d881..c106cdd7ff5eb8d92e85a1af948f21b80235226f 100644 (file)
@@ -31,6 +31,7 @@
  * allocated and used.
  */
 
+#include <linux/file.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -89,8 +90,8 @@ void fsnotify_put_event(struct fsnotify_event *event)
        if (atomic_dec_and_test(&event->refcnt)) {
                pr_debug("%s: event=%p\n", __func__, event);
 
-               if (event->data_type == FSNOTIFY_EVENT_PATH)
-                       path_put(&event->path);
+               if (event->data_type == FSNOTIFY_EVENT_FILE)
+                       fput(event->file);
 
                BUG_ON(!list_empty(&event->private_data_list));
 
@@ -375,8 +376,8 @@ struct fsnotify_event *fsnotify_clone_event(struct fsnotify_event *old_event)
                }
        }
        event->tgid = get_pid(old_event->tgid);
-       if (event->data_type == FSNOTIFY_EVENT_PATH)
-               path_get(&event->path);
+       if (event->data_type == FSNOTIFY_EVENT_FILE)
+               get_file(event->file);
 
        return event;
 }
@@ -423,11 +424,9 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
        event->data_type = data_type;
 
        switch (data_type) {
-       case FSNOTIFY_EVENT_PATH: {
-               struct path *path = data;
-               event->path.dentry = path->dentry;
-               event->path.mnt = path->mnt;
-               path_get(&event->path);
+       case FSNOTIFY_EVENT_FILE: {
+               event->file = data;
+               get_file(event->file);
                break;
        }
        case FSNOTIFY_EVENT_INODE:
@@ -435,8 +434,7 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
                break;
        case FSNOTIFY_EVENT_NONE:
                event->inode = NULL;
-               event->path.dentry = NULL;
-               event->path.mnt = NULL;
+               event->file = NULL;
                break;
        default:
                BUG();
index 59d0df43ff9d5ef649fd109228ded45f37579d84..e4e2204187ee2ae12e8eb0601e0fc078af68bb51 100644 (file)
@@ -26,19 +26,18 @@ static inline void fsnotify_d_instantiate(struct dentry *dentry,
 }
 
 /* Notify this dentry's parent about a child's events. */
-static inline void fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
+static inline void fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask)
 {
        if (!dentry)
-               dentry = path->dentry;
+               dentry = file->f_path.dentry;
 
-       __fsnotify_parent(path, dentry, mask);
+       __fsnotify_parent(file, dentry, mask);
 }
 
 /* simple call site for access decisions */
 static inline int fsnotify_perm(struct file *file, int mask)
 {
-       struct path *path = &file->f_path;
-       struct inode *inode = path->dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        __u32 fsnotify_mask = 0;
 
        if (file->f_mode & FMODE_NONOTIFY)
@@ -52,7 +51,7 @@ static inline int fsnotify_perm(struct file *file, int mask)
        else
                BUG();
 
-       return fsnotify(inode, fsnotify_mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
+       return fsnotify(inode, fsnotify_mask, file, FSNOTIFY_EVENT_FILE, NULL, 0);
 }
 
 /*
@@ -187,16 +186,15 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
  */
 static inline void fsnotify_access(struct file *file)
 {
-       struct path *path = &file->f_path;
-       struct inode *inode = path->dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        __u32 mask = FS_ACCESS;
 
        if (S_ISDIR(inode->i_mode))
                mask |= FS_IN_ISDIR;
 
        if (!(file->f_mode & FMODE_NONOTIFY)) {
-               fsnotify_parent(path, NULL, mask);
-               fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
+               fsnotify_parent(file, NULL, mask);
+               fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0);
        }
 }
 
@@ -205,16 +203,15 @@ static inline void fsnotify_access(struct file *file)
  */
 static inline void fsnotify_modify(struct file *file)
 {
-       struct path *path = &file->f_path;
-       struct inode *inode = path->dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        __u32 mask = FS_MODIFY;
 
        if (S_ISDIR(inode->i_mode))
                mask |= FS_IN_ISDIR;
 
        if (!(file->f_mode & FMODE_NONOTIFY)) {
-               fsnotify_parent(path, NULL, mask);
-               fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
+               fsnotify_parent(file, NULL, mask);
+               fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0);
        }
 }
 
@@ -223,16 +220,15 @@ static inline void fsnotify_modify(struct file *file)
  */
 static inline void fsnotify_open(struct file *file)
 {
-       struct path *path = &file->f_path;
-       struct inode *inode = path->dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
        __u32 mask = FS_OPEN;
 
        if (S_ISDIR(inode->i_mode))
                mask |= FS_IN_ISDIR;
 
        if (!(file->f_mode & FMODE_NONOTIFY)) {
-               fsnotify_parent(path, NULL, mask);
-               fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
+               fsnotify_parent(file, NULL, mask);
+               fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0);
        }
 }
 
@@ -241,7 +237,6 @@ static inline void fsnotify_open(struct file *file)
  */
 static inline void fsnotify_close(struct file *file)
 {
-       struct path *path = &file->f_path;
        struct inode *inode = file->f_path.dentry->d_inode;
        fmode_t mode = file->f_mode;
        __u32 mask = (mode & FMODE_WRITE) ? FS_CLOSE_WRITE : FS_CLOSE_NOWRITE;
@@ -250,8 +245,8 @@ static inline void fsnotify_close(struct file *file)
                mask |= FS_IN_ISDIR;
 
        if (!(file->f_mode & FMODE_NONOTIFY)) {
-               fsnotify_parent(path, NULL, mask);
-               fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
+               fsnotify_parent(file, NULL, mask);
+               fsnotify(inode, mask, file, FSNOTIFY_EVENT_FILE, NULL, 0);
        }
 }
 
index 564b5ea4a831f91ce488d01da16dc2eca43d3cd3..3410d388163ebbd848b180a0f8dc9003d87fad09 100644 (file)
@@ -223,20 +223,20 @@ struct fsnotify_event {
        /* to_tell may ONLY be dereferenced during handle_event(). */
        struct inode *to_tell;  /* either the inode the event happened to or its parent */
        /*
-        * depending on the event type we should have either a path or inode
-        * We hold a reference on path, but NOT on inode.  Since we have the ref on
-        * the path, it may be dereferenced at any point during this object's
+        * depending on the event type we should have either a file or inode
+        * We hold a reference on file, but NOT on inode.  Since we have the ref on
+        * the file, it may be dereferenced at any point during this object's
         * lifetime.  That reference is dropped when this object's refcnt hits
-        * 0.  If this event contains an inode instead of a path, the inode may
+        * 0.  If this event contains an inode instead of a file, the inode may
         * ONLY be used during handle_event().
         */
        union {
-               struct path path;
+               struct file *file;
                struct inode *inode;
        };
 /* when calling fsnotify tell it if the data is a path or inode */
 #define FSNOTIFY_EVENT_NONE    0
-#define FSNOTIFY_EVENT_PATH    1
+#define FSNOTIFY_EVENT_FILE    1
 #define FSNOTIFY_EVENT_INODE   2
        int data_type;          /* which of the above union we have */
        atomic_t refcnt;        /* how many groups still are using/need to send this event */
@@ -311,7 +311,7 @@ struct fsnotify_mark {
 /* main fsnotify call to send events */
 extern int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
                    const unsigned char *name, u32 cookie);
-extern void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask);
+extern void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask);
 extern void __fsnotify_inode_delete(struct inode *inode);
 extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt);
 extern u32 fsnotify_get_cookie(void);
@@ -444,7 +444,7 @@ static inline int fsnotify(struct inode *to_tell, __u32 mask, void *data, int da
        return 0;
 }
 
-static inline void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
+static inline void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask)
 {}
 
 static inline void __fsnotify_inode_delete(struct inode *inode)
index 7499397a61003f7d77d10623535bac26eadcf3e0..b955a22d8ff19ed01703e1502a561309d85ce6a7 100644 (file)
@@ -545,8 +545,8 @@ static int audit_watch_handle_event(struct fsnotify_group *group, struct fsnotif
                return 0;
 
        switch (event->data_type) {
-       case (FSNOTIFY_EVENT_PATH):
-               inode = event->path.dentry->d_inode;
+       case (FSNOTIFY_EVENT_FILE):
+               inode = event->file->f_path.dentry->d_inode;
                break;
        case (FSNOTIFY_EVENT_INODE):
                inode = event->inode;