Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
This patch adds a new flag IN_SYNC - a new inotify event that is triggered whenever msync() is carried out on a mmap-ed file. Patch is tested on v2.6.37 of the Linux Kernel.
From 83edf446e92c86c738337ca4a35eab48e2f4e0eb Mon Sep 17 00:00:00 2001
From: Chinmay V S <cvs268@gmail.com>
Date: Mon, 17 Jun 2013 13:53:57 +0800
Subject: [PATCH] Add mmap-ed file support to inotify
This patch adds a new flag IN_SYNC. This is a new inotify event that is
triggered whenever msync() is carried out on a mmap-ed file.
Signed-off-by: Chinmay V S <cvs268@gmail.com>
---
fs/sync.c | 5 +++++
include/linux/fsnotify.h | 16 ++++++++++++++++
include/linux/fsnotify_backend.h | 1 +
include/linux/inotify.h | 3 ++-
mm/msync.c | 4 ++++
5 files changed, 28 insertions(+), 3 deletions(-)
diff --git a/fs/sync.c b/fs/sync.c
index ba76b96..174c2af 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -16,6 +16,7 @@
#include <linux/buffer_head.h>
#include <linux/backing-dev.h>
#include "internal.h"
+#include <linux/fsnotify.h>
#define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \
SYNC_FILE_RANGE_WAIT_AFTER)
@@ -190,6 +191,10 @@ static int do_fsync(unsigned int fd, int datasync)
ret = vfs_fsync(file, datasync);
fput(file);
}
+
+ if (!ret)
+ fsnotify_sync(file->f_path.dentry);
+
return ret;
}
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index b10bcde..ef211fb 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -224,6 +224,22 @@ static inline void fsnotify_modify(struct file *file)
}
/*
+ * fsnotify_sync - file was synced
+ */
+static inline void fsnotify_sync(struct dentry *dentry)
+{
+ struct inode *inode = dentry->d_inode;
+ u32 mask = FS_SYNC;
+
+ if (S_ISDIR(inode->i_mode))
+ mask |= FS_ISDIR;
+
+ fsnotify_parent(NULL, dentry, mask);
+ fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
+
+}
+
+/*
* fsnotify_open - file was opened
*/
static inline void fsnotify_open(struct file *file)
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 7380763..35b5cb8 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -36,6 +36,7 @@
#define FS_DELETE 0x00000200 /* Subfile was deleted */
#define FS_DELETE_SELF 0x00000400 /* Self was deleted */
#define FS_MOVE_SELF 0x00000800 /* Self was moved */
+#define FS_SYNC 0x00001000 /* File was synced */
#define FS_UNMOUNT 0x00002000 /* inode on umount fs */
#define FS_Q_OVERFLOW 0x00004000 /* Event queued overflowed */
diff --git a/include/linux/inotify.h b/include/linux/inotify.h
index d33041e..244a132 100644
--- a/include/linux/inotify.h
+++ b/include/linux/inotify.h
@@ -38,6 +38,7 @@ struct inotify_event {
#define IN_DELETE 0x00000200 /* Subfile was deleted */
#define IN_DELETE_SELF 0x00000400 /* Self was deleted */
#define IN_MOVE_SELF 0x00000800 /* Self was moved */
+#define IN_SYNC 0x00001000 /* File was synced */
/* the following are legal events. they are sent as needed to any watch */
#define IN_UNMOUNT 0x00002000 /* Backing fs was unmounted */
@@ -64,7 +65,7 @@ struct inotify_event {
#define IN_ALL_EVENTS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \
IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \
IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | \
- IN_MOVE_SELF)
+ IN_MOVE_SELF | IN_SYNC)
/* Flags for sys_inotify_init1. */
#define IN_CLOEXEC O_CLOEXEC
diff --git a/mm/msync.c b/mm/msync.c
index 632df45..b1665ac 100644
--- a/mm/msync.c
+++ b/mm/msync.c
@@ -13,6 +13,7 @@
#include <linux/file.h>
#include <linux/syscalls.h>
#include <linux/sched.h>
+#include <linux/fsnotify.h>
/*
* MS_SYNC syncs the entire file - including mappings.
@@ -83,6 +84,9 @@ SYSCALL_DEFINE3(msync, unsigned long, start, size_t, len, int, flags)
get_file(file);
up_read(&mm->mmap_sem);
error = vfs_fsync(file, 0);
+ if (!error)
+ fsnotify_sync(file->f_path.dentry);
+
fput(file);
if (error || start >= end)
goto out;
--
1.8.2

trajs commented Apr 27, 2017

Hi,
I am also looking at a similar situation.
I have two processes opening a file and mmaping it.
and thought will use an out-of-band notification.

After mmaping, When i change a value in the mmaped region, I see that
that the file modify date changes through stat commnd.

Since, stat command showed a change, I thought inotify will pick that.
Unfortunately it doesn't.
Your solution on msync is good.
In that case my application explicitly would have to call msync() which i would like to avoid.
Is there a way to get notified for a change in mmaped area without explicit call on msync?

Any thoughts or pointers would be of great help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment