fsnotify: clone existing events
fsnotify_clone_event will take an event, clone it, and return the cloned event to the caller. Since events may be in use by multiple fsnotify groups simultaneously certain event entries (such as the mask) cannot be changed after the event was created. Since fanotify would like to merge events happening on the same file it needs a new clean event to work with so it can change any fields it wishes. Signed-off-by: Eric Paris <eparis@redhat.com>
This commit is contained in:
Родитель
74766bbfa9
Коммит
b4e4e14073
|
@ -284,11 +284,33 @@ static void initialize_event(struct fsnotify_event *event)
|
||||||
|
|
||||||
spin_lock_init(&event->lock);
|
spin_lock_init(&event->lock);
|
||||||
|
|
||||||
event->data_type = FSNOTIFY_EVENT_NONE;
|
|
||||||
|
|
||||||
INIT_LIST_HEAD(&event->private_data_list);
|
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
|
* 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
|
* 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->sync_cookie = cookie;
|
||||||
event->to_tell = to_tell;
|
event->to_tell = to_tell;
|
||||||
|
event->data_type = data_type;
|
||||||
|
|
||||||
switch (data_type) {
|
switch (data_type) {
|
||||||
case FSNOTIFY_EVENT_FILE: {
|
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.dentry = path->dentry;
|
||||||
event->path.mnt = path->mnt;
|
event->path.mnt = path->mnt;
|
||||||
path_get(&event->path);
|
path_get(&event->path);
|
||||||
event->data_type = FSNOTIFY_EVENT_PATH;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FSNOTIFY_EVENT_INODE:
|
case FSNOTIFY_EVENT_INODE:
|
||||||
event->inode = data;
|
event->inode = data;
|
||||||
event->data_type = FSNOTIFY_EVENT_INODE;
|
|
||||||
break;
|
break;
|
||||||
case FSNOTIFY_EVENT_NONE:
|
case FSNOTIFY_EVENT_NONE:
|
||||||
event->inode = NULL;
|
event->inode = NULL;
|
||||||
|
|
|
@ -363,6 +363,9 @@ extern struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32
|
||||||
void *data, int data_is, const char *name,
|
void *data, int data_is, const char *name,
|
||||||
u32 cookie, gfp_t gfp);
|
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
|
#else
|
||||||
|
|
||||||
static inline void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
|
static inline void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче