From 3bcf3860a4ff9bbc522820b4b765e65e4deceb3e Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 28 Jul 2010 10:18:37 -0400 Subject: fsnotify: store struct file not struct path 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 --- fs/notify/fanotify/fanotify.c | 8 ++++---- fs/notify/fanotify/fanotify_user.c | 6 +++--- fs/notify/fsnotify.c | 16 ++++++++-------- fs/notify/inotify/inotify_fsnotify.c | 12 ++++++------ fs/notify/notification.c | 20 +++++++++----------- 5 files changed, 30 insertions(+), 32 deletions(-) (limited to 'fs/notify') diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index f3c40c0e2b8..c2a3029052b 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -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) diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 7182c83be90..50cea74bf1c 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -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) diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 72aae404531..4788c866473 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -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 */ diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 73a1106b354..3c506e0364c 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -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; } diff --git a/fs/notify/notification.c b/fs/notify/notification.c index f39260f8f86..c106cdd7ff5 100644 --- a/fs/notify/notification.c +++ b/fs/notify/notification.c @@ -31,6 +31,7 @@ * allocated and used. */ +#include #include #include #include @@ -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(); -- cgit v1.2.3