linux-next: manual merge of the fsnotify tree with Linus' tree

From: Stephen Rothwell
Date: Tue Aug 18 2009 - 01:19:07 EST


Hi Eric,

Today's linux-next merge of the fsnotify tree got conflicts in
fs/notify/inotify/inotify_fsnotify.c, fs/notify/inotify/inotify_user.c
and fs/notify/notification.c between commits
eef3a116be11d35396efb2a8cc7345fd3221e294 ("notify: unused event private
race") and cd94c8bbef8d4b796a7ed4c551355a334604fd36 ("inotify: tail drop
inotify q_overflow events") from Linus' tree and commits
7bf357aac07084acfac5f0e746aca85c42cc046e ("fsnotify: use
fsnotify_create_event to allocate the q_overflow event"),
cddf930f6410692ba1db0c53753492d119b1bd55 ("fsnotify: allow notification
requests to not include private data") and
7f51531a261beb6be2071f4345482ac488eea734 ("fsnotify: per group
notification queue merge types") from the fsnotify tree.

I fixed it up as best I can (see below) and can carry the fixes as
necessary.
--
Cheers,
Stephen Rothwell sfr@xxxxxxxxxxxxxxxx

diff --cc fs/notify/inotify/inotify_fsnotify.c
index 5dcbafe,133f080..0000000
--- a/fs/notify/inotify/inotify_fsnotify.c
+++ b/fs/notify/inotify/inotify_fsnotify.c
@@@ -31,6 -31,56 +31,60 @@@

#include "inotify.h"

+ /*
+ * Check if 2 events contain the same information. We do not compare private data
+ * but at this moment that isn't a problem for any know fsnotify listeners.
+ */
+ static bool event_compare(struct fsnotify_event *old, struct fsnotify_event *new)
+ {
+ if ((old->mask == new->mask) &&
+ (old->to_tell == new->to_tell) &&
+ (old->data_type == new->data_type) &&
+ (old->name_len == new->name_len)) {
+ switch (old->data_type) {
+ case (FSNOTIFY_EVENT_INODE):
+ /* remember, after old was put on the wait_q we aren't
+ * allowed to look at the inode any more, only thing
+ * left to check was if the file_name is the same */
+ if (old->name_len &&
+ !strcmp(old->file_name, new->file_name))
+ return true;
+ break;
+ case (FSNOTIFY_EVENT_PATH):
+ if ((old->path.mnt == new->path.mnt) &&
+ (old->path.dentry == new->path.dentry))
+ return true;
+ break;
+ case (FSNOTIFY_EVENT_NONE):
++ if (old->mask & FS_Q_OVERFLOW)
++ return true;
++ else if (old->mask & FS_IN_IGNORED)
++ return false;
+ return true;
+ };
+ }
+ return false;
+ }
+
+ static int inotify_merge(struct list_head *list, struct fsnotify_event *event)
+ {
+ struct fsnotify_event_holder *last_holder;
+ struct fsnotify_event *last_event;
+ int ret = 0;
+
+ /* and the list better be locked by something too */
+ spin_lock(&event->lock);
+
+ last_holder = list_entry(list->prev, struct fsnotify_event_holder, event_list);
+ last_event = last_holder->event;
+ if (event_compare(last_event, event))
+ ret = -EEXIST;
+
+ spin_unlock(&event->lock);
+
+ return ret;
+ }
+
static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_event *event)
{
struct fsnotify_mark_entry *entry;
@@@ -61,15 -111,14 +115,15 @@@
fsn_event_priv->group = group;
event_priv->wd = wd;

- ret = fsnotify_add_notify_event(group, event, fsn_event_priv);
+ ret = fsnotify_add_notify_event(group, event, fsn_event_priv, inotify_merge);
- /* EEXIST is not an error */
- if (ret == -EEXIST)
- ret = 0;
-
- /* did event_priv get attached? */
- if (list_empty(&fsn_event_priv->event_list))
+ if (ret) {
inotify_free_event_priv(fsn_event_priv);
+ /* EEXIST says we tail matched, EOVERFLOW isn't something
+ * to report up the stack. */
+ if ((ret == -EEXIST) ||
+ (ret == -EOVERFLOW))
+ ret = 0;
+ }

/*
* If we hold the entry until after the event is on the queue
diff --cc fs/notify/inotify/inotify_user.c
index dc32ed8,d5e78f6..0000000
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@@ -405,8 -401,10 +402,8 @@@ void inotify_ignored_and_remove_idr(str
fsn_event_priv->group = group;
event_priv->wd = ientry->wd;

- ret = fsnotify_add_notify_event(group, ignored_event, fsn_event_priv);
- fsnotify_add_notify_event(group, ignored_event, fsn_event_priv, NULL);
-
- /* did the private data get added? */
- if (list_empty(&fsn_event_priv->event_list))
++ ret = fsnotify_add_notify_event(group, ignored_event, fsn_event_priv, NULL);
+ if (ret)
inotify_free_event_priv(fsn_event_priv);

skip_send_ignore:
diff --cc fs/notify/notification.c
index 3816d57,4f69b6f..0000000
--- a/fs/notify/notification.c
+++ b/fs/notify/notification.c
@@@ -173,9 -140,10 +140,7 @@@ int fsnotify_add_notify_event(struct fs
{
struct fsnotify_event_holder *holder = NULL;
struct list_head *list = &group->notification_list;
- struct fsnotify_event_holder *last_holder;
- struct fsnotify_event *last_event;
-
- /* easy to tell if priv was attached to the event */
- if (priv)
- INIT_LIST_HEAD(&priv->event_list);
+ int ret = 0;

/*
* There is one fsnotify_event_holder embedded inside each fsnotify_event.
@@@ -195,8 -163,7 +160,8 @@@ alloc_holder
mutex_lock(&group->notification_mutex);

if (group->q_len >= group->max_events) {
- event = &q_overflow_event;
+ event = q_overflow_event;
+ ret = -EOVERFLOW;
/* sorry, no private data on the overflow event */
priv = NULL;
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/