[PATCH] inotify: Properly handle cross-dir renames

Volker Lendecke Volker.Lendecke at SerNet.DE
Fri Dec 5 08:51:36 MST 2014


Hi!

I'd appreciate review&push!

Thanks,

Volker

-- 
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
From 9f12b349024837258e244caccbd1d9ae50593469 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Fri, 5 Dec 2014 15:38:45 +0000
Subject: [PATCH] inotify: Properly handle cross-dir renames

When watching two subdirectories with inotify and a file is moved between both,
we get a IN_MOVED_FROM for the source watch and a IN_MOVED_TO for the
destination watch. Without this patch we create a NOTIFY_ACTION_OLD_NAME for
the old directory. We hold this back in notify_fsp, expecting the NEW_NAME
immediately after it. In the cross-directory rename case this does not work,
we'll not get the NEW_NAME, there is no NEW_NAME in that directory.

This patch changes us to create NOTIFY_ACTION_REMOVED and NOTIFY_ACTION_ADDED
in this case. Not sure this is right, but at least it is better than before: We
get something at all.

This is more likely to happen with the notifyd approach, as there we
inotify-watch many subdirectories from one process. Without nootifyd you had to
have two explorer windows open and do a nfs or local mv between those two
directories to find this.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/smbd/notify_inotify.c |   10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/source3/smbd/notify_inotify.c b/source3/smbd/notify_inotify.c
index efb659f..1fcd8ec 100644
--- a/source3/smbd/notify_inotify.c
+++ b/source3/smbd/notify_inotify.c
@@ -118,6 +118,7 @@ static bool filter_match(struct inotify_watch_context *w,
 */
 static void inotify_dispatch(struct inotify_private *in, 
 			     struct inotify_event *e, 
+			     int prev_wd,
 			     uint32_t prev_cookie,
 			     struct inotify_event *e2)
 {
@@ -140,13 +141,14 @@ static void inotify_dispatch(struct inotify_private *in,
 	} else if (e->mask & IN_DELETE) {
 		ne.action = NOTIFY_ACTION_REMOVED;
 	} else if (e->mask & IN_MOVED_FROM) {
-		if (e2 != NULL && e2->cookie == e->cookie) {
+		if (e2 != NULL && e2->cookie == e->cookie &&
+		    e2->wd == e->wd) {
 			ne.action = NOTIFY_ACTION_OLD_NAME;
 		} else {
 			ne.action = NOTIFY_ACTION_REMOVED;
 		}
 	} else if (e->mask & IN_MOVED_TO) {
-		if (e->cookie == prev_cookie) {
+		if ((e->cookie == prev_cookie) && (e->wd == prev_wd)) {
 			ne.action = NOTIFY_ACTION_NEW_NAME;
 		} else {
 			ne.action = NOTIFY_ACTION_ADDED;
@@ -198,6 +200,7 @@ static void inotify_handler(struct tevent_context *ev, struct tevent_fd *fde,
 	int bufsize = 0;
 	struct inotify_event *e0, *e;
 	uint32_t prev_cookie=0;
+	int prev_wd = -1;
 	NTSTATUS status;
 
 	/*
@@ -234,7 +237,8 @@ static void inotify_handler(struct tevent_context *ev, struct tevent_fd *fde,
 		if (bufsize >= sizeof(*e)) {
 			e2 = (struct inotify_event *)(e->len + sizeof(*e) + (char *)e);
 		}
-		inotify_dispatch(in, e, prev_cookie, e2);
+		inotify_dispatch(in, e, prev_wd, prev_cookie, e2);
+		prev_wd = e->wd;
 		prev_cookie = e->cookie;
 		e = e2;
 	}
-- 
1.7.9.5



More information about the samba-technical mailing list