aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify/notification.c
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2009-12-17 21:24:21 -0500
committerEric Paris <eparis@redhat.com>2010-07-28 09:58:49 -0400
commitb4e4e1407312ae5a267ed7d716e6d4e7120a8430 (patch)
tree2953d8885e3224955f1a5aca7c129709b26a059d /fs/notify/notification.c
parent74766bbfa99adf8cb8119df6121851edba21c9d9 (diff)
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>
Diffstat (limited to 'fs/notify/notification.c')
-rw-r--r--fs/notify/notification.c29
1 files changed, 25 insertions, 4 deletions
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)
284 284
285 spin_lock_init(&event->lock); 285 spin_lock_init(&event->lock);
286 286
287 event->data_type = FSNOTIFY_EVENT_NONE;
288
289 INIT_LIST_HEAD(&event->private_data_list); 287 INIT_LIST_HEAD(&event->private_data_list);
290} 288}
291 289
290struct fsnotify_event *fsnotify_clone_event(struct fsnotify_event *old_event)
291{
292 struct fsnotify_event *event;
293
294 event = kmem_cache_alloc(fsnotify_event_cachep, GFP_KERNEL);
295 if (!event)
296 return NULL;
297
298 memcpy(event, old_event, sizeof(*event));
299 initialize_event(event);
300
301 if (event->name_len) {
302 event->file_name = kstrdup(old_event->file_name, GFP_KERNEL);
303 if (!event->file_name) {
304 kmem_cache_free(fsnotify_event_cachep, event);
305 return NULL;
306 }
307 }
308 if (event->data_type == FSNOTIFY_EVENT_PATH)
309 path_get(&event->path);
310
311 return event;
312}
313
292/* 314/*
293 * fsnotify_create_event - Allocate a new event which will be sent to each 315 * fsnotify_create_event - Allocate a new event which will be sent to each
294 * group's handle_event function if the group was interested in this 316 * 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,
324 346
325 event->sync_cookie = cookie; 347 event->sync_cookie = cookie;
326 event->to_tell = to_tell; 348 event->to_tell = to_tell;
349 event->data_type = data_type;
327 350
328 switch (data_type) { 351 switch (data_type) {
329 case FSNOTIFY_EVENT_FILE: { 352 case FSNOTIFY_EVENT_FILE: {
@@ -340,12 +363,10 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
340 event->path.dentry = path->dentry; 363 event->path.dentry = path->dentry;
341 event->path.mnt = path->mnt; 364 event->path.mnt = path->mnt;
342 path_get(&event->path); 365 path_get(&event->path);
343 event->data_type = FSNOTIFY_EVENT_PATH;
344 break; 366 break;
345 } 367 }
346 case FSNOTIFY_EVENT_INODE: 368 case FSNOTIFY_EVENT_INODE:
347 event->inode = data; 369 event->inode = data;
348 event->data_type = FSNOTIFY_EVENT_INODE;
349 break; 370 break;
350 case FSNOTIFY_EVENT_NONE: 371 case FSNOTIFY_EVENT_NONE:
351 event->inode = NULL; 372 event->inode = NULL;