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);
* 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 *,
- void **arg),
- void **arg)
+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.
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, arg);
- 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;
}
}
* 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;
}
mutex_unlock(&group->notification_mutex);
wake_up(&group->notification_waitq);
- return rc;
+ return return_event;
}
/*
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;
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.
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);
* @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;
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) {