summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2014-12-05 15:38:45 +0000
committerJeremy Allison <jra@samba.org>2014-12-05 21:01:54 +0100
commitabf867da764b60e94c43ab9ec1d5338ac99ec18d (patch)
tree2567e7be76555eb8128876af6d24e6306269d687
parentd6e2db6f52fa26ae3c044ff56ebf814313ca4eb8 (diff)
downloadsamba-abf867da764b60e94c43ab9ec1d5338ac99ec18d.tar.gz
samba-abf867da764b60e94c43ab9ec1d5338ac99ec18d.tar.xz
samba-abf867da764b60e94c43ab9ec1d5338ac99ec18d.zip
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@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org> Autobuild-User(master): Jeremy Allison <jra@samba.org> Autobuild-Date(master): Fri Dec 5 21:01:54 CET 2014 on sn-devel-104
-rw-r--r--source3/smbd/notify_inotify.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/source3/smbd/notify_inotify.c b/source3/smbd/notify_inotify.c
index efb659f7c0..1fcd8ecd73 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;
}