]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - fs/notify/notification.c
Merge branch 'acpica' into release
[mv-sheeva.git] / fs / notify / notification.c
index 066f1f988bacc001f44ba8b4d93a858dfc3567c2..f39260f8f8656e42feac01e728497cd05650d881 100644 (file)
@@ -87,12 +87,15 @@ void fsnotify_put_event(struct fsnotify_event *event)
                return;
 
        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);
 
                BUG_ON(!list_empty(&event->private_data_list));
 
                kfree(event->file_name);
+               put_pid(event->tgid);
                kmem_cache_free(fsnotify_event_cachep, event);
        }
 }
@@ -134,13 +137,16 @@ struct fsnotify_event_private_data *fsnotify_remove_priv_from_event(struct fsnot
  * 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,
-                             int (*merge)(struct list_head *, struct fsnotify_event *))
+struct fsnotify_event *fsnotify_add_notify_event(struct fsnotify_group *group, struct fsnotify_event *event,
+                                                struct fsnotify_event_private_data *priv,
+                                                struct fsnotify_event *(*merge)(struct list_head *,
+                                                                                struct fsnotify_event *))
 {
+       struct fsnotify_event *return_event = NULL;
        struct fsnotify_event_holder *holder = NULL;
        struct list_head *list = &group->notification_list;
-       int rc = 0;
+
+       pr_debug("%s: group=%p event=%p priv=%p\n", __func__, group, event, priv);
 
        /*
         * There is one fsnotify_event_holder embedded inside each fsnotify_event.
@@ -154,27 +160,37 @@ int fsnotify_add_notify_event(struct fsnotify_group *group, struct fsnotify_even
 alloc_holder:
                holder = fsnotify_alloc_event_holder();
                if (!holder)
-                       return -ENOMEM;
+                       return ERR_PTR(-ENOMEM);
        }
 
        mutex_lock(&group->notification_mutex);
 
        if (group->q_len >= group->max_events) {
                event = q_overflow_event;
-               rc = -EOVERFLOW;
+
+               /*
+                * we need to return the overflow event
+                * which means we need a ref
+                */
+               fsnotify_get_event(event);
+               return_event = event;
+
                /* sorry, no private data on the overflow event */
                priv = NULL;
        }
 
        if (!list_empty(list) && merge) {
-               int ret;
+               struct fsnotify_event *tmp;
 
-               ret = merge(list, event);
-               if (ret) {
+               tmp = merge(list, event);
+               if (tmp) {
                        mutex_unlock(&group->notification_mutex);
+
+                       if (return_event)
+                               fsnotify_put_event(return_event);
                        if (holder != &event->holder)
                                fsnotify_destroy_event_holder(holder);
-                       return ret;
+                       return tmp;
                }
        }
 
@@ -189,6 +205,12 @@ alloc_holder:
                 * event holder was used, go back and get a new one */
                spin_unlock(&event->lock);
                mutex_unlock(&group->notification_mutex);
+
+               if (return_event) {
+                       fsnotify_put_event(return_event);
+                       return_event = NULL;
+               }
+
                goto alloc_holder;
        }
 
@@ -203,7 +225,7 @@ alloc_holder:
        mutex_unlock(&group->notification_mutex);
 
        wake_up(&group->notification_waitq);
-       return rc;
+       return return_event;
 }
 
 /*
@@ -218,6 +240,8 @@ struct fsnotify_event *fsnotify_remove_notify_event(struct fsnotify_group *group
 
        BUG_ON(!mutex_is_locked(&group->notification_mutex));
 
+       pr_debug("%s: group=%p\n", __func__, group);
+
        holder = list_first_entry(&group->notification_list, struct fsnotify_event_holder, event_list);
 
        event = holder->event;
@@ -303,6 +327,8 @@ int fsnotify_replace_event(struct fsnotify_event_holder *old_holder,
                SPINLOCK_NEW,
        };
 
+       pr_debug("%s: old_event=%p new_event=%p\n", __func__, old_event, new_event);
+
        /*
         * if the new_event's embedded holder is in use someone
         * screwed up and didn't give us a clean new event.
@@ -336,6 +362,8 @@ struct fsnotify_event *fsnotify_clone_event(struct fsnotify_event *old_event)
        if (!event)
                return NULL;
 
+       pr_debug("%s: old_event=%p new_event=%p\n", __func__, old_event, event);
+
        memcpy(event, old_event, sizeof(*event));
        initialize_event(event);
 
@@ -346,6 +374,7 @@ struct fsnotify_event *fsnotify_clone_event(struct fsnotify_event *old_event)
                        return NULL;
                }
        }
+       event->tgid = get_pid(old_event->tgid);
        if (event->data_type == FSNOTIFY_EVENT_PATH)
                path_get(&event->path);
 
@@ -365,8 +394,8 @@ struct fsnotify_event *fsnotify_clone_event(struct fsnotify_event *old_event)
  * @name the filename, if available
  */
 struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask, void *data,
-                                            int data_type, const char *name, u32 cookie,
-                                            gfp_t gfp)
+                                            int data_type, const unsigned char *name,
+                                            u32 cookie, gfp_t gfp)
 {
        struct fsnotify_event *event;
 
@@ -374,6 +403,9 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
        if (!event)
                return NULL;
 
+       pr_debug("%s: event=%p to_tell=%p mask=%x data=%p data_type=%d\n",
+                __func__, event, to_tell, mask, data, data_type);
+
        initialize_event(event);
 
        if (name) {
@@ -385,6 +417,7 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
                event->name_len = strlen(event->file_name);
        }
 
+       event->tgid = get_pid(task_tgid(current));
        event->sync_cookie = cookie;
        event->to_tell = to_tell;
        event->data_type = data_type;