diff --git a/fs/notify/notification.c b/fs/notify/notification.c index 6dc96b35e4a7..bc9470c7ece7 100644 --- a/fs/notify/notification.c +++ b/fs/notify/notification.c @@ -284,11 +284,33 @@ static void initialize_event(struct fsnotify_event *event) spin_lock_init(&event->lock); - event->data_type = FSNOTIFY_EVENT_NONE; - INIT_LIST_HEAD(&event->private_data_list); } +struct fsnotify_event *fsnotify_clone_event(struct fsnotify_event *old_event) +{ + struct fsnotify_event *event; + + 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; +} + /* * fsnotify_create_event - Allocate a new event which will be sent to each * group's handle_event function if the group was interested in this @@ -324,6 +346,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: { @@ -340,12 +363,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; diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 25789d45fad8..3a7fff235539 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -363,6 +363,9 @@ extern struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 void *data, int data_is, const char *name, u32 cookie, gfp_t gfp); +/* fanotify likes to change events after they are on lists... */ +extern struct fsnotify_event *fsnotify_clone_event(struct fsnotify_event *old_event); + #else static inline void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,