diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2009-09-04 15:06:27 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2009-09-04 15:06:27 +1000 |
commit | 617d35a6bd50f37c632c82008bc0fb244bb745c8 (patch) | |
tree | 62daff33693571b8c756062b7e1e236be6c46288 /fs | |
parent | af72f9e9a2b17d2f8338844b17d38b0e083b8d33 (diff) | |
parent | edf8d5943af4a86907d68d9801ebcdc73ecbee01 (diff) |
Merge commit 'fsnotify/for-next'
Diffstat (limited to 'fs')
-rw-r--r-- | fs/compat.c | 5 | ||||
-rw-r--r-- | fs/exec.c | 4 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 4 | ||||
-rw-r--r-- | fs/notify/dnotify/dnotify.c | 8 | ||||
-rw-r--r-- | fs/notify/fsnotify.c | 16 | ||||
-rw-r--r-- | fs/notify/group.c | 50 | ||||
-rw-r--r-- | fs/notify/inode_mark.c | 18 | ||||
-rw-r--r-- | fs/notify/inotify/inotify_fsnotify.c | 59 | ||||
-rw-r--r-- | fs/notify/inotify/inotify_user.c | 19 | ||||
-rw-r--r-- | fs/notify/notification.c | 161 | ||||
-rw-r--r-- | fs/open.c | 2 | ||||
-rw-r--r-- | fs/read_write.c | 8 |
12 files changed, 197 insertions, 157 deletions
diff --git a/fs/compat.c b/fs/compat.c index 94502dab972a..1465b801afde 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1177,11 +1177,10 @@ out: if (iov != iovstack) kfree(iov); if ((ret + (type == READ)) > 0) { - struct dentry *dentry = file->f_path.dentry; if (type == READ) - fsnotify_access(dentry); + fsnotify_access(file); else - fsnotify_modify(dentry); + fsnotify_modify(file); } return ret; } diff --git a/fs/exec.c b/fs/exec.c index fb4f3cdda78c..9f974080712c 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -128,7 +128,7 @@ SYSCALL_DEFINE1(uselib, const char __user *, library) if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) goto exit; - fsnotify_open(file->f_path.dentry); + fsnotify_open(file); error = -ENOEXEC; if(file->f_op) { @@ -663,7 +663,7 @@ struct file *open_exec(const char *name) if (file->f_path.mnt->mnt_flags & MNT_NOEXEC) goto exit; - fsnotify_open(file->f_path.dentry); + fsnotify_open(file); err = deny_write_access(file); if (err) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 23341c1063bc..5c8f67eb049d 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -948,7 +948,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, nfsdstats.io_read += host_err; *count = host_err; err = 0; - fsnotify_access(file->f_path.dentry); + fsnotify_access(file); } else err = nfserrno(host_err); out: @@ -1059,7 +1059,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, goto out_nfserr; *cnt = host_err; nfsdstats.io_write += host_err; - fsnotify_modify(file->f_path.dentry); + fsnotify_modify(file); /* clear setuid/setgid flag after write */ if (inode->i_mode & (S_ISUID | S_ISGID)) diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c index 828a889be909..8c568a09138e 100644 --- a/fs/notify/dnotify/dnotify.c +++ b/fs/notify/dnotify/dnotify.c @@ -132,7 +132,8 @@ static int dnotify_handle_event(struct fsnotify_group *group, * userspace notification for that pair. */ static bool dnotify_should_send_event(struct fsnotify_group *group, - struct inode *inode, __u32 mask) + struct inode *inode, __u32 mask, + void *data, int data_type) { struct fsnotify_mark_entry *entry; bool send; @@ -361,7 +362,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg) dnentry = container_of(entry, struct dnotify_mark_entry, fsn_entry); spin_lock(&entry->lock); } else { - fsnotify_add_mark(new_entry, dnotify_group, inode); + fsnotify_add_mark(new_entry, dnotify_group, inode, 0); spin_lock(&new_entry->lock); entry = new_entry; dnentry = new_dnentry; @@ -431,8 +432,7 @@ static int __init dnotify_init(void) dnotify_struct_cache = KMEM_CACHE(dnotify_struct, SLAB_PANIC); dnotify_mark_entry_cache = KMEM_CACHE(dnotify_mark_entry, SLAB_PANIC); - dnotify_group = fsnotify_obtain_group(DNOTIFY_GROUP_NUM, - 0, &dnotify_fsnotify_ops); + dnotify_group = fsnotify_obtain_group(0, &dnotify_fsnotify_ops); if (IS_ERR(dnotify_group)) panic("unable to allocate fsnotify group for dnotify\n"); return 0; diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 037e878e03fc..d4b02729598e 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -77,13 +77,16 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode) } /* Notify this dentry's parent about a child's events. */ -void __fsnotify_parent(struct dentry *dentry, __u32 mask) +void __fsnotify_parent(struct file *file, struct dentry *dentry, __u32 mask) { struct dentry *parent; struct inode *p_inode; bool send = false; bool should_update_children = false; + if (file) + dentry = file->f_path.dentry; + if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) return; @@ -114,8 +117,12 @@ void __fsnotify_parent(struct dentry *dentry, __u32 mask) * specifies these are events which came from a child. */ mask |= FS_EVENT_ON_CHILD; - fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, - dentry->d_name.name, 0); + 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, + dentry->d_name.name, 0); dput(parent); } @@ -156,7 +163,8 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const idx = srcu_read_lock(&fsnotify_grp_srcu); list_for_each_entry_rcu(group, &fsnotify_groups, group_list) { if (test_mask & group->mask) { - if (!group->ops->should_send_event(group, to_tell, mask)) + if (!group->ops->should_send_event(group, to_tell, mask, + data, data_is)) continue; if (!event) { event = fsnotify_create_event(to_tell, mask, data, diff --git a/fs/notify/group.c b/fs/notify/group.c index 0e1677144bc5..62fb8961a57b 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c @@ -78,15 +78,6 @@ void fsnotify_recalc_group_mask(struct fsnotify_group *group) } /* - * Take a reference to a group so things found under the fsnotify_grp_mutex - * can't get freed under us - */ -static void fsnotify_get_group(struct fsnotify_group *group) -{ - atomic_inc(&group->refcnt); -} - -/* * Final freeing of a group */ void fsnotify_final_destroy_group(struct fsnotify_group *group) @@ -171,50 +162,23 @@ void fsnotify_put_group(struct fsnotify_group *group) } /* - * Simply run the fsnotify_groups list and find a group which matches - * the given parameters. If a group is found we take a reference to that - * group. - */ -static struct fsnotify_group *fsnotify_find_group(unsigned int group_num, __u32 mask, - const struct fsnotify_ops *ops) -{ - struct fsnotify_group *group_iter; - struct fsnotify_group *group = NULL; - - BUG_ON(!mutex_is_locked(&fsnotify_grp_mutex)); - - list_for_each_entry_rcu(group_iter, &fsnotify_groups, group_list) { - if (group_iter->group_num == group_num) { - if ((group_iter->mask == mask) && - (group_iter->ops == ops)) { - fsnotify_get_group(group_iter); - group = group_iter; - } else - group = ERR_PTR(-EEXIST); - } - } - return group; -} - -/* * Either finds an existing group which matches the group_num, mask, and ops or * creates a new group and adds it to the global group list. In either case we * take a reference for the group returned. */ -struct fsnotify_group *fsnotify_obtain_group(unsigned int group_num, __u32 mask, +struct fsnotify_group *fsnotify_obtain_group(__u32 mask, const struct fsnotify_ops *ops) { - struct fsnotify_group *group, *tgroup; + struct fsnotify_group *group; /* very low use, simpler locking if we just always alloc */ - group = kmalloc(sizeof(struct fsnotify_group), GFP_KERNEL); + group = kzalloc(sizeof(struct fsnotify_group), GFP_KERNEL); if (!group) return ERR_PTR(-ENOMEM); atomic_set(&group->refcnt, 1); group->on_group_list = 0; - group->group_num = group_num; group->mask = mask; mutex_init(&group->notification_mutex); @@ -230,14 +194,6 @@ struct fsnotify_group *fsnotify_obtain_group(unsigned int group_num, __u32 mask, group->ops = ops; mutex_lock(&fsnotify_grp_mutex); - tgroup = fsnotify_find_group(group_num, mask, ops); - if (tgroup) { - /* group already exists */ - mutex_unlock(&fsnotify_grp_mutex); - /* destroy the new one we made */ - fsnotify_put_group(group); - return tgroup; - } /* group not found, add a new one */ list_add_rcu(&group->group_list, &fsnotify_groups); diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c index c8a07c65482b..3f3261b11295 100644 --- a/fs/notify/inode_mark.c +++ b/fs/notify/inode_mark.c @@ -283,12 +283,20 @@ struct fsnotify_mark_entry *fsnotify_find_mark_entry(struct fsnotify_group *grou return NULL; } +void fsnotify_duplicate_mark(struct fsnotify_mark_entry *new, struct fsnotify_mark_entry *old) +{ + assert_spin_locked(&old->lock); + new->inode = old->inode; + new->group = old->group; + new->mask = old->mask; + new->free_mark = old->free_mark; +} + /* * Nothing fancy, just initialize lists and locks and counters. */ void fsnotify_init_mark(struct fsnotify_mark_entry *entry, void (*free_mark)(struct fsnotify_mark_entry *entry)) - { spin_lock_init(&entry->lock); atomic_set(&entry->refcnt, 1); @@ -305,9 +313,10 @@ void fsnotify_init_mark(struct fsnotify_mark_entry *entry, * event types should be delivered to which group and for which inodes. */ int fsnotify_add_mark(struct fsnotify_mark_entry *entry, - struct fsnotify_group *group, struct inode *inode) + struct fsnotify_group *group, struct inode *inode, + int allow_dups) { - struct fsnotify_mark_entry *lentry; + struct fsnotify_mark_entry *lentry = NULL; int ret = 0; inode = igrab(inode); @@ -327,7 +336,8 @@ int fsnotify_add_mark(struct fsnotify_mark_entry *entry, entry->group = group; entry->inode = inode; - lentry = fsnotify_find_mark_entry(group, inode); + if (!allow_dups) + lentry = fsnotify_find_mark_entry(group, inode); if (!lentry) { hlist_add_head(&entry->i_list, &inode->i_fsnotify_mark_entries); list_add(&entry->g_list, &group->mark_entries); diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index c9ee67b442e1..027e07bf30ce 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -31,6 +31,60 @@ #include "inotify.h" +/* + * Check if 2 events contain the same information. We do not compare private data + * but at this moment that isn't a problem for any know fsnotify listeners. + */ +static bool event_compare(struct fsnotify_event *old, struct fsnotify_event *new) +{ + if ((old->mask == new->mask) && + (old->to_tell == new->to_tell) && + (old->data_type == new->data_type) && + (old->name_len == new->name_len)) { + switch (old->data_type) { + case (FSNOTIFY_EVENT_INODE): + /* remember, after old was put on the wait_q we aren't + * allowed to look at the inode any more, only thing + * left to check was if the file_name is the same */ + if (old->name_len && + !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)) + return true; + break; + case (FSNOTIFY_EVENT_NONE): + if (old->mask & FS_Q_OVERFLOW) + return true; + else if (old->mask & FS_IN_IGNORED) + return false; + return true; + }; + } + return false; +} + +static int inotify_merge(struct list_head *list, struct fsnotify_event *event) +{ + struct fsnotify_event_holder *last_holder; + struct fsnotify_event *last_event; + int ret = 0; + + /* and the list better be locked by something too */ + spin_lock(&event->lock); + + last_holder = list_entry(list->prev, struct fsnotify_event_holder, event_list); + last_event = last_holder->event; + if (event_compare(last_event, event)) + ret = -EEXIST; + + spin_unlock(&event->lock); + + return ret; +} + static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *event) { struct fsnotify_mark_entry *entry; @@ -61,7 +115,7 @@ static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_ev fsn_event_priv->group = group; event_priv->wd = wd; - ret = fsnotify_add_notify_event(group, event, fsn_event_priv); + ret = fsnotify_add_notify_event(group, event, fsn_event_priv, inotify_merge); if (ret) { inotify_free_event_priv(fsn_event_priv); /* EEXIST says we tail matched, EOVERFLOW isn't something @@ -85,7 +139,8 @@ static void inotify_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnot inotify_ignored_and_remove_idr(entry, group); } -static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode, __u32 mask) +static bool inotify_should_send_event(struct fsnotify_group *group, struct inode *inode, + __u32 mask, void *data, int data_type) { struct fsnotify_mark_entry *entry; bool send; diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index dcd2040d330c..0728e83eeff8 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -55,12 +55,6 @@ int inotify_max_user_watches __read_mostly; static struct kmem_cache *inotify_inode_mark_cachep __read_mostly; struct kmem_cache *event_priv_cachep __read_mostly; -/* - * When inotify registers a new group it increments this and uses that - * value as an offset to set the fsnotify group "name" and priority. - */ -static atomic_t inotify_grp_num; - #ifdef CONFIG_SYSCTL #include <linux/sysctl.h> @@ -441,7 +435,7 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark_entry *entry, fsn_event_priv->group = group; event_priv->wd = ientry->wd; - ret = fsnotify_add_notify_event(group, ignored_event, fsn_event_priv); + ret = fsnotify_add_notify_event(group, ignored_event, fsn_event_priv, NULL); if (ret) inotify_free_event_priv(fsn_event_priv); @@ -459,7 +453,9 @@ skip_send_ignore: /* ding dong the mark is dead */ static void inotify_free_mark(struct fsnotify_mark_entry *entry) { - struct inotify_inode_mark_entry *ientry = (struct inotify_inode_mark_entry *)entry; + struct inotify_inode_mark_entry *ientry; + + ientry = container_of(entry, struct inotify_inode_mark_entry, fsn_entry); kmem_cache_free(inotify_inode_mark_cachep, ientry); } @@ -572,7 +568,7 @@ retry: fsnotify_get_mark(&tmp_ientry->fsn_entry); /* we are on the idr, now get on the inode */ - ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode); + ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode, 0); if (ret) { /* we failed to get on the inode, get off the idr */ inotify_remove_from_idr(group, tmp_ientry); @@ -626,11 +622,8 @@ retry: static struct fsnotify_group *inotify_new_group(struct user_struct *user, unsigned int max_events) { struct fsnotify_group *group; - unsigned int grp_num; - /* fsnotify_obtain_group took a reference to group, we put this when we kill the file in the end */ - grp_num = (INOTIFY_GROUP_NUM - atomic_inc_return(&inotify_grp_num)); - group = fsnotify_obtain_group(grp_num, 0, &inotify_fsnotify_ops); + group = fsnotify_obtain_group(0, &inotify_fsnotify_ops); if (IS_ERR(group)) return group; diff --git a/fs/notify/notification.c b/fs/notify/notification.c index 3816d5750dd5..dafd0b7687b8 100644 --- a/fs/notify/notification.c +++ b/fs/notify/notification.c @@ -56,7 +56,7 @@ static struct kmem_cache *fsnotify_event_holder_cachep; * it is needed. It's refcnt is set 1 at kernel init time and will never * get set to 0 so it will never get 'freed' */ -static struct fsnotify_event q_overflow_event; +static struct fsnotify_event *q_overflow_event; static atomic_t fsnotify_sync_cookie = ATOMIC_INIT(0); /** @@ -104,7 +104,8 @@ struct fsnotify_event_holder *fsnotify_alloc_event_holder(void) void fsnotify_destroy_event_holder(struct fsnotify_event_holder *holder) { - kmem_cache_free(fsnotify_event_holder_cachep, holder); + if (holder) + kmem_cache_free(fsnotify_event_holder_cachep, holder); } /* @@ -129,53 +130,17 @@ struct fsnotify_event_private_data *fsnotify_remove_priv_from_event(struct fsnot } /* - * Check if 2 events contain the same information. We do not compare private data - * but at this moment that isn't a problem for any know fsnotify listeners. - */ -static bool event_compare(struct fsnotify_event *old, struct fsnotify_event *new) -{ - if ((old->mask == new->mask) && - (old->to_tell == new->to_tell) && - (old->data_type == new->data_type) && - (old->name_len == new->name_len)) { - switch (old->data_type) { - case (FSNOTIFY_EVENT_INODE): - /* remember, after old was put on the wait_q we aren't - * allowed to look at the inode any more, only thing - * left to check was if the file_name is the same */ - if (old->name_len && - !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)) - return true; - break; - case (FSNOTIFY_EVENT_NONE): - if (old->mask & FS_Q_OVERFLOW) - return true; - else if (old->mask & FS_IN_IGNORED) - return false; - return false; - }; - } - return false; -} - -/* * Add an event to the group notification queue. The group can later pull this * event off the queue to deal with. If the event is successfully added to the * group's notification queue, a reference is taken on event. */ int fsnotify_add_notify_event(struct fsnotify_group *group, struct fsnotify_event *event, - struct fsnotify_event_private_data *priv) + struct fsnotify_event_private_data *priv, + int (*merge)(struct list_head *, struct fsnotify_event *)) { struct fsnotify_event_holder *holder = NULL; struct list_head *list = &group->notification_list; - struct fsnotify_event_holder *last_holder; - struct fsnotify_event *last_event; - int ret = 0; + int rc = 0; /* * There is one fsnotify_event_holder embedded inside each fsnotify_event. @@ -195,12 +160,24 @@ alloc_holder: mutex_lock(&group->notification_mutex); if (group->q_len >= group->max_events) { - event = &q_overflow_event; - ret = -EOVERFLOW; + event = q_overflow_event; + rc = -EOVERFLOW; /* sorry, no private data on the overflow event */ priv = NULL; } + if (!list_empty(list) && merge) { + int ret; + + ret = merge(list, event); + if (ret) { + mutex_unlock(&group->notification_mutex); + if (holder != &event->holder) + fsnotify_destroy_event_holder(holder); + return ret; + } + } + spin_lock(&event->lock); if (list_empty(&event->holder.event_list)) { @@ -215,18 +192,6 @@ alloc_holder: goto alloc_holder; } - if (!list_empty(list)) { - last_holder = list_entry(list->prev, struct fsnotify_event_holder, event_list); - last_event = last_holder->event; - if (event_compare(last_event, event)) { - spin_unlock(&event->lock); - mutex_unlock(&group->notification_mutex); - if (holder != &event->holder) - fsnotify_destroy_event_holder(holder); - return -EEXIST; - } - } - group->q_len++; holder->event = event; @@ -238,7 +203,7 @@ alloc_holder: mutex_unlock(&group->notification_mutex); wake_up(&group->notification_waitq); - return ret; + return rc; } /* @@ -314,25 +279,77 @@ void fsnotify_flush_notify(struct fsnotify_group *group) static void initialize_event(struct fsnotify_event *event) { - event->holder.event = NULL; INIT_LIST_HEAD(&event->holder.event_list); atomic_set(&event->refcnt, 1); spin_lock_init(&event->lock); - event->path.dentry = NULL; - event->path.mnt = NULL; - event->inode = NULL; - event->data_type = FSNOTIFY_EVENT_NONE; - INIT_LIST_HEAD(&event->private_data_list); +} + +/* + * Caller damn well better be holding whatever mutex is protecting the + * old_holder->event_list and the new_event must be a clean event which + * cannot be found anywhere else in the kernel. + */ +int fsnotify_replace_event(struct fsnotify_event_holder *old_holder, + struct fsnotify_event *new_event) +{ + struct fsnotify_event *old_event = old_holder->event; + struct fsnotify_event_holder *new_holder = &new_event->holder; - event->to_tell = NULL; + enum event_spinlock_class { + SPINLOCK_OLD, + SPINLOCK_NEW, + }; - event->file_name = NULL; - event->name_len = 0; + /* + * if the new_event's embedded holder is in use someone + * screwed up and didn't give us a clean new event. + */ + BUG_ON(!list_empty(&new_holder->event_list)); + + spin_lock_nested(&old_event->lock, SPINLOCK_OLD); + spin_lock_nested(&new_event->lock, SPINLOCK_NEW); + + new_holder->event = new_event; + list_replace_init(&old_holder->event_list, &new_holder->event_list); + + spin_unlock(&new_event->lock); + spin_unlock(&old_event->lock); + + /* event == holder means we are referenced through the in event holder */ + if (old_holder != &old_event->holder) + fsnotify_destroy_event_holder(old_holder); + + fsnotify_get_event(new_event); /* on the list take reference */ + fsnotify_put_event(old_event); /* off the list, drop reference */ + + return 0; +} + +struct fsnotify_event *fsnotify_clone_event(struct fsnotify_event *old_event) +{ + struct fsnotify_event *event; - event->sync_cookie = 0; + event = kmem_cache_alloc(fsnotify_event_cachep, GFP_KERNEL); + if (!event) + return NULL; + + memcpy(event, old_event, sizeof(*event)); + initialize_event(event); + + if (event->name_len) { + event->file_name = kstrdup(old_event->file_name, GFP_KERNEL); + if (!event->file_name) { + kmem_cache_free(fsnotify_event_cachep, event); + return NULL; + } + } + if (event->data_type == FSNOTIFY_EVENT_PATH) + path_get(&event->path); + + return event; } /* @@ -353,7 +370,7 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, { struct fsnotify_event *event; - event = kmem_cache_alloc(fsnotify_event_cachep, gfp); + event = kmem_cache_zalloc(fsnotify_event_cachep, gfp); if (!event) return NULL; @@ -370,6 +387,7 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, event->sync_cookie = cookie; event->to_tell = to_tell; + event->data_type = data_type; switch (data_type) { case FSNOTIFY_EVENT_FILE: { @@ -386,12 +404,10 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, event->path.dentry = path->dentry; event->path.mnt = path->mnt; path_get(&event->path); - event->data_type = FSNOTIFY_EVENT_PATH; break; } case FSNOTIFY_EVENT_INODE: event->inode = data; - event->data_type = FSNOTIFY_EVENT_INODE; break; case FSNOTIFY_EVENT_NONE: event->inode = NULL; @@ -412,8 +428,11 @@ __init int fsnotify_notification_init(void) fsnotify_event_cachep = KMEM_CACHE(fsnotify_event, SLAB_PANIC); fsnotify_event_holder_cachep = KMEM_CACHE(fsnotify_event_holder, SLAB_PANIC); - initialize_event(&q_overflow_event); - q_overflow_event.mask = FS_Q_OVERFLOW; + q_overflow_event = fsnotify_create_event(NULL, FS_Q_OVERFLOW, NULL, + FSNOTIFY_EVENT_NONE, NULL, 0, + GFP_KERNEL); + if (!q_overflow_event) + panic("unable to allocate fsnotify q_overflow_event\n"); return 0; } diff --git a/fs/open.c b/fs/open.c index 40d1fa25f5aa..6f37e62b6ea6 100644 --- a/fs/open.c +++ b/fs/open.c @@ -1040,7 +1040,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode) put_unused_fd(fd); fd = PTR_ERR(f); } else { - fsnotify_open(f->f_path.dentry); + fsnotify_open(f); fd_install(fd, f); } } diff --git a/fs/read_write.c b/fs/read_write.c index 6c8c55dec2bc..c7479e91848f 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -293,7 +293,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) else ret = do_sync_read(file, buf, count, pos); if (ret > 0) { - fsnotify_access(file->f_path.dentry); + fsnotify_access(file); add_rchar(current, ret); } inc_syscr(current); @@ -348,7 +348,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_ else ret = do_sync_write(file, buf, count, pos); if (ret > 0) { - fsnotify_modify(file->f_path.dentry); + fsnotify_modify(file); add_wchar(current, ret); } inc_syscw(current); @@ -656,9 +656,9 @@ out: kfree(iov); if ((ret + (type == READ)) > 0) { if (type == READ) - fsnotify_access(file->f_path.dentry); + fsnotify_access(file); else - fsnotify_modify(file->f_path.dentry); + fsnotify_modify(file); } return ret; } |